"""Modeling view component."""

from __future__ import annotations

from typing import TYPE_CHECKING

from PySide2.QtWidgets import (
    QComboBox,
    QDoubleSpinBox,
    QFormLayout,
    QGroupBox,
    QHBoxLayout,
    QLabel,
    QPushButton,
    QSpinBox,
    QTabWidget,
    QTextEdit,
    QVBoxLayout,
    QWidget,
)

if TYPE_CHECKING:
    from pytola_sim.lscsim.core.main_controller import MainController


class ModelingView(QWidget):
    """Modeling view component."""

    def __init__(self, controller: MainController) -> None:
        super().__init__()
        self.controller = controller
        self._setup_ui()

    def _setup_ui(self) -> None:
        main_layout = QVBoxLayout(self)

        # Create tab widget
        self.tab_widget = QTabWidget()

        # Geometry tab
        self.geometry_tab = self._create_geometry_tab()
        self.tab_widget.addTab(self.geometry_tab, "几何建模")

        # Mesh tab
        self.mesh_tab = self._create_mesh_tab()
        self.tab_widget.addTab(self.mesh_tab, "网格划分")

        # Boundary Conditions tab
        self.bc_tab = self._create_bc_tab()
        self.tab_widget.addTab(self.bc_tab, "边界条件")

        # Materials tab
        self.materials_tab = self._create_materials_tab()
        self.tab_widget.addTab(self.materials_tab, "材料属性")

        main_layout.addWidget(self.tab_widget)

        # Control buttons
        button_layout = QHBoxLayout()
        self.generate_mesh_btn = QPushButton("生成网格")
        self.validate_model_btn = QPushButton("验证模型")
        self.preview_btn = QPushButton("预览模型")

        button_layout.addWidget(self.generate_mesh_btn)
        button_layout.addWidget(self.validate_model_btn)
        button_layout.addWidget(self.preview_btn)
        button_layout.addStretch()

        main_layout.addLayout(button_layout)

        # Connect signals
        self._connect_signals()

    def _create_geometry_tab(self) -> QWidget:
        """Create geometry modeling tab."""
        widget = QWidget()
        layout = QVBoxLayout(widget)

        # Geometry creation group
        geom_group = QGroupBox("几何体创建")
        geom_layout = QVBoxLayout(geom_group)

        # Primitive creation
        primitive_layout = QHBoxLayout()
        self.geom_type_combo = QComboBox()
        self.geom_type_combo.addItems(["立方体", "圆柱体", "球体", "自定义"])
        self.create_geom_btn = QPushButton("创建几何体")

        primitive_layout.addWidget(QLabel("几何类型:"))
        primitive_layout.addWidget(self.geom_type_combo)
        primitive_layout.addWidget(self.create_geom_btn)

        geom_layout.addLayout(primitive_layout)

        # Geometry parameters
        param_group = QGroupBox("几何参数")
        param_layout = QFormLayout(param_group)

        self.length_spin = QDoubleSpinBox()
        self.length_spin.setRange(0.1, 10000)
        self.length_spin.setValue(100)

        self.width_spin = QDoubleSpinBox()
        self.width_spin.setRange(0.1, 10000)
        self.width_spin.setValue(50)

        self.height_spin = QDoubleSpinBox()
        self.height_spin.setRange(0.1, 10000)
        self.height_spin.setValue(20)

        param_layout.addRow("长度 (mm):", self.length_spin)
        param_layout.addRow("宽度 (mm):", self.width_spin)
        param_layout.addRow("高度 (mm):", self.height_spin)

        geom_layout.addWidget(param_group)
        layout.addWidget(geom_group)

        # Boolean operations
        boolean_group = QGroupBox("布尔运算")
        boolean_layout = QHBoxLayout(boolean_group)

        self.union_btn = QPushButton("并集")
        self.subtract_btn = QPushButton("差集")
        self.intersect_btn = QPushButton("交集")

        boolean_layout.addWidget(self.union_btn)
        boolean_layout.addWidget(self.subtract_btn)
        boolean_layout.addWidget(self.intersect_btn)

        layout.addWidget(boolean_group)
        layout.addStretch()

        return widget

    def _create_mesh_tab(self) -> QWidget:
        """Create mesh generation tab."""
        widget = QWidget()
        layout = QVBoxLayout(widget)

        # Mesh parameters
        mesh_group = QGroupBox("网格参数")
        mesh_layout = QFormLayout(mesh_group)

        self.element_type_combo = QComboBox()
        self.element_type_combo.addItems(["四面体", "六面体", "混合网格"])

        self.global_size_spin = QDoubleSpinBox()
        self.global_size_spin.setRange(0.1, 100)
        self.global_size_spin.setValue(5.0)

        self.max_aspect_ratio_spin = QDoubleSpinBox()
        self.max_aspect_ratio_spin.setRange(1.0, 100.0)
        self.max_aspect_ratio_spin.setValue(10.0)

        self.smooth_passes_spin = QSpinBox()
        self.smooth_passes_spin.setRange(0, 10)
        self.smooth_passes_spin.setValue(3)

        mesh_layout.addRow("单元类型:", self.element_type_combo)
        mesh_layout.addRow("全局尺寸 (mm):", self.global_size_spin)
        mesh_layout.addRow("最大纵横比:", self.max_aspect_ratio_spin)
        mesh_layout.addRow("光顺次数:", self.smooth_passes_spin)

        layout.addWidget(mesh_group)

        # Mesh controls
        control_layout = QHBoxLayout()
        self.refine_mesh_btn = QPushButton("局部加密")
        self.coarsen_mesh_btn = QPushButton("局部粗化")
        self.optimize_mesh_btn = QPushButton("网格优化")

        control_layout.addWidget(self.refine_mesh_btn)
        control_layout.addWidget(self.coarsen_mesh_btn)
        control_layout.addWidget(self.optimize_mesh_btn)

        layout.addLayout(control_layout)
        layout.addStretch()

        return widget

    def _create_bc_tab(self) -> QWidget:
        """Create boundary conditions tab."""
        widget = QWidget()
        layout = QVBoxLayout(widget)

        # Boundary conditions
        bc_group = QGroupBox("边界条件设置")
        bc_layout = QVBoxLayout(bc_group)

        # Fixed constraints
        fixed_layout = QHBoxLayout()
        self.fixed_surface_combo = QComboBox()
        self.fixed_surface_combo.addItems(["底面", "侧面", "顶面", "自定义面"])
        self.apply_fixed_btn = QPushButton("施加固定约束")

        fixed_layout.addWidget(QLabel("固定面:"))
        fixed_layout.addWidget(self.fixed_surface_combo)
        fixed_layout.addWidget(self.apply_fixed_btn)

        bc_layout.addLayout(fixed_layout)

        # Symmetry conditions
        sym_layout = QHBoxLayout()
        self.symmetry_plane_combo = QComboBox()
        self.symmetry_plane_combo.addItems(["X对称", "Y对称", "Z对称"])
        self.apply_symmetry_btn = QPushButton("施加对称条件")

        sym_layout.addWidget(QLabel("对称面:"))
        sym_layout.addWidget(self.symmetry_plane_combo)
        sym_layout.addWidget(self.apply_symmetry_btn)

        bc_layout.addLayout(sym_layout)

        layout.addWidget(bc_group)

        # Loads section
        loads_group = QGroupBox("载荷施加")
        loads_layout = QVBoxLayout(loads_group)

        # Pressure load
        pressure_layout = QHBoxLayout()
        self.pressure_value_spin = QDoubleSpinBox()
        self.pressure_value_spin.setRange(-1000, 1000)
        self.pressure_value_spin.setValue(100)
        self.apply_pressure_btn = QPushButton("施加压力载荷")

        pressure_layout.addWidget(QLabel("压力值 (MPa):"))
        pressure_layout.addWidget(self.pressure_value_spin)
        pressure_layout.addWidget(self.apply_pressure_btn)

        loads_layout.addLayout(pressure_layout)

        # Force load
        force_layout = QHBoxLayout()
        self.force_x_spin = QDoubleSpinBox()
        self.force_y_spin = QDoubleSpinBox()
        self.force_z_spin = QDoubleSpinBox()
        self.apply_force_btn = QPushButton("施加集中力")

        force_layout.addWidget(QLabel("力 (N): X:"))
        force_layout.addWidget(self.force_x_spin)
        force_layout.addWidget(QLabel("Y:"))
        force_layout.addWidget(self.force_y_spin)
        force_layout.addWidget(QLabel("Z:"))
        force_layout.addWidget(self.force_z_spin)
        force_layout.addWidget(self.apply_force_btn)

        loads_layout.addLayout(force_layout)

        layout.addWidget(loads_group)
        layout.addStretch()

        return widget

    def _create_materials_tab(self) -> QWidget:
        """Create materials tab."""
        widget = QWidget()
        layout = QVBoxLayout(widget)

        # Material assignment
        assign_group = QGroupBox("材料分配")
        assign_layout = QVBoxLayout(assign_group)

        # Material selection
        material_selection_layout = QHBoxLayout()
        self.material_assign_combo = QComboBox()
        self.material_assign_combo.addItems(["结构钢", "铝合金", "钛合金", "混凝土"])
        self.assign_material_btn = QPushButton("分配材料")

        material_selection_layout.addWidget(QLabel("材料:"))
        material_selection_layout.addWidget(self.material_assign_combo)
        material_selection_layout.addWidget(self.assign_material_btn)

        assign_layout.addLayout(material_selection_layout)

        # Assigned materials display
        self.material_display = QTextEdit()
        self.material_display.setMaximumHeight(150)
        self.material_display.setReadOnly(True)
        self.material_display.setPlaceholderText("已分配的材料将在此显示...")

        assign_layout.addWidget(QLabel("材料分配情况:"))
        assign_layout.addWidget(self.material_display)

        layout.addWidget(assign_group)

        # Material properties
        props_group = QGroupBox("材料属性")
        props_layout = QFormLayout(props_group)

        self.density_label = QLabel("7850 kg/m³")
        self.young_modulus_label = QLabel("200 GPa")
        self.poisson_ratio_label = QLabel("0.3")
        self.yield_strength_label = QLabel("250 MPa")

        props_layout.addRow("密度:", self.density_label)
        props_layout.addRow("弹性模量:", self.young_modulus_label)
        props_layout.addRow("泊松比:", self.poisson_ratio_label)
        props_layout.addRow("屈服强度:", self.yield_strength_label)

        layout.addWidget(props_group)
        layout.addStretch()

        return widget

    def _connect_signals(self) -> None:
        """Connect UI signals to slots."""
        # Geometry signals
        self.create_geom_btn.clicked.connect(self._on_create_geometry)
        self.union_btn.clicked.connect(self._on_boolean_union)
        self.subtract_btn.clicked.connect(self._on_boolean_subtract)
        self.intersect_btn.clicked.connect(self._on_boolean_intersect)

        # Mesh signals
        self.generate_mesh_btn.clicked.connect(self._on_generate_mesh)
        self.refine_mesh_btn.clicked.connect(self._on_refine_mesh)
        self.optimize_mesh_btn.clicked.connect(self._on_optimize_mesh)

        # BC signals
        self.apply_fixed_btn.clicked.connect(self._on_apply_fixed_constraint)
        self.apply_pressure_btn.clicked.connect(self._on_apply_pressure)
        self.apply_force_btn.clicked.connect(self._on_apply_force)

        # Material signals
        self.assign_material_btn.clicked.connect(self._on_assign_material)

        # General signals
        self.validate_model_btn.clicked.connect(self._on_validate_model)
        self.preview_btn.clicked.connect(self._on_preview_model)

    def _on_create_geometry(self) -> None:
        """Handle create geometry button click."""
        geom_type = self.geom_type_combo.currentText()
        parameters = {
            "length": self.length_spin.value(),
            "width": self.width_spin.value(),
            "height": self.height_spin.value(),
        }

        self.controller.execute_command(
            "Modeling.CreateGeometry",
            {"type": geom_type, "parameters": parameters},
        )

    def _on_boolean_union(self) -> None:
        """Handle boolean union operation."""
        self.controller.execute_command(
            "Modeling.BooleanOperation",
            {"operation": "union"},
        )

    def _on_boolean_subtract(self) -> None:
        """Handle boolean subtract operation."""
        self.controller.execute_command(
            "Modeling.BooleanOperation",
            {"operation": "subtract"},
        )

    def _on_boolean_intersect(self) -> None:
        """Handle boolean intersect operation."""
        self.controller.execute_command(
            "Modeling.BooleanOperation",
            {"operation": "intersect"},
        )

    def _on_generate_mesh(self) -> None:
        """Handle generate mesh button click."""
        mesh_params = {
            "element_type": self.element_type_combo.currentText(),
            "global_size": self.global_size_spin.value(),
            "max_aspect_ratio": self.max_aspect_ratio_spin.value(),
            "smooth_passes": self.smooth_passes_spin.value(),
        }

        self.controller.execute_command("Modeling.SetMeshParameters", mesh_params)
        self.controller.execute_command("Modeling.GenerateMesh")

    def _on_refine_mesh(self) -> None:
        """Handle refine mesh button click."""
        self.controller.execute_command("Modeling.RefineMesh")

    def _on_optimize_mesh(self) -> None:
        """Handle optimize mesh button click."""
        self.controller.execute_command("Modeling.OptimizeMesh")

    def _on_apply_fixed_constraint(self) -> None:
        """Handle apply fixed constraint button click."""
        surface = self.fixed_surface_combo.currentText()
        self.controller.execute_command(
            "Modeling.ApplyBoundaryConditions",
            {"type": "fixed", "surface": surface},
        )

    def _on_apply_pressure(self) -> None:
        """Handle apply pressure button click."""
        pressure = self.pressure_value_spin.value()
        self.controller.execute_command(
            "Modeling.ApplyLoads",
            {"type": "pressure", "value": pressure},
        )

    def _on_apply_force(self) -> None:
        """Handle apply force button click."""
        force_vector = [
            self.force_x_spin.value(),
            self.force_y_spin.value(),
            self.force_z_spin.value(),
        ]
        self.controller.execute_command(
            "Modeling.ApplyLoads",
            {"type": "force", "vector": force_vector},
        )

    def _on_assign_material(self) -> None:
        """Handle assign material button click."""
        material_name = self.material_assign_combo.currentText()
        self.controller.execute_command(
            "Modeling.AssignMaterial",
            {"material_name": material_name},
        )

    def _on_validate_model(self) -> None:
        """Handle validate model button click."""
        self.controller.execute_command("Modeling.ValidateModel")

    def _on_preview_model(self) -> None:
        """Handle preview model button click."""
        self.controller.execute_command("Modeling.PreviewModel")
