from django.contrib import admin
from django.contrib.admin import action
from django.contrib.contenttypes.models import ContentType
from django.forms import BaseInlineFormSet
from django.utils.html import format_html
from . import models


@admin.register(models.PlateOrder)
class PlateOrderAdmin(admin.ModelAdmin):
    list_display = (
        'id',
        'design_code_display',
        'customer_name',
        'style_name',
        'plate_type',
        'development_status_display',
        'urgency_display',
        'progress_display',
        'salesperson_name',
        'required_completion_date',
        'created_at',
    )
    list_filter = (
        'urgency_level',
        'plate_type',
        'is_ordered',
        'is_mark_frame',
        'created_at',
        'required_completion_date',
    )
    search_fields = (
        'design_code',
        'style_name',
        'customer__name',
        'salesperson__name',
        'merchandiser__name',
        'designer__name',
    )
    readonly_fields = ('progress_display', 'status_display')
    actions = ['advance_to_next_state_action', 'step_back_one_state_action', 'reset_progress_action']
    autocomplete_fields = ['customer', 'salesperson', 'merchandiser', 'designer']
    
    fieldsets = [
        ('基本信息', {
            'fields': ['design_code', 'plate_type', 'plate_date', 'urgency_level', 'original_id']
        }),
        ('客户信息', {
            'fields': ['customer', 'area', 'default_address', 'salesperson', 'merchandiser', 'designer']
        }),
        ('产品信息', {
            'fields': ['style_name', 'fabric', 'fabric_source', 'width', 'production_method']
        }),
        ('开版信息', {
            'fields': [
                'plate_method', 'plate_image', 'image_name', 'plate_notes', 'reprint_reason',
                'is_mark_frame', 'sample_meter', 'required_sample_meters'
            ]
        }),
        ('质量评级', {
            'fields': [
                'drawing_rating', 'color_matching_rating', 
                'sample_rating', 'difficulty_rating'
            ]
        }),
        ('时间管理', {
            'fields': ['required_completion_date', 'completion_date']
        }),
        ('审批与反馈', {
            'fields': [
                'approval_result', 'customer_feedback', 
                'is_ordered'
            ]
        }),
        ('流程管理', {
            'fields': ['business_object', 'status_display', 'progress_display'],
            'classes': ['collapse']
        }),
    ]
    
    @admin.display(description='设计编号')
    def design_code_display(self, obj):
        return obj.design_code or (str(obj.id) if obj.id else '-')

    @admin.display(description='客户')
    def customer_name(self, obj):
        return obj.customer.name if obj.customer else '-'
    
    @admin.display(description='销售员')
    def salesperson_name(self, obj):
        return obj.salesperson.name if obj.salesperson else '-'
    
    @admin.display(description='开发进程')
    def development_status_display(self, obj):
        return obj.status
    
    @admin.display(description='紧急程度')
    def urgency_display(self, obj):
        if obj.urgency_level == '加急':
            return format_html(
                '<span style="color: red; font-weight: bold;">⚠️ 加急</span>'
            )
        return obj.urgency_level
    
    @admin.display(description='进度')
    def progress_display(self, obj):
        return obj.progress_percentage
    
    @admin.display(description='当前状态')
    def status_display(self, obj):
        return obj.status
    
    @action(description='推进到下一个状态')
    def advance_to_next_state_action(self, request, queryset):
        from stateflow import services
        success_count = 0
        messages = []
        
        for obj in queryset:
            if not obj.business_object:
                messages.append(f"{obj.id}: 没有关联的流程实例，无法推进")
                continue
            
            # 修复历史/异常数据：确保该订单的流程实例正确绑定到订单（避免 BusinessObject.object_id/content_type 为空）
            services.ensure_business_object_bound_to_instance(
                obj.business_object,
                obj,
                default_name=f"PlateOrder-{obj.id}",
            )
            success, message, state_log = services.advance_to_next_state(obj.business_object, request.user)
            if success:
                success_count += 1
            messages.append(f"{obj.id}: {message}")
        
        self.message_user(request, f'成功推进 {success_count}/{queryset.count()} 个开版订单。详情: {"; ".join(messages[:5])}')
    
    @action(description='回退一步')
    def step_back_one_state_action(self, request, queryset):
        from stateflow import services
        success_count = 0
        messages = []
        
        for obj in queryset:
            if not obj.business_object:
                messages.append(f"{obj.id}: 没有关联的流程实例，无法回退")
                continue
            
            success, message = services.step_back_one_state(obj.business_object, request.user)
            if success:
                success_count += 1
            messages.append(f"{obj.id}: {message}")
        
        self.message_user(request, f'成功回退 {success_count}/{queryset.count()} 个开版订单。详情: {"; ".join(messages[:5])}')
    
    @action(description='重置进度')
    def reset_progress_action(self, request, queryset):
        from stateflow import services
        reset_count = 0
        
        for obj in queryset:
            if not obj.business_object:
                continue
            
            services.reset_business_object_progress(obj.business_object)
            reset_count += 1
        
        self.message_user(request, f'已重置 {reset_count} 个开版订单的进度。')


class PrintingJobInlineFormSet(BaseInlineFormSet):
    """自定义 formset 处理 PrintingJob 的创建"""
    
    def save_new(self, form, commit=True):
        """保存新的 PrintingJob（暂时不创建 BusinessObject，等 order 保存完成后再创建）"""
        obj = super().save_new(form, commit=commit)
        return obj


class PrintingJobInline(admin.StackedInline):
    model = models.PrintingJob
    formset = PrintingJobInlineFormSet
    extra = 1
    autocomplete_fields = ('product',)  # 避免加载所有产品导致页面卡死


@admin.register(models.PrintingOrder)
class PrintingOrderAdmin(admin.ModelAdmin):
    list_display = (
        'oid',
        'external_order_id',
        'external_customer_name',
        'external_employee_name',
        'customer_name',
        'progress_percent',
        'created_at',
        'outgoing_date',
    )
    search_fields = (
        '=id',
        'external_order_id',
        'external_customer_id',
        'external_customer_name',
        'external_employee_name',
        'customer__name',
        'fabric',
        'craft',
        'description',
    )
    readonly_fields = ('external_raw_pretty',)
    fieldsets = (
        ('基础信息', {
            'fields': (
                'customer', 'fabric', 'width', 'is_urgent', 'area', 'address',
                'fabric_source', 'is_fabric_received', 'craft', 'description',
                'outgoing_date', 'curve', 'new_curve', 'position',
                'printing_warn', 'rolling_warn', 'production_warn',
                'is_invalid', 'process',
            )
        }),
        ('外部同步信息', {
            'fields': (
                'external_order_id',
                'external_customer_id',
                'external_customer_name',
                'external_employee_name',
                'external_raw_pretty',
            ),
            'classes': ('collapse',),
        }),
    )

    @admin.display(description='外部订单编号')
    def external_order_id(self, obj):
        return obj.external_order_id or '-'

    @admin.display(description='外部客户名')
    def external_customer_name(self, obj):
        return obj.external_customer_name or '-'

    @admin.display(description='外部员工名')
    def external_employee_name(self, obj):
        return obj.external_employee_name or '-'

    @admin.display(description='外部原始数据')
    def external_raw_pretty(self, obj):
        import json
        return format_html('<pre style="white-space: pre-wrap;">{}</pre>', json.dumps(obj.external_raw or {}, ensure_ascii=False, indent=2))


    def save_formset(self, request, form, formset, change):
        """保存 formset 后，为新创建的 PrintingJob 创建 BusinessObject"""
        # 先调用默认的保存
        formset.save()
        
        # 此时 PrintingOrder 已经保存完成（包括 process 字段）
        # 为所有新创建且没有 business_object 的 job 创建 BusinessObject
        if isinstance(formset.model, type) and issubclass(formset.model, models.PrintingJob):
            order = form.instance
            ct = ContentType.objects.get_for_model(models.PrintingJob)
            for job in order.printing_jobs.all():
                if not job.business_object and order.process:
                    from stateflow.models import BusinessObject
                    business_object = BusinessObject.objects.create(
                        name=f"PrintingJob-{job.id}",
                        process=order.process,
                        description=f"印染任务 {job.id} 的流程实例",
                        content_type=ct,
                        object_id=job.id,
                    )
                    job.business_object = business_object
                    job.save(update_fields=['business_object'])

    def save_model(self, request, obj, form, change):
        """保存 PrintingOrder 时使用 service 层"""
        from api_v1.views.printing.services import PrintingOrderService
        
        if not change:  # 新创建
            # 使用 service 创建（会自动设置默认 process）
            data = {
                'customer': obj.customer,
                'fabric': obj.fabric,
                'width': obj.width,
                'is_urgent': obj.is_urgent,
                'area': obj.area,
                'address': obj.address,
                'fabric_source': obj.fabric_source,
                'is_fabric_received': obj.is_fabric_received,
                'craft': obj.craft,
                'description': obj.description,
                'outgoing_date': obj.outgoing_date,
                'curve': obj.curve,
                'new_curve': obj.new_curve,
                'position': obj.position,
                'printing_warn': obj.printing_warn,
                'rolling_warn': obj.rolling_warn,
                'production_warn': obj.production_warn,
                'is_invalid': obj.is_invalid,
                'process': obj.process,
            }
            created_obj = PrintingOrderService.create_printing_order(data, request.user)
            # 将创建的对象的所有字段复制到当前对象
            for field in created_obj._meta.fields:
                setattr(obj, field.name, getattr(created_obj, field.name))
        else:  # 更新
            # 使用 service 更新
            data = {
                'customer': obj.customer,
                'fabric': obj.fabric,
                'width': obj.width,
                'is_urgent': obj.is_urgent,
                'area': obj.area,
                'address': obj.address,
                'fabric_source': obj.fabric_source,
                'is_fabric_received': obj.is_fabric_received,
                'craft': obj.craft,
                'description': obj.description,
                'outgoing_date': obj.outgoing_date,
                'curve': obj.curve,
                'new_curve': obj.new_curve,
                'position': obj.position,
                'printing_warn': obj.printing_warn,
                'rolling_warn': obj.rolling_warn,
                'production_warn': obj.production_warn,
                'is_invalid': obj.is_invalid,
                'process': obj.process,
            }
            success, message, updated_obj = PrintingOrderService.update_printing_order(
                obj, data, request.user
            )
            if not success:
                from django.core.exceptions import ValidationError
                raise ValidationError(message)

    @admin.display(description='客户名称')
    def customer_name(self, obj: models.PrintingOrder):
        return obj.customer.name

    @admin.display(description='订单编号(虚拟)')
    def oid(self, obj: models.PrintingOrder):
        return obj.human_id

    @admin.display(description='进度')
    def progress_percent(self, obj: models.PrintingOrder):
        return f"{obj.progress}%"


@admin.register(models.PrintingJob)
class PrintingJobAdmin(admin.ModelAdmin):
    list_display = (
        'id', 
        'printing_order', 
        'customer_name',
        'product', 
        'quantity', 
        'unit',
        'size',
        'pieces',
        'business_object',
        'current_progress',
        'execution_status',
        'created_at',
    )
    search_fields = (
        '=printing_order__id',
        'printing_order__external_order_id',
        'product__name',
        'external_product_name',
    )
    list_filter = ('created_at', 'printing_order__customer__name')
    actions = ['advance_to_next_state_action', 'step_back_one_state_action', 'reset_progress_action']
    autocomplete_fields = (
        'merchant',
        'printing_order',
        'product',
        'business_object',
        'created_by',
    )

    def save_model(self, request, obj, form, change):
        """保存 PrintingJob 时使用 service 层"""
        from api_v1.views.printing.services import PrintingJobService
        
        if not change:  # 新创建
            # 使用 service 创建（这样会自动创建 BusinessObject）
            data = {
                'printing_order': obj.printing_order,
                'product': obj.product,
                'quantity': obj.quantity,
                'unit': obj.unit,
                'size': obj.size,
                'pieces': obj.pieces,
                'sub_id': obj.sub_id,
                'description': obj.description,
            }
            created_obj = PrintingJobService.create_printing_job(data, request.user)
            # 将创建的对象的 ID 赋值给当前对象（这样 admin 可以正确跳转）
            obj.pk = created_obj.pk
            obj.id = created_obj.id
        else:  # 更新
            # 使用 service 更新
            data = {
                'printing_order': obj.printing_order,
                'product': obj.product,
                'quantity': obj.quantity,
                'unit': obj.unit,
                'size': obj.size,
                'pieces': obj.pieces,
                'sub_id': obj.sub_id,
                'description': obj.description,
            }
            success, message, updated_obj = PrintingJobService.update_printing_job(
                obj, data, request.user
            )
            if not success:
                from django.core.exceptions import ValidationError
                raise ValidationError(message)

    @admin.display(description='客户名称')
    def customer_name(self, obj: models.PrintingJob):
        return obj.printing_order.customer.name

    @admin.display(description='当前进度')
    def current_progress(self, obj: models.PrintingJob):
        """显示该 job 自己的进度（已完成节点数 / 总节点数）"""
        if not obj.business_object or not obj.printing_order.process:
            return "0%"
        
        total_nodes = obj.business_object.process.process_nodes.count()
        if total_nodes == 0:
            return "0%"
        
        completed_nodes = obj.business_object.state_logs.filter(is_cancelled=False).count()
        progress = int((completed_nodes / total_nodes) * 100)
        return f"{progress}%"

    @admin.display(description='执行状态')
    def execution_status(self, obj: models.PrintingJob):
        return obj.status

    @action(description='前进到下一个状态')
    def advance_to_next_state_action(self, request, queryset):
        from stateflow import services
        success_count = 0
        messages = []
        
        for obj in queryset:
            # 检查是否有 business_object
            if not obj.business_object:
                messages.append(f"PrintingJob #{obj.id}: 没有关联的业务对象，无法推进")
                continue
            
            # 修复历史/异常数据：确保该 job 的流程实例正确绑定到 job（避免 BusinessObject.object_id/content_type 为空）
            services.ensure_business_object_bound_to_instance(
                obj.business_object,
                obj,
                default_name=f"PrintingJob-{obj.id}",
            )
            success, message, state_log = services.advance_to_next_state(obj.business_object, request.user)
            if success:
                success_count += 1
            messages.append(f"PrintingJob #{obj.id}: {message}")
        
        self.message_user(request, f'成功推进 {success_count}/{queryset.count()} 个印染任务。详情: {"; ".join(messages[:5])}')

    @action(description='回退一步')
    def step_back_one_state_action(self, request, queryset):
        from stateflow import services
        success_count = 0
        messages = []
        
        for obj in queryset:
            # 检查是否有 business_object
            if not obj.business_object:
                messages.append(f"PrintingJob #{obj.id}: 没有关联的业务对象，无法回退")
                continue
            
            success, message = services.step_back_one_state(obj.business_object, request.user)
            if success:
                success_count += 1
            messages.append(f"PrintingJob #{obj.id}: {message}")
        
        self.message_user(request, f'成功回退 {success_count}/{queryset.count()} 个印染任务。详情: {"; ".join(messages[:5])}')

    @action(description='重置进度')
    def reset_progress_action(self, request, queryset):
        from stateflow import services
        reset_count = 0
        
        for obj in queryset:
            # 检查是否有 business_object
            if not obj.business_object:
                continue
            
            services.reset_business_object_progress(obj.business_object)
            reset_count += 1
        
        self.message_user(request, f'已重置 {reset_count} 个印染任务的进度。')


@admin.register(models.PrintingJobBatchAdvanceRecord)
class PrintingJobBatchAdvanceRecordAdmin(admin.ModelAdmin):
    list_display = (
        'id',
        'printing_order',
        'state',
        'created_by',
        'jobs_count',
        'created_at',
    )
    list_filter = (
        'state',
        'created_by',
        'created_at',
    )
    search_fields = (
        'printing_order__customer__name',
        'state__name',
        'created_by__username',
    )
    readonly_fields = (
        'created_at',
        'updated_at',
    )
    date_hierarchy = 'created_at'
    ordering = ('-created_at',)
    autocomplete_fields = ('printing_order', 'state', 'created_by', 'printing_jobs')

    @admin.display(description='涉及任务数')
    def jobs_count(self, obj: models.PrintingJobBatchAdvanceRecord) -> int:
        return obj.printing_jobs.count()


@admin.register(models.PrintingOrderExternalSnapshotSyncAudit)
class PrintingOrderExternalSnapshotSyncAuditAdmin(admin.ModelAdmin):
    list_display = (
        'id',
        'external_order_id',
        'printing_order',
        'operator_user',
        'operator_employee',
        'allow_reset_stateflow',
        'is_success',
        'created_at',
        'updated_at',
    )
    list_filter = (
        'is_success',
        'allow_reset_stateflow',
        'created_at',
    )
    search_fields = (
        'external_order_id',
        'printing_order__id',
        'operator_user__username',
        'operator_employee__name',
        'failure_reason',
    )
    readonly_fields = (
        'printing_order',
        'external_order_id',
        'operator_user',
        'operator_employee',
        'before_snapshot',
        'allow_reset_stateflow',
        'is_success',
        'failure_reason',
        'created_at',
        'updated_at',
    )
    date_hierarchy = 'created_at'
    ordering = ('-created_at', '-id')

    def has_add_permission(self, request):
        return False

    def has_change_permission(self, request, obj=None):
        return False


@admin.register(models.PlateOrderTiiaUploadFailure)
class PlateOrderTiiaUploadFailureAdmin(admin.ModelAdmin):
    list_display = ('id', 'run_date', 'plate_order_id', 'attempts', 'last_attempt_at', 'created_at')
    list_filter = ('run_date', 'created_at')
    search_fields = ('plate_order_id', 'error')
    readonly_fields = ('created_at', 'updated_at')
