import os
import json
import re
from PyQt6.QtWidgets import (QWidget, QHBoxLayout, QVBoxLayout, 
                             QPushButton, QLabel, QFrame, QGraphicsView,
                             QGraphicsScene, QGraphicsPathItem, QProgressBar)
from PyQt6.QtCore import Qt, QTimer, QThread, pyqtSignal, QUrl, QObject, pyqtProperty, QRectF, QSize
from PyQt6.QtGui import QColor, QPen, QPainter, QPainterPath, QFont, QLinearGradient, QBrush
from utils.config_parse import ConfigParse
import sys
import os
from utils.gcode_viewer import GCodeViewerWidget



# ── 状态主题色 ──────────────────────────────────────────
STATUS_COLORS = {
    "Operational": "#4CAF50",
    "Printing":    "#2196F3",
    "Paused":      "#FF9800",
    "Error":       "#F44336",
    "Offline":     "#9E9E9E",
    "Cancelling":  "#FF5722",
    "Finishing":   "#8BC34A",
}
STATUS_LABELS = {
    "Operational": "就绪",
    "Printing":    "打印中",
    "Paused":      "已暂停",
    "Error":       "错误",
    "Offline":     "离线",
    "Cancelling":  "取消中",
    "Finishing":   "整理中",
}


class CardFrame(QFrame):
    """统一的信息卡片样式"""

    def __init__(self, title="", parent=None):
        super().__init__(parent)
        self.setStyleSheet("""
            CardFrame {
                background-color: #3a3a3a;
                border: 1px solid #555555;
                border-radius: 8px;
            }
        """)
        layout = QVBoxLayout(self)
        layout.setContentsMargins(12, 10, 12, 10)
        layout.setSpacing(4)

        if title:
            title_lbl = QLabel(title)
            title_lbl.setStyleSheet("color: #aaaaaa; font-size: 13px; font-weight: 500; border: none;")
            layout.addWidget(title_lbl)

        self.content_layout = layout

    def add_row(self, label, value_widget):
        row = QHBoxLayout()
        row.setSpacing(8)
        lbl = QLabel(label)
        lbl.setStyleSheet("color: #cccccc; font-size: 15px; border: none;")
        lbl.setFixedWidth(70)
        row.addWidget(lbl)
        row.addWidget(value_widget, 1)
        self.content_layout.addLayout(row)


class TempGauge(QWidget):
    """温度计指示器"""

    def __init__(self, label="Tool", parent=None):
        super().__init__(parent)
        self.setFixedSize(100, 80)
        self._label = label
        self._actual = 0.0
        self._target = 0.0

    def set_value(self, actual, target):
        self._actual = actual
        self._target = target
        self.update()

    def paintEvent(self, event):
        p = QPainter(self)
        p.setRenderHint(QPainter.RenderHint.Antialiasing)
        w, h = self.width(), self.height()

        # 背景条
        bar_x, bar_w = 16, 20
        bar_y, bar_h = 10, 56
        p.setPen(QPen(QColor("#555555"), 1))
        p.setBrush(QBrush(QColor("#2a2a2a")))
        p.drawRoundedRect(bar_x, bar_y, bar_w, bar_h, 4, 4)

        # 填充柱（按温度比例，最高 300°C）
        ratio = min(max(self._actual / 300, 0), 1)
        fill_h = int((bar_h - 4) * ratio)
        if fill_h > 0:
            grad = QLinearGradient(0, bar_y + bar_h, 0, bar_y)
            grad.setColorAt(0, QColor("#f57c00"))
            grad.setColorAt(1, QColor("#e53935") if self._actual > 200 else QColor("#ffb74d"))
            p.setBrush(QBrush(grad))
            p.setPen(Qt.PenStyle.NoPen)
            p.drawRoundedRect(bar_x + 2, bar_y + bar_h - 2 - fill_h, bar_w - 4, fill_h, 3, 3)

        # 目标值标记线
        if self._target > 0:
            tgt_y = bar_y + bar_h - int((bar_h - 4) * min(self._target / 300, 1))
            p.setPen(QPen(QColor("#ffffff"), 2))
            p.drawLine(bar_x - 2, tgt_y, bar_x + bar_w + 2, tgt_y)

        # 文字
        font = QFont("sans-serif", 11, QFont.Weight.Bold)
        p.setFont(font)
        p.setPen(QPen(QColor("#e0e0e0")))
        p.drawText(44, 16, w - 44, 24, Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter,
                   f"{self._actual:.0f}°")
        if self._target > 0:
            font2 = QFont("sans-serif", 10)
            p.setFont(font2)
            p.setPen(QPen(QColor("#888888")))
            p.drawText(44, 34, w - 44, 20, Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter,
                       f"→ {self._target:.0f}°")

        font3 = QFont("sans-serif", 10, QFont.Weight.Bold)
        p.setFont(font3)
        p.setPen(QPen(QColor("#aaaaaa")))
        p.drawText(0, h - 20, w, 20, Qt.AlignmentFlag.AlignCenter, self._label)



# ── 状态页面 ────────────────────────────────────────────
class StatusPage(QWidget):
    def __init__(self, api_client, parent=None):
        super().__init__(parent)
        self.api_client = api_client

        self.file_name = "None"
        self.progress = 0.0
        self.filepos = 0
        self.display_name = "None"
        self.state = "Unknown"
        self.print_time = 0
        self.print_time_left = 0
        self.tool_temp_actual = 0.0
        self.tool_temp_target = 0.0
        self.bed_temp_actual = 0.0
        self.bed_temp_target = 0.0

        self.config_parser = ConfigParse()
        self.config_parser.config_changed.connect(self._on_config_changed)
        self.gcode_dir = self.config_parser.gcode_dir
        self._loaded_file = None

        self.init_ui()
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update_status)
        self.timer.start(1000)
        self.update_status()

    def _on_config_changed(self, config_instance):
        self.gcode_dir = self.config_parser.gcode_dir

    def fresh_status_valve(self):
        data = self.api_client.get_status()
        if data:
            status = data.get("status", {})
            job = data.get("job", {})
            self.file_name = job.get("job", {}).get("file", {}).get("name", "None")
            self.progress = job.get("progress", {}).get("completion", 0) or 0
            self.filepos = job.get("progress", {}).get("filepos", 0) or 0
            self.display_name = job.get("job", {}).get("file", {}).get("display_name", "None")
            self.state = status.get("state", {}).get("text", "Offline")
            self.print_time = job.get("progress", {}).get("printTime", 0) or 0
            self.print_time_left = job.get("progress", {}).get("printTimeLeft", 0) or 0
            temp = status.get("temperature", {})
            self.tool_temp_actual = (temp.get("tool0", {}) or {}).get("actual", 0) or 0
            self.tool_temp_target = (temp.get("tool0", {}) or {}).get("target", 0) or 0
            self.bed_temp_actual = (temp.get("bed", {}) or {}).get("actual", 0) or 0
            self.bed_temp_target = (temp.get("bed", {}) or {}).get("target", 0) or 0

    @staticmethod
    def format_time(seconds):
        if seconds is None or seconds == 0:
            return "N/A"
        m, s = divmod(int(seconds), 60)
        h, m = divmod(m, 60)
        if h > 0:
            return f"{h}h {m:02d}m {s:02d}s"
        elif m > 0:
            return f"{m}m {s:02d}s"
        else:
            return f"{s}s"

    def _make_card(self, title=""):
        card = CardFrame(title)
        return card

    def _truncate(self, text, max_len=22):
        return text if len(text) <= max_len else text[:max_len - 2] + "…"

    def init_ui(self):
        self.fresh_status_valve()
        main_layout = QHBoxLayout(self)
        main_layout.setContentsMargins(8, 8, 8, 8)
        main_layout.setSpacing(8)

        # ── 左侧信息面板 ──────────────────────────────────
        left_frame = QFrame()
        left_frame.setStyleSheet("background-color: #333333; border-radius: 10px;")
        left_layout = QVBoxLayout(left_frame)
        left_layout.setContentsMargins(10, 10, 10, 10)
        left_layout.setSpacing(6)

        # — 状态徽章 —
        self._status_badge = QLabel()
        self._status_badge.setFixedHeight(40)
        self._status_badge.setAlignment(Qt.AlignmentFlag.AlignCenter)
        font_badge = QFont("sans-serif", 18, QFont.Weight.Bold)
        self._status_badge.setFont(font_badge)
        left_layout.addWidget(self._status_badge)

        # — 文件信息卡片 —
        self._file_card = CardFrame("当前文件")
        self._file_name_lbl = QLabel("--")
        self._file_name_lbl.setStyleSheet("color: #ffffff; font-size: 16px; font-weight: 600; border: none;")
        self._file_name_lbl.setWordWrap(True)
        self._file_card.content_layout.addWidget(self._file_name_lbl)
        left_layout.addWidget(self._file_card)

        # — 进度卡片 —
        self._progress_card = CardFrame("打印进度")
        # 进度条
        self._progress_bar = QProgressBar()
        self._progress_bar.setTextVisible(True)
        self._progress_bar.setFixedHeight(28)
        self._progress_bar.setStyleSheet("""
            QProgressBar {
                background-color: #2a2a2a;
                border: 1px solid #555;
                border-radius: 6px;
                text-align: center;
                color: white;
                font-size: 14px;
                font-weight: bold;
            }
            QProgressBar::chunk {
                background-color: #4CAF50;
                border-radius: 5px;
            }
        """)
        self._progress_card.content_layout.addWidget(self._progress_bar)
        # 时间行
        time_row = QHBoxLayout()
        time_row.setSpacing(10)
        self._time_elapsed_lbl = QLabel("已用: --")
        self._time_elapsed_lbl.setStyleSheet("color: #bbbbbb; font-size: 14px; border: none;")
        self._time_left_lbl = QLabel("剩余: --")
        self._time_left_lbl.setStyleSheet("color: #bbbbbb; font-size: 14px; border: none;")
        time_row.addWidget(self._time_elapsed_lbl)
        time_row.addStretch()
        time_row.addWidget(self._time_left_lbl)
        self._progress_card.content_layout.addLayout(time_row)
        left_layout.addWidget(self._progress_card)

        # — 温度卡片 —
        self._temp_card = CardFrame("温度")
        temp_row = QHBoxLayout()
        temp_row.setSpacing(8)
        self._tool_gauge = TempGauge("喷头")
        self._bed_gauge = TempGauge("热床")
        temp_row.addWidget(self._tool_gauge)
        temp_row.addWidget(self._bed_gauge)
        temp_row.addStretch()
        self._temp_card.content_layout.addLayout(temp_row)
        left_layout.addWidget(self._temp_card)

        left_layout.addStretch()

        # ── 右侧预留区域 ─────────────────────────────
        right_frame = QFrame()
        right_frame.setStyleSheet("background-color: #3a3a3a; border-radius: 10px;")
        right_layout = QVBoxLayout(right_frame)
        right_layout.setContentsMargins(6, 6, 6, 6)

        self.gcode_viewer = GCodeViewerWidget()
        right_layout.addWidget(self.gcode_viewer)

        main_layout.addWidget(left_frame, 2)
        main_layout.addWidget(right_frame, 3)

    def update_status(self):
        self.fresh_status_valve()

        # 状态徽章
        status_key = self.state.split()[0] if self.state else "Offline"
        color = STATUS_COLORS.get(status_key, "#9E9E9E")
        label = STATUS_LABELS.get(status_key, self.state)
        self._status_badge.setText(f"● {label}")
        self._status_badge.setStyleSheet(
            f"background-color: #2a2a2a; color: {color}; "
            f"border: 2px solid {color}; border-radius: 8px; "
            f"font-size: 18px; font-weight: bold; padding: 4px;"
        )

        # 文件
        self._file_name_lbl.setText(self._truncate(self.display_name, 28))

        # 进度
        prog = min(max(self.progress, 0), 100)
        self._progress_bar.setValue(int(prog))
        self._progress_bar.setFormat(f"{prog:.1f}%")
        self._time_elapsed_lbl.setText(f"已用: {self.format_time(self.print_time)}")
        self._time_left_lbl.setText(f"剩余: {self.format_time(self.print_time_left)}")
        # 打印中时进度条变蓝
        if self.state.startswith("Printing"):
            self._progress_bar.setStyleSheet("""
                QProgressBar {
                    background-color: #2a2a2a;
                    border: 1px solid #555;
                    border-radius: 6px;
                    text-align: center;
                    color: white;
                    font-size: 14px;
                    font-weight: bold;
                }
                QProgressBar::chunk {
                    background-color: #2196F3;
                    border-radius: 5px;
                }
            """)
        else:
            self._progress_bar.setStyleSheet("""
                QProgressBar {
                    background-color: #2a2a2a;
                    border: 1px solid #555;
                    border-radius: 6px;
                    text-align: center;
                    color: white;
                    font-size: 14px;
                    font-weight: bold;
                }
                QProgressBar::chunk {
                    background-color: #4CAF50;
                    border-radius: 5px;
                }
            """)

        # 温度
        self._tool_gauge.set_value(self.tool_temp_actual, self.tool_temp_target)
        self._bed_gauge.set_value(self.bed_temp_actual, self.bed_temp_target)

        # G-code 模型加载与进度更新
        if self.file_name and self.file_name != "None":
            if self.file_name != self._loaded_file:
                gcode_path = os.path.join(self.gcode_dir, self.file_name)
                if os.path.exists(gcode_path):
                    try:
                        self.gcode_viewer.load_gcode(gcode_path)
                        self._loaded_file = self.file_name
                    except Exception as e:
                        print("Failed to load G-code:", e)
            
            # 使用 filepos 替代进度百分比进行精准的偏移量层级更新
            if self._loaded_file == self.file_name:
                is_printing = self.state.startswith("Printing") or self.state.startswith("Paused")
                self.gcode_viewer.update_by_filepos(self.filepos, is_printing)



    #TODO: Better Gcode Parser, this one is too slow for large files, need to optimize or use a separate thread to load
    # def load_gcode_vertices(self, path):
    #     vertices = []

    #     x = 0
    #     y = 0
    #     z = 0

    #     with open(path, "r", encoding="utf-8", errors="ignore") as f:
    #         for line in f:
    #             line = line.strip()

    #             if not line:
    #                 continue

    #             if line.startswith("G0") or line.startswith("G1"):
    #                 old_x = x
    #                 old_y = y
    #                 old_z = z

    #                 mx = re.search(r"X([-0-9.]+)", line)
    #                 my = re.search(r"Y([-0-9.]+)", line)
    #                 mz = re.search(r"Z([-0-9.]+)", line)

    #                 if mx:
    #                     x = float(mx.group(1))

    #                 if my:
    #                     y = float(my.group(1))

    #                 if mz:
    #                     z = float(mz.group(1))

    #                 vertices.append({
    #                     "x1": old_x,
    #                     "y1": old_y,
    #                     "z1": old_z,
    #                     "x2": x,
    #                     "y2": y,
    #                     "z2": z,
    #                 })

    #     return vertices
