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

from qtpy.QtCore import Qt
from qtpy.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.forge_engine.network_export import export_validated_build
from shireforge.generators.calibration_cube import CubeParameters
from shireforge.viewer.mesh_loader import load_preview_mesh


class ForgePage(QWidget):
    def __init__(
        self,
        *,
        embedded: bool = False,
        auto_build: bool = True,
    ) -> None:
        super().__init__()
        self.embedded = bool(embedded)
        self.auto_build = bool(auto_build)
        layout = QVBoxLayout(self)
        layout.setContentsMargins(12, 12, 12, 8)

        header = QHBoxLayout()
        title = QLabel("FORGE" if self.embedded else "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.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)

        if not self.embedded:
            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;
            }
        """)

        if self.auto_build:
            self.activate()

    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)
        self.viewer.set_background("#090812", top="#1b1029")
        box.addWidget(self.viewer.interactor, 1)

        self.stats = QLabel()
        self.stats.setAlignment(Qt.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 TO SHiREVAULT READY")
        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 activate(self) -> None:
        """Create the initial model only when Forge is first opened."""
        if self.current_build is None:
            self.rebuild_model()

    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="#b66b39",
                ambient=0.28,
                diffuse=0.82,
                specular=0.10,
                specular_power=10,
                smooth_shading=True,
                show_edges=True,
                edge_color="#28140d",
                line_width=1,
            )
            self.viewer.show_grid(color="#59406f")
            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

        self.status.setText("●  EXPORTING TO SHiREVAULT")
        self.export_button.setEnabled(False)
        QApplication.processEvents()

        try:
            exported = export_validated_build(self.current_build)
            ready_path = (
                "/SHiREVault/SHiREForge/Ready/"
                f"{self.current_build.build_id}"
            )

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

        except Exception as error:
            self.status.setText("●  NETWORK EXPORT FAILED")
            self.export_button.setEnabled(True)
            self.conversation.append(
                "<br><b style='color:#ff6b6b'>Export blocked</b><br>"
                f"{html.escape(str(error))}<br>"
                "No local fallback was used."
            )

    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 shutdown(self) -> None:
        viewer = getattr(self, "viewer", None)
        if viewer is not None:
            viewer.close()
            self.viewer = None

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