import bpy
from typing import Set, Dict, List, Optional, Tuple
from bpy.types import (
    Operator, 
    Panel, 
    Menu, 
    Context, 
    UILayout, 
    WindowManager,
    Object
)
from .main_panel import AvatarToolKit_PT_AvatarToolkitPanel, CATEGORY_NAME
from ..core.translations import t
from ..core.common import (
    get_active_armature, 
    clear_default_objects, 
    get_armature_list,
    get_armature_stats
)

# Module-level cache for UI performance (avoids Blender scene property write restrictions)
_validation_cache = {}
_stats_cache = {}

def clear_armature_caches():
    """Clear all armature-related caches - called when armature changes"""
    global _validation_cache, _stats_cache
    _validation_cache.clear()
    _stats_cache.clear()

from ..functions.pose_mode import (
    AvatarToolkit_OT_StartPoseMode,
    AvatarToolkit_OT_StopPoseMode,
    AvatarToolkit_OT_ApplyPoseAsShapekey,
    AvatarToolkit_OT_ApplyPoseAsRest
)
from ..core.armature_validation import validate_armature, AvatarToolkit_OT_ValidateTPose, is_pmx_model
from ..core.importers.importer import AvatarToolKit_OT_Import
from ..core.resonite_utils import AvatarToolKit_OT_ExportResonite
from ..functions.tools.standardize_armature import AvatarToolkit_OT_StandardizeArmature

class AvatarToolKit_OT_ExportFBX(Operator):
    """Export selected objects as FBX"""
    bl_idname: str = "avatar_toolkit.export_fbx"
    bl_label: str = t("QuickAccess.export_fbx")
    
    def execute(self, context: Context) -> Set[str]:
        bpy.ops.export_scene.fbx('INVOKE_DEFAULT')
        return {'FINISHED'}

class AvatarToolKit_MT_ExportMenu(Menu):
    """Export menu containing various export options"""
    bl_idname: str = "AVATAR_TOOLKIT_MT_export_menu"
    bl_label: str = t("QuickAccess.export")

    def draw(self, context: Context) -> None:
        layout: UILayout = self.layout
        layout.operator(AvatarToolKit_OT_ExportFBX.bl_idname, text=t("QuickAccess.export_fbx"))
        layout.operator(AvatarToolKit_OT_ExportResonite.bl_idname, text=t("QuickAccess.export_resonite"))

class AvatarToolKit_OT_ExportMenu(Operator):
    """Open the export menu"""
    bl_idname: str = "avatar_toolkit.export"
    bl_label: str = t("QuickAccess.export")

    @classmethod
    def poll(cls, context: Context) -> bool:
        return get_active_armature(context) is not None
    
    def execute(self, context: Context) -> Set[str]:
        bpy.context.window_manager.popup_menu(AvatarToolKit_MT_ExportMenu.draw)
        return {'FINISHED'}
    
class AvatarToolKit_PT_QuickAccessPanel(Panel):
    """Quick access panel for common Avatar Toolkit operations"""
    bl_label: str = t("QuickAccess.label")
    bl_idname: str = "OBJECT_PT_avatar_toolkit_quick_access"
    bl_space_type: str = 'VIEW_3D'
    bl_region_type: str = 'UI'
    bl_category: str = CATEGORY_NAME
    bl_parent_id: str = AvatarToolKit_PT_AvatarToolkitPanel.bl_idname
    bl_order: int = 0

    def draw(self, context: Context) -> None:
        """Draw the panel layout"""
        layout: UILayout = self.layout
        props = context.scene.avatar_toolkit
        
        # Armature Selection Box
        armature_box: UILayout = layout.box()
        col: UILayout = armature_box.column(align=True)
        col.label(text=t("QuickAccess.select_armature"), icon='ARMATURE_DATA')
        col.separator(factor=0.5)
        
        # Armature Selection
        col.prop(context.scene.avatar_toolkit, "active_armature", text="")
        
        # Get active armature
        active_armature: Optional[Object] = get_active_armature(context)
        if active_armature:
            # Validation Button Box - Always visible
            validation_box: UILayout = layout.box()
            col = validation_box.column(align=True)
            col.label(text=t("Validation.label", "Armature Validation"), icon='CHECKMARK')
            col.separator(factor=0.5)
            
            # Main validate button with prominent styling
            validate_row = col.row(align=True)
            validate_row.scale_y = 1.3
            validate_row.operator("avatar_toolkit.validate_armature_manual", 
                                text=t("Validation.validate_now", "Validate Armature Now"), 
                                icon='CHECKMARK')
            
            # Validation mode selector
            col.prop(props, "validation_mode", text=t("Settings.validation_mode", "Mode"))
            
            # Show validation results if flag is set
            if props.show_validation_results:
                # Cache validation results
                cache_key = f"validation_{active_armature.name}_{active_armature.data.name}_{len(active_armature.data.bones)}"
                
                if cache_key not in _validation_cache:
                    _validation_cache[cache_key] = validate_armature(active_armature, detailed_messages=True)
                
                is_valid, messages, is_acceptable, hierarchy_messages, scale_messages, non_standard_messages = _validation_cache[cache_key]
                
                # Check if this is a PMX model
                pmx_detected = is_pmx_model(active_armature)
                
                results_box = validation_box.box()
                row = results_box.row()
                row.prop(props, "show_validation_results", text=t("Validation.results", "Validation Results"), 
                        icon='TRIA_DOWN' if props.show_validation_results else 'TRIA_RIGHT', emboss=False)
                
                # PMX Model Notice
                if pmx_detected:
                    pmx_box = results_box.box()
                    pmx_box.label(text=t("Armature.validation.pmx_model_detected"), icon='INFO')
                    
                    validation_mode = context.scene.avatar_toolkit.validation_mode
                    if validation_mode == 'STRICT':
                        pmx_box.label(text=t("Armature.validation.pmx_model_strict"))
                        pmx_box.label(text=t("Armature.validation.pmx_model_standardize"))
                    else:
                        pmx_box.label(text=t("Armature.validation.pmx_model_basic"))
                
                # Validation Results
                if not is_valid:
                    # Display found bones
                    if messages and len(messages) > 0:
                        bones_section = results_box.box()
                        row = bones_section.row()
                        row.prop(props, "show_found_bones", text=t("Validation.section.found_bones"), 
                                icon='TRIA_DOWN' if props.show_found_bones else 'TRIA_RIGHT', emboss=False)
                        if props.show_found_bones:
                            for line in messages[0].split('\n'):
                                bones_section.label(text=line)
                    
                    # Status message
                    status_box = results_box.box()
                    row = status_box.row()
                    row.alert = True
                    row.label(text=t("Validation.status.failed"), icon='ERROR')
                    
                    # Error explanation
                    error_box = results_box.box()
                    error_box.alert = True
                    error_box.label(text=t("Validation.message.failed.line1"))
                    error_box.label(text=t("Validation.message.failed.line2"))
                    error_box.label(text=t("Validation.message.failed.line3"))
                    
                    # Non-Standard Bones section
                    if non_standard_messages or pmx_detected:
                        ns_section = results_box.box()
                        row = ns_section.row()
                        row.alert = True
                        row.prop(props, "show_non_standard", text=t("Validation.section.non_standard"), 
                                icon='TRIA_DOWN' if props.show_non_standard else 'TRIA_RIGHT', emboss=False)
                        if props.show_non_standard:
                            if non_standard_messages and len(non_standard_messages) > 0:
                                for message in non_standard_messages:
                                    for line in message.split('\n'):
                                        sub_row = ns_section.row()
                                        sub_row.alert = True
                                        sub_row.label(text=line)
                            elif pmx_detected:
                                ns_section.alert = True
                                ns_section.label(text=t("Armature.validation.pmx_model_basic"))
                                ns_section.label(text=t("Armature.validation.pmx_model_strict"))
                                ns_section.label(text=t("Armature.validation.pmx_model_standardize"))
                            else:
                                ns_section.label(text=t("Validation.no_non_standard_issues"))
                    
                    # Hierarchy Issues section
                    if hierarchy_messages:
                        hier_section = results_box.box()
                        row = hier_section.row()
                        row.alert = True
                        row.prop(props, "show_hierarchy", text=t("Validation.section.hierarchy"), 
                                icon='TRIA_DOWN' if props.show_hierarchy else 'TRIA_RIGHT', emboss=False)
                        if props.show_hierarchy:
                            for message in hierarchy_messages:
                                sub_row = hier_section.row()
                                sub_row.alert = True
                                sub_row.label(text=message)
                    
                    # Scale Issues section
                    if scale_messages:
                        scale_section = results_box.box()
                        row = scale_section.row()
                        row.alert = True
                        row.prop(props, "show_scale_issues", text=t("Validation.section.scale_issues"), 
                                icon='TRIA_DOWN' if props.show_scale_issues else 'TRIA_RIGHT', emboss=False)
                        if props.show_scale_issues:
                            for scale_msg in scale_messages:
                                sub_row = scale_section.row()
                                sub_row.alert = True
                                sub_row.label(text=scale_msg)
                
                elif is_valid and not is_acceptable:
                    # Valid armature - show stats
                    stats_cache_key = f"stats_{active_armature.name}_{active_armature.data.name}_{len(active_armature.data.bones)}"
                    
                    if stats_cache_key not in _stats_cache:
                        _stats_cache[stats_cache_key] = get_armature_stats(active_armature)
                    
                    stats = _stats_cache[stats_cache_key]
                    
                    status_box = results_box.box()
                    row = status_box.row()
                    row.label(text=t("QuickAccess.valid_armature"), icon='CHECKMARK')
                    split = row.split(factor=0.4)
                    split.label(text=t("QuickAccess.bones_count", count=stats['bone_count']))
                    
                    if stats['has_pose']:
                        results_box.label(text=t("QuickAccess.pose_bones_available"), icon='POSE_HLT')
                
                elif is_valid and is_acceptable:
                    # Acceptable standard
                    status_box = results_box.box()
                    status_box.label(text=t("Armature.validation.acceptable_standard.success"), icon='INFO')
                    status_box.label(text=t("Armature.validation.acceptable_standard.note"))
                    status_box.label(text=t("Armature.validation.acceptable_standard.option"))
                    
                    # Add standardize button
                    standardize_box = results_box.box()
                    standardize_box.operator(AvatarToolkit_OT_StandardizeArmature.bl_idname, 
                                        text=t("QuickAccess.standardize_armature"),
                                        icon='MODIFIER')

            # T-Pose Validation Box
            tpose_box: UILayout = layout.box()
            col = tpose_box.column(align=True)
            col.label(text=t("Validation.tpose.label"), icon='ARMATURE_DATA')
            col.separator(factor=0.5)
            col.operator(AvatarToolkit_OT_ValidateTPose.bl_idname, text=t("Validation.tpose.validate_now"), icon='CHECKMARK')

            if props.show_tpose_validation:
                validation_box = col.box()
                if props.tpose_validation_result:
                    validation_box.label(text=t("Validation.tpose.valid"), icon='CHECKMARK')
                else:
                    row = validation_box.row()
                    row.alert = True
                    row.label(text=t("Validation.tpose.warning"), icon='ERROR')
                    
                    for msg in props.tpose_validation_messages:
                        row = validation_box.row()
                        row.alert = True
                        row.label(text=msg.name)

            # Pose Mode Controls
            pose_box: UILayout = layout.box()
            col = pose_box.column(align=True)
            col.label(text=t("QuickAccess.pose_controls"), icon='ARMATURE_DATA')
            col.separator(factor=0.5)
            
            if context.mode == "POSE":
                col.operator(AvatarToolkit_OT_StopPoseMode.bl_idname, icon='POSE_HLT')
                col.separator(factor=0.5)
                col.operator(AvatarToolkit_OT_ApplyPoseAsRest.bl_idname, icon='MOD_ARMATURE')
                col.operator(AvatarToolkit_OT_ApplyPoseAsShapekey.bl_idname, icon='MOD_ARMATURE')
            else:
                col.operator(AvatarToolkit_OT_StartPoseMode.bl_idname, icon='POSE_HLT')

        # Import/Export Box
        import_box: UILayout = layout.box()
        col = import_box.column(align=True)
        col.label(text=t("QuickAccess.import_export"), icon='IMPORT')
        col.separator(factor=0.5)
        
        # Import/Export Buttons
        button_row: UILayout = col.row(align=True)
        button_row.scale_y = 1.5
        button_row.operator(AvatarToolKit_OT_Import.bl_idname, text=t("QuickAccess.import"), icon='IMPORT')
        button_row.operator(AvatarToolKit_OT_ExportMenu.bl_idname, text=t("QuickAccess.export"), icon='EXPORT')

