import argparse
import html
from pathlib import Path
import shutil
import sys

from PySide6.QtCore import Qt
from PySide6.QtWidgets import (
    QApplication,
    QDoubleSpinBox,
    QFormLayout,
    QFrame,
    QHBoxLayout,
    QLabel,
    QLineEdit,
    QListWidget,
    QMainWindow,
    QPushButton,
    QSplitter,
    QTextBrowser,
    QVBoxLayout,
    QWidget,
)
from pyvistaqt import QtInteractor

from shireforge.forge_engine.build_service import build_calibration_cube
from shireforge.generators.calibration_cube import CubeParameters
from shireforge.viewer.mesh_loader import load_preview_mesh


class ForgeWindow(QMainWindow):
    def __init__(self) -> None:
        super().__init__()
        self.setWindowTitle("SHiRE Forge")
        self.resize(1600, 900)
        self.setMinimumSize(1280, 720)

        root = QWidget()
        layout = QVBoxLayout(root)
        layout.setContentsMargins(12, 12, 12, 8)
        self.setCentralWidget(root)

        header = QHBoxLayout()
        title = QLabel("SHiRE  •  FORGE")
        title.setObjectName("title")
        self.status = QLabel("●  LOCAL MODE")
        self.status.setObjectName("status")
        header.addWidget(title)
        header.addStretch()
        header.addWidget(self.status)
        layout.addLayout(header)

        splitter = QSplitter(Qt.Orientation.Horizontal)
        splitter.addWidget(self._conversation_panel())
        splitter.addWidget(self._viewport_panel())
        splitter.addWidget(self._workflow_panel())
        splitter.setSizes([360, 850, 390])
        layout.addWidget(splitter, 1)

        nav = QHBoxLayout()
        for name in ("SHiRE", "FORGE", "SENTINEL", "STATIONS"):
            button = QPushButton(name)
            button.setEnabled(name == "FORGE")
            nav.addWidget(button)
        layout.addLayout(nav)

        self.current_build = None

        self.setStyleSheet("""
            QWidget {
                background: #130f0c;
                color: #eadfd2;
                font-family: Sans Serif;
                font-size: 14px;
            }
            QFrame {
                background: #201813;
                border: 1px solid #5b3825;
                border-radius: 8px;
            }
            QLabel#title {
                color: #ff9c45;
                font-size: 24px;
                font-weight: 700;
            }
            QLabel#status {
                color: #78d69b;
                font-weight: 700;
            }
            QPushButton {
                background: #3b2418;
                border: 1px solid #9c5529;
                border-radius: 6px;
                padding: 8px 12px;
            }
            QPushButton:hover {
                background: #56301d;
            }
            QPushButton:disabled {
                color: #70645c;
                border-color: #44372f;
            }
            QLineEdit, QDoubleSpinBox, QTextBrowser, QListWidget {
                background: #100d0b;
                border: 1px solid #5b3825;
                border-radius: 5px;
                padding: 6px;
            }
        """)

        self.rebuild_model()

    def _conversation_panel(self) -> QWidget:
        panel = QFrame()
        box = QVBoxLayout(panel)
        box.addWidget(QLabel("CONVERSATION"))

        self.conversation = QTextBrowser()
        self.conversation.setHtml(
            "<b style='color:#ff9c45'>SHiRE</b><br>"
            "Forge foundation online.<br><br>"
            "Adjust the cube parameters and rebuild the real model."
        )
        box.addWidget(self.conversation, 1)

        self.prompt = QLineEdit()
        self.prompt.setPlaceholderText("Describe what you want to create…")
        self.prompt.returnPressed.connect(self.submit_prompt)
        box.addWidget(self.prompt)

        send = QPushButton("SEND REQUEST")
        send.clicked.connect(self.submit_prompt)
        box.addWidget(send)
        return panel

    def _viewport_panel(self) -> QWidget:
        panel = QFrame()
        box = QVBoxLayout(panel)

        controls = QHBoxLayout()
        controls.addWidget(QLabel("REAL 3D VIEWPORT"))
        controls.addStretch()

        fit_button = QPushButton("FIT MODEL")
        fit_button.clicked.connect(self.fit_model)
        controls.addWidget(fit_button)

        reset_button = QPushButton("RESET CAMERA")
        reset_button.clicked.connect(self.reset_camera)
        controls.addWidget(reset_button)
        box.addLayout(controls)

        self.viewer = QtInteractor(panel)
        box.addWidget(self.viewer.interactor, 1)

        self.stats = QLabel()
        self.stats.setAlignment(Qt.AlignmentFlag.AlignCenter)
        box.addWidget(self.stats)
        return panel

    def _workflow_panel(self) -> QWidget:
        panel = QFrame()
        box = QVBoxLayout(panel)
        box.addWidget(QLabel("WORKFLOW"))

        self.stages = QListWidget()
        self.stages.addItems([
            "✓ Request",
            "✓ Requirements analysis",
            "✓ Shape plan",
            "✓ Parametric build",
            "✓ Model preview",
            "○ Print validation",
            "○ STL export",
        ])
        box.addWidget(self.stages)

        box.addWidget(QLabel("MODEL PARAMETERS"))
        form = QFormLayout()

        self.width = self._dimension_input()
        self.depth = self._dimension_input()
        self.height = self._dimension_input()

        form.addRow("Width (mm)", self.width)
        form.addRow("Depth (mm)", self.depth)
        form.addRow("Height (mm)", self.height)
        box.addLayout(form)

        rebuild = QPushButton("REBUILD MODEL")
        rebuild.clicked.connect(self.rebuild_model)
        box.addWidget(rebuild)

        self.export_button = QPushButton("EXPORT STL + STEP")
        self.export_button.setEnabled(False)
        self.export_button.clicked.connect(self.export_current_model)
        box.addWidget(self.export_button)
        box.addStretch()
        return panel

    @staticmethod
    def _dimension_input() -> QDoubleSpinBox:
        field = QDoubleSpinBox()
        field.setRange(1.0, 500.0)
        field.setDecimals(1)
        field.setValue(20.0)
        field.setSingleStep(1.0)
        return field

    def rebuild_model(self) -> None:
        self.status.setText("●  BUILDING")
        self.export_button.setEnabled(False)
        QApplication.processEvents()

        try:
            parameters = CubeParameters(
                width=self.width.value(),
                depth=self.depth.value(),
                height=self.height.value(),
            )
            result = build_calibration_cube(parameters)
            mesh = load_preview_mesh(result.stl_path)
            validation = result.validation

            self.viewer.clear()
            self.viewer.add_mesh(
                mesh,
                color="#c96b2c",
                show_edges=True,
                edge_color="#2b160d",
            )
            self.viewer.show_grid()
            self.viewer.add_axes()
            self.viewer.view_isometric()
            self.viewer.reset_camera()

            width, depth, height = validation.dimensions
            self.stats.setText(
                f"{width:.1f} × {depth:.1f} × {height:.1f} mm"
                f"   •   {validation.triangle_count} triangles"
                f"   •   Volume {validation.volume:.1f} mm³"
                f"   •   Surface {validation.surface_area:.1f} mm²"
                f"   •   Watertight {validation.watertight}"
            )

            self.current_build = result
            self.export_button.setEnabled(validation.passed)

            if validation.passed:
                self.status.setText("●  VALIDATED")
                self.stages.item(5).setText("✓ Print validation")
                self.stages.item(6).setText("○ STL export")
            else:
                self.status.setText("●  VALIDATION WARNING")
                self.stages.item(5).setText("⚠ Print validation")

        except Exception as error:
            self.current_build = None
            self.status.setText("●  BUILD FAILED")
            self.stats.setText(f"Build failed: {error}")
            self.stages.item(3).setText("✕ Parametric build")
            self.stages.item(4).setText("○ Model preview")
            self.stages.item(5).setText("○ Print validation")

    def export_current_model(self) -> None:
        if self.current_build is None:
            return

        if not self.current_build.validation.passed:
            self.status.setText("●  EXPORT BLOCKED")
            return

        export_dir = (
            Path.home()
            / "SHiREForge-Dev"
            / "workspace"
            / "exports"
            / self.current_build.build_id
        )
        export_dir.mkdir(parents=True, exist_ok=False)

        stl_target = export_dir / self.current_build.stl_path.name
        step_target = export_dir / self.current_build.step_path.name

        shutil.copy2(self.current_build.stl_path, stl_target)
        shutil.copy2(self.current_build.step_path, step_target)

        self.stages.item(6).setText("✓ STL export")
        self.status.setText("●  EXPORT COMPLETE")
        self.export_button.setEnabled(False)
        self.conversation.append(
            "<br><b style='color:#ff9c45'>SHiRE</b><br>"
            f"Validated STL and STEP exported to:<br>{html.escape(str(export_dir))}"
        )

    def submit_prompt(self) -> None:
        text = self.prompt.text().strip()
        if not text:
            return

        self.conversation.append(
            f"<br><b style='color:#e8c29a'>You</b><br>{html.escape(text)}"
        )
        self.conversation.append(
            "<br><b style='color:#ff9c45'>SHiRE</b><br>"
            "Request recorded. Natural-language planning arrives in Phase 3."
        )
        self.prompt.clear()

    def fit_model(self) -> None:
        self.viewer.reset_camera()

    def reset_camera(self) -> None:
        self.viewer.view_isometric()
        self.viewer.reset_camera()

    def closeEvent(self, event) -> None:
        self.viewer.close()
        super().closeEvent(event)


def main() -> int:
    parser = argparse.ArgumentParser(description="Launch SHiRE Forge")
    parser.add_argument("--version", action="store_true")
    args = parser.parse_args()

    if args.version:
        print("SHiRE Forge 0.1.0")
        return 0

    app = QApplication(sys.argv)
    window = ForgeWindow()
    window.show()
    return app.exec()


if __name__ == "__main__":
    raise SystemExit(main())
