from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from flower.common import ModelBase
from typing import List


class StateParameter(ModelBase):
    """StateParameter model representing parameters that can be shared across states."""
    key = models.CharField(max_length=100, unique=True, verbose_name='参数键', help_text='唯一标识符')
    value = models.CharField(max_length=200, blank=True, null=True, verbose_name='参数值')
    attachment = models.FileField(upload_to='state_parameters/', null=True, blank=True, verbose_name='附件')
    description = models.CharField(max_length=200, blank=True, verbose_name='参数描述')
    is_required = models.BooleanField(default=False, verbose_name='是否必填', help_text='标记该参数是否必须提供')
    is_image_path = models.BooleanField(default=False, verbose_name='是否图片路径', help_text='标记value字段是否为图片URL路径')

    def __str__(self):
        return self.key

    class Meta:
        verbose_name = '工艺参数'
        verbose_name_plural = '工艺参数'


class State(ModelBase):
    """State model representing a state in a stateflow diagram."""
    name = models.CharField(max_length=100, verbose_name='状态名称')
    description = models.CharField(max_length=200, blank=True, verbose_name='状态描述')
    parameters = models.ManyToManyField(
        StateParameter,
        blank=True,
        related_name='states',
        verbose_name='关联参数',
        help_text='此状态使用的工艺参数'
    )

    def __str__(self):
        return self.name

    def add_additional_params(self, params: dict):
        """Add additional parameters to the state's data field."""
        if not self.data:
            self.data = {}
        self.data.update(params)
        self.save()

    def get_additional_params(self) -> dict:
        """Retrieve additional parameters from the state's data field."""
        return self.data if self.data else {}

    def get_parameters(self, required_only: bool = False) -> List['StateParameter']:
        """
        获取状态关联的参数列表
        
        Args:
            required_only: 是否只返回必填参数，默认 False 返回所有参数
        
        Returns:
            参数列表
        """
        params = self.parameters.all()
        if required_only:
            params = params.filter(is_required=True)
        return list(params)

    class Meta:
        verbose_name = '流程节点'
        verbose_name_plural = '流程节点'


class Process(ModelBase):
    """Process model representing a stateflow process template."""
    name = models.CharField(max_length=100, verbose_name='流程名称')
    state_nodes = models.ManyToManyField(
        State,
        through='ProcessNode',
        related_name='processes',
        verbose_name='节点列表',
    )
    description = models.TextField(blank=True, verbose_name='流程描述')

    def __str__(self):
        return self.name

    def replace_nodes(self, nodes: List[State]):
        """Replace all nodes with new ordered list."""
        # 清空现有节点后按照传入顺序重建
        self.process_nodes.all().delete()
        for order, node in enumerate(nodes):
            ProcessNode.objects.create(process=self, state=node, order=order)

    def get_nodes(self) -> List[State]:
        """Retrieve the list of state nodes as State instances."""
        process_nodes = self.process_nodes.select_related('state').order_by('order', 'id')
        return [item.state for item in process_nodes]

    class Meta:
        verbose_name = '流程编排'
        verbose_name_plural = '流程编排'


class ProcessNode(ModelBase):
    """Intermediate model describing ordered relation between Process and State."""
    process = models.ForeignKey(Process, on_delete=models.CASCADE, related_name='process_nodes', verbose_name='流程')
    state = models.ForeignKey(State, on_delete=models.PROTECT, related_name='state_process_nodes', verbose_name='节点')
    order = models.PositiveIntegerField(default=0, verbose_name='顺序')

    class Meta:
        verbose_name = '流程节点关联'
        verbose_name_plural = '流程节点关联'
        ordering = ['order', 'id']
        unique_together = ('process', 'order')

    def __str__(self) -> str:
        return f"{self.process.name} -> {self.state.name} ({self.order})"


class BusinessObject(ModelBase):
    """业务对象 - 代表流程的一个实例，通过日志跟踪进度"""
    name = models.CharField(max_length=100, verbose_name='业务对象名称')
    process = models.ForeignKey(Process, on_delete=models.PROTECT, related_name='business_objects', verbose_name='关联流程')
    description = models.TextField(blank=True, verbose_name='描述')
    
    # GenericForeignKey - 关联到任意模型（可选）
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, null=True, blank=True, verbose_name='关联对象类型')
    object_id = models.PositiveIntegerField(null=True, blank=True, verbose_name='关联对象ID')
    content_object = GenericForeignKey('content_type', 'object_id')

    def __str__(self):
        return f"{self.name} ({self.process.name})"

    def get_current_state(self) -> 'State':
        """
        获取当前状态（通过services推导，行为可配置）
        
        根据 settings.STATEFLOW_CURRENT_STATE_MODE 决定返回：
        - 'NEXT' (默认): 下一个待执行的节点
        - 'LAST': 最后完成的节点
        
        注意：推荐在新代码中直接使用 get_last_completed_state() 或 get_next_pending_state() 以明确语义
        """
        from . import services
        return services.get_business_object_current_state(self)

    def get_last_completed_state(self) -> 'State':
        """
        获取最后完成的状态
        
        返回：最后一个已完成的状态节点，如果没有则返回 None
        """
        from . import services
        return services.get_last_completed_state(self)

    def get_next_pending_state(self) -> 'State':
        """
        获取下一个待执行的状态
        
        返回：下一个待执行的状态节点，如果没有则返回 None
        """
        from . import services
        return services.get_next_pending_state_simple(self)

    def get_completed_node_ids(self) -> List[int]:
        """获取已完成的节点ID列表"""
        from . import services
        return services.get_completed_node_ids(self)

    def get_current_parameters(self) -> List['StateParameter']:
        """获取当前状态的参数"""
        from . import services
        return services.get_current_state_parameters(self)

    def get_progress_percentage(self) -> float:
        """计算进度百分比"""
        from . import services
        return services.get_progress_percentage(self)

    def get_state_status(self, state: 'State') -> str:
        """获取指定状态的状态"""
        from . import services
        return services.get_business_object_state_status(self, state)

    def get_timeline(self) -> List[dict]:
        """获取状态时间线"""
        from . import services
        return services.get_business_object_state_timeline(self)

    class Meta:
        db_table = 'business_object'
        verbose_name = '业务对象'
        verbose_name_plural = '业务对象'


class StateFlowRecord(ModelBase):
    """状态流转记录"""
    business_object = models.ForeignKey(BusinessObject, on_delete=models.CASCADE, related_name='state_logs', verbose_name='业务对象')
    state = models.ForeignKey(State, on_delete=models.CASCADE, verbose_name='状态')
    completed_at = models.DateTimeField(auto_now_add=True, verbose_name='完成时间')
    completed_by = models.ForeignKey('auth.User', on_delete=models.SET_NULL, null=True, verbose_name='操作人')
    cancelled_at = models.DateTimeField(null=True, blank=True, verbose_name='撤销时间')
    is_cancelled = models.BooleanField(default=False, verbose_name='是否已撤销')
    
    def get_latest_parameter(self, key, default=None, include_cancelled=False):
        """
        获取参数的最新值（最后一次提交的值）
        
        参数:
            key: 参数键
            default: 默认值
            include_cancelled: 是否包含已撤销状态的参数记录，默认 False
        
        返回:
            参数值或默认值
        """
        # 如果状态已撤销且不包含已撤销记录，返回默认值
        if self.is_cancelled and not include_cancelled:
            return default
        
        records = self.parameter_records.filter(
            parameters__has_key=key
        ).order_by('-created_at')
        
        if records.exists():
            return records.first().parameters.get(key, default)
        return default
    
    def get_parameter_history(self, key, include_cancelled=False):
        """
        获取参数的完整历史
        
        参数:
            key: 参数键
            include_cancelled: 是否包含已撤销状态的参数记录，默认 False
        
        返回:
            list: 历史记录列表，每项包含 value, created_at, remark
        """
        # 如果状态已撤销且不包含已撤销记录，返回空列表
        if self.is_cancelled and not include_cancelled:
            return []
        
        records = self.parameter_records.filter(
            parameters__has_key=key
        ).order_by('created_at')
        
        history = []
        for record in records:
            history.append({
                'value': record.parameters.get(key),
                'created_at': record.created_at,
                'remark': record.remark
            })
        return history
    
    def get_all_parameters_summary(self, include_cancelled=False):
        """
        获取所有参数的最新值汇总
        
        参数:
            include_cancelled: 是否包含已撤销状态的参数记录，默认 False
        
        返回:
            dict: {key: value} 每个key取最新的值
        """
        # 如果状态已撤销且不包含已撤销记录，返回空字典
        if self.is_cancelled and not include_cancelled:
            return {}
        
        summary = {}
        # 按时间顺序，后面的记录覆盖前面的
        for record in self.parameter_records.all().order_by('created_at'):
            summary.update(record.parameters)
        return summary
    
    def get_all_parameter_records_count(self):
        """获取参数记录总数"""
        return self.parameter_records.count()
    
    class Meta:
        db_table = 'state_flow_record'
        verbose_name = '状态流转记录'
        verbose_name_plural = '状态流转记录'
        # 移除 unique_together 约束，允许同一状态多次记录（支持撤销后重新执行）
        ordering = ['completed_at']


class StateLogParameterRecord(ModelBase):
    """
    状态流转参数记录
    使用 JSON 存储一次提交的所有参数
    支持对同一状态流转多次补充参数
    """
    state_log = models.ForeignKey(
        StateFlowRecord, 
        on_delete=models.CASCADE, 
        related_name='parameter_records',
        verbose_name='状态流转记录'
    )
    
    parameters = models.JSONField(
        verbose_name='参数数据',
        help_text='JSON格式存储参数，例如: {"temperature": "25.5", "operator": "张三"}'
    )
    
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    
    remark = models.TextField(blank=True, default='', verbose_name='备注')
    
    def __str__(self):
        return f"{self.state_log} - {len(self.parameters)} 个参数 ({self.created_at})"
    
    def get_parameter(self, key, default=None):
        """快捷方式：获取单个参数值"""
        return self.parameters.get(key, default)
    
    def has_parameter(self, key):
        """快捷方式：检查参数是否存在"""
        return key in self.parameters
    
    def get_all_keys(self):
        """快捷方式：获取所有参数键"""
        return list(self.parameters.keys())
    
    class Meta:
        db_table = 'state_log_parameter_record'
        verbose_name = '状态流转参数记录'
        verbose_name_plural = '状态流转参数记录'
        ordering = ['created_at']
        indexes = [
            models.Index(fields=['state_log', 'created_at']),
        ]
