"""
BusinessObject API ViewSet
"""
from rest_framework import viewsets, filters, status
from rest_framework.decorators import action
from rest_framework.response import Response
from django_filters.rest_framework import DjangoFilterBackend
from django_filters import rest_framework as django_filters
from django.db.models import Exists, OuterRef

from flower.viewsets import LimitedModelViewSet
from stateflow import models, services
from stateflow.serializers import (
    BusinessObjectListSerializer,
    BusinessObjectDetailSerializer,
    BusinessObjectCreateUpdateSerializer,
    StateListSerializer,
)


class BusinessObjectFilterSet(django_filters.FilterSet):
    """业务对象过滤器"""
    name = django_filters.CharFilter(lookup_expr='icontains')
    process_name = django_filters.CharFilter(field_name='process__name', lookup_expr='icontains')
    overall_status = django_filters.ChoiceFilter(
        choices=[
            ('in_progress', '进行中'),
            ('completed', '已完成')
        ],
        method='filter_overall_status'
    )
    content_type_str = django_filters.CharFilter(method='filter_content_type')
    has_content_object = django_filters.BooleanFilter(method='filter_has_content_object')

    # 按“已完成的 state_id + 参数 key/value”反查 BusinessObject
    #
    # 说明：
    # - stateflow 的工艺参数保存在 StateLogParameterRecord.parameters(JSONField)，并挂在某次 StateFlowRecord（完成某节点）之下
    # - 本过滤器只匹配“未撤销”的 StateFlowRecord（is_cancelled=False）
    # - 为避免意外放宽查询范围：当提供了 state_id 但缺少 param_key/param_value 时，返回空结果
    state_id = django_filters.NumberFilter(method='filter_completed_state_param')
    param_key = django_filters.CharFilter(method='noop')
    param_value = django_filters.CharFilter(method='noop')

    def noop(self, queryset, name, value):
        """占位：param_key/param_value 仅作为 state_id 组合过滤的输入，不单独过滤"""
        return queryset

    def filter_completed_state_param(self, queryset, name, value):
        """
        过滤：存在未撤销的 StateFlowRecord(state_id=value)，且该 state_log 下存在参数记录满足 {param_key: param_value}
        """
        if value in (None, ''):
            return queryset

        param_key = (self.data.get('param_key') or '').strip()
        param_value = (self.data.get('param_value') or '').strip()
        if not param_key or not param_value:
            return queryset.none()

        matching_logs = models.StateFlowRecord.objects.filter(
            business_object_id=OuterRef('pk'),
            state_id=value,
            is_cancelled=False,
            parameter_records__parameters__contains={param_key: param_value},
        )
        return queryset.annotate(_has_state_param=Exists(matching_logs)).filter(_has_state_param=True)
    
    def filter_overall_status(self, queryset, name, value):
        """过滤整体状态"""
        business_object_ids = []
        for obj in queryset:
            if services.get_overall_status(obj) == value:
                business_object_ids.append(obj.id)
        return queryset.filter(id__in=business_object_ids)
    
    def filter_content_type(self, queryset, name, value):
        """通过 app_label.model 字符串过滤"""
        try:
            from django.contrib.contenttypes.models import ContentType
            app_label, model = value.split('.')
            content_type = ContentType.objects.get(app_label=app_label, model=model)
            return queryset.filter(content_type=content_type)
        except:
            return queryset.none()
    
    def filter_has_content_object(self, queryset, name, value):
        """过滤是否有关联对象"""
        if value:
            return queryset.exclude(content_type__isnull=True)
        else:
            return queryset.filter(content_type__isnull=True)
    
    class Meta:
        model = models.BusinessObject
        fields = [
            'name',
            'process',
            'process_name',
            'overall_status',
            'content_type_str',
            'has_content_object',
            'state_id',
            'param_key',
            'param_value',
        ]


class BusinessObjectViewSet(LimitedModelViewSet):
    """
    业务对象 CRUD 接口
    
    业务对象是流程的实例，可以选择性地关联到实际的业务模型（如订单、工单等）
    
    list: 获取业务对象列表
    retrieve: 获取业务对象详情（包含时间线和日志）
    create: 创建业务对象
    update: 更新业务对象
    partial_update: 部分更新业务对象
    destroy: 删除业务对象
    
    查询参数:
    - name: 按名称模糊查询
    - process: 按流程ID过滤
    - process_name: 按流程名称模糊查询
    - overall_status: 按整体状态过滤 (not_started/in_progress/completed)
    - content_type_str: 按关联对象类型过滤，格式: app_label.model
    - has_content_object: 是否有关联对象 (true/false)
    - search: 全文搜索（名称和描述）
    - ordering: 排序字段
    """
    queryset = models.BusinessObject.objects.all()
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_class = BusinessObjectFilterSet
    search_fields = ['name', 'description']
    ordering_fields = ['id', 'name', 'created_at', 'updated_at']
    ordering = ['-created_at']
    
    def get_serializer_class(self):
        """根据动作选择序列化器"""
        if self.action == 'list':
            return BusinessObjectListSerializer
        elif self.action in ['create', 'update', 'partial_update']:
            return BusinessObjectCreateUpdateSerializer
        else:  # retrieve
            return BusinessObjectDetailSerializer
    
    def get_queryset(self):
        """优化查询"""
        queryset = super().get_queryset()
        if self.action == 'list':
            queryset = queryset.select_related('process', 'content_type')
        elif self.action == 'retrieve':
            queryset = queryset.select_related('process', 'content_type').prefetch_related(
                'state_logs__state',
                'state_logs__completed_by',
                'process__process_nodes__state'
            )
        return queryset
    
    @action(detail=True, methods=['post'])
    def advance(self, request, pk=None):
        """
        推进到下一个状态
        
        请求体:
        {
            "parameters": {
                "temperature": "25.5",
                "humidity": "60%",
                "operator": "张三"
            }
        }
        
        参数可选，但如果下一个状态有必填参数，则必须提供
        """
        business_object = self.get_object()
        user = request.user
        parameters = request.data.get('parameters', {})
        
        success, message, state_log = services.advance_to_next_state(business_object, user, **parameters)
        
        if success:
            from stateflow.serializers import StateFlowRecordWithParametersSerializer
            return Response({
                'success': True,
                'message': message,
                'state_log': StateFlowRecordWithParametersSerializer(state_log).data if state_log else None,
                'business_object': BusinessObjectDetailSerializer(business_object).data
            })
        else:
            return Response({
                'success': False,
                'message': message
            }, status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=True, methods=['post'])
    def step_back(self, request, pk=None):
        """回退一步（撤销最后一次完成的状态）"""
        business_object = self.get_object()
        user = request.user
        
        success, message = services.step_back_one_state(business_object, user)
        
        if success:
            return Response({
                'success': True,
                'message': message,
                'business_object': BusinessObjectDetailSerializer(business_object).data
            })
        else:
            return Response({
                'success': False,
                'message': message
            }, status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=True, methods=['post'])
    def reset(self, request, pk=None):
        """重置进度"""
        business_object = self.get_object()
        services.reset_business_object_progress(business_object)
        
        return Response({
            'success': True,
            'message': '进度已重置',
            'business_object': BusinessObjectDetailSerializer(business_object).data
        })
    
    @action(detail=True, methods=['get'])
    def timeline(self, request, pk=None):
        """获取状态时间线"""
        business_object = self.get_object()
        timeline = services.get_business_object_state_timeline(business_object)
        
        timeline_data = [
            {
                'state': StateListSerializer(item['state']).data,
                'status': item['status'],
                'order': item['order'],
                'completed_at': item['completed_at'],
                'completed_by': item['completed_by'].username if item['completed_by'] else None,
                'cancelled_at': item['cancelled_at'],
                'is_cancelled': item['is_cancelled'],
            }
            for item in timeline
        ]
        
        return Response(timeline_data)
    
    @action(detail=True, methods=['get'])
    def next_pending_state(self, request, pk=None):
        """
        获取最近一个待执行节点
        
        查询参数:
        - include_parameters: 是否包含参数列表，默认 true (可选值: true, false)
        """
        business_object = self.get_object()
        include_parameters = request.query_params.get('include_parameters', 'true').lower() == 'true'
        
        next_state = services.get_next_pending_state(business_object, include_parameters=include_parameters)
        
        if next_state is None:
            return Response({
                'next_state': None,
                'message': '没有待执行节点（未开始或已完成）'
            })
        
        from stateflow.serializers import StateParameterSerializer
        
        result = {
            'state': StateListSerializer(next_state['state']).data,
            'order': next_state['order'],
        }
        
        if 'parameters' in next_state:
            result['parameters'] = StateParameterSerializer(next_state['parameters'], many=True).data
        
        return Response(result)
    
    @action(detail=True, methods=['get'])
    def pending_states(self, request, pk=None):
        """获取所有待执行节点列表（不包含参数）"""
        business_object = self.get_object()
        pending_states = services.get_all_pending_states(business_object)
        
        result = [
            {
                'state': StateListSerializer(item['state']).data,
                'order': item['order'],
            }
            for item in pending_states
        ]
        
        return Response({
            'count': len(result),
            'pending_states': result
        })
    
    @action(detail=True, methods=['get'], url_path='current_state_parameters')
    def current_state_parameters(self, request, pk=None):
        """
        获取当前状态（最后完成的状态）的参数列表
        
        查询参数:
        - required_only: 是否只返回必填参数，默认 false (可选值: true, false)
        
        注意：current_state 表示最后完成的状态，如果未开始则返回空
        """
        business_object = self.get_object()
        required_only = request.query_params.get('required_only', 'false').lower() == 'true'
        
        current_state = services.get_business_object_current_state(business_object)
        
        if current_state is None:
            return Response({
                'parameters': [],
                'message': '尚未完成任何状态'
            })
        
        from stateflow.serializers import StateParameterSerializer
        
        parameters = services.get_state_parameters(current_state, required_only=required_only)
        
        return Response({
            'state': StateListSerializer(current_state).data,
            'parameters': StateParameterSerializer(parameters, many=True).data,
            'count': len(parameters)
        })
    
    @action(detail=True, methods=['get'], url_path='process-nodes')
    def process_nodes(self, request, pk=None):
        """
        获取业务对象所属流程的所有状态节点
        
        返回流程中所有节点的列表，按顺序排列
        """
        business_object = self.get_object()
        nodes = services.get_process_nodes(business_object)
        
        return Response({
            'count': len(nodes),
            'nodes': [
                {
                    'id': node['id'],
                    'state_id': node['state_id'],
                    'state_name': node['state_name'],
                    'order': node['order']
                }
                for node in nodes
            ]
        })
    
    @action(detail=True, methods=['post'], url_path='state-logs/(?P<log_id>[^/.]+)/add-parameters')
    def add_parameters_to_log(self, request, pk=None, log_id=None):
        """
        为状态流转记录补充参数
        
        POST /api/v1/stateflow/business-objects/{id}/state-logs/{log_id}/add-parameters/
        
        请求体:
        {
            "parameters": {
                "additional_note": "发现轻微瑕疵",
                "temperature": "26.0"
            },
            "remark": "质检员补充"
        }
        """
        business_object = self.get_object()
        
        try:
            state_log = business_object.state_logs.get(id=log_id)
        except models.StateFlowRecord.DoesNotExist:
            return Response({
                'success': False,
                'message': '状态流转记录不存在'
            }, status=status.HTTP_404_NOT_FOUND)
        
        parameters = request.data.get('parameters', {})
        remark = request.data.get('remark', '')
        
        if not parameters:
            return Response({
                'success': False,
                'message': '参数不能为空'
            }, status=status.HTTP_400_BAD_REQUEST)
        
        from stateflow.serializers import StateLogParameterRecordSerializer
        record = services.add_parameters_to_state_log(state_log, remark=remark, **parameters)
        
        return Response({
            'success': True,
            'parameter_record': StateLogParameterRecordSerializer(record).data
        })
    
    @action(detail=True, methods=['get'], url_path='state-logs')
    def get_state_logs(self, request, pk=None):
        """
        获取业务对象的所有状态流转记录列表
        
        GET /api/v1/stateflow/business-objects/{id}/state-logs/
        GET /api/v1/stateflow/business-objects/{id}/state-logs/?include_parameters=false
        GET /api/v1/stateflow/business-objects/{id}/state-logs/?include_cancelled=true
        
        查询参数:
        - include_parameters: 是否包含工艺参数，默认 true（可选值: true, false）
        - include_cancelled: 是否包含已撤销的记录，默认 true（可选值: true, false）
        """
        business_object = self.get_object()
        include_parameters = request.query_params.get('include_parameters', 'true').lower() == 'true'
        include_cancelled = request.query_params.get('include_cancelled', 'true').lower() == 'true'
        
        # 获取状态流转记录
        state_logs = business_object.state_logs.select_related('state', 'completed_by').order_by('completed_at')
        
        if not include_cancelled:
            state_logs = state_logs.filter(is_cancelled=False)
        
        # 序列化
        if include_parameters:
            from stateflow.serializers import StateFlowRecordWithParametersSerializer
            serializer = StateFlowRecordWithParametersSerializer(state_logs, many=True)
        else:
            from stateflow.serializers import StateFlowRecordSerializer
            serializer = StateFlowRecordSerializer(state_logs, many=True)
        
        return Response({
            'count': state_logs.count(),
            'state_logs': serializer.data
        })
    
    @action(detail=True, methods=['get'], url_path='state-logs/(?P<log_id>[^/.]+)/parameters')
    def get_log_parameters(self, request, pk=None, log_id=None):
        """
        获取状态流转记录的所有参数记录
        
        GET /api/v1/stateflow/business-objects/{id}/state-logs/{log_id}/parameters/
        GET /api/v1/stateflow/business-objects/{id}/state-logs/{log_id}/parameters/?key=temperature
        GET /api/v1/stateflow/business-objects/{id}/state-logs/{log_id}/parameters/?include_cancelled=true
        
        查询参数:
        - key: 指定参数键，返回该参数的历史（可选）
        - include_cancelled: 是否包含已撤销状态的参数，默认 false（可选）
        """
        business_object = self.get_object()
        
        try:
            state_log = business_object.state_logs.get(id=log_id)
        except models.StateFlowRecord.DoesNotExist:
            return Response({
                'success': False,
                'message': '状态流转记录不存在'
            }, status=status.HTTP_404_NOT_FOUND)
        
        key = request.query_params.get('key')
        include_cancelled = request.query_params.get('include_cancelled', 'false').lower() == 'true'
        
        if key:
            # 返回指定参数的历史
            history = state_log.get_parameter_history(key, include_cancelled=include_cancelled)
            return Response({
                'state_log_id': state_log.id,
                'key': key,
                'is_cancelled': state_log.is_cancelled,
                'history': history
            })
        else:
            # 返回所有参数记录
            from stateflow.serializers import StateLogParameterRecordSerializer
            records = state_log.parameter_records.all()
            return Response({
                'state_log_id': state_log.id,
                'is_cancelled': state_log.is_cancelled,
                'count': records.count(),
                'summary': state_log.get_all_parameters_summary(include_cancelled=include_cancelled),
                'records': StateLogParameterRecordSerializer(records, many=True).data if include_cancelled or not state_log.is_cancelled else []
            })
