# 제품 등록 페이지 — 기준 이미지 캡처
import cv2
import numpy as np
from PyQt5.QtCore import Qt, QSize
from PyQt5.QtGui import QImage, QPixmap, QColor
from PyQt5.QtWidgets import (
    QWidget, QHBoxLayout, QVBoxLayout, QGroupBox,
    QPushButton, QListWidget, QListWidgetItem, QLabel,
    QMessageBox, QScrollArea, QFrame,
)

from db.sql_client import SQLClient


_GRP_STYLE = (
    "QGroupBox {"
    "  background:#222222; border:1px solid #333333; border-radius:6px;"
    "  margin-top:14px; padding:14px 12px 12px 12px;"
    "}"
    "QGroupBox::title { color:#aaaaaa; subcontrol-origin:margin; left:10px; padding:0 4px; }"
)


class RegisterPage(QWidget):
    def __init__(self, insight_cam, matcher=None, db_client=None, config=None, parent=None):
        super().__init__(parent)
        self._insight      = insight_cam
        self._db_client    = db_client
        self._config       = config or {}
        self._db_items     = []
        self._wk_map       = {}
        self._selected     = None
        self._captured_img = None

        self._build_ui()

    # ================================================================== #
    # UI 구성
    # ================================================================== #

    def _build_ui(self):
        root = QHBoxLayout(self)
        root.setContentsMargins(0, 0, 0, 0)
        root.setSpacing(0)
        root.addWidget(self._build_left_panel(),  stretch=2)
        root.addWidget(self._build_right_panel(), stretch=3)

    def _build_left_panel(self) -> QWidget:
        w = QWidget()
        w.setStyleSheet("background:#1a1a1a;")
        layout = QVBoxLayout(w)
        layout.setContentsMargins(16, 16, 8, 16)
        layout.setSpacing(10)

        self._btn_mes = QPushButton("MES 불러오기")
        self._btn_mes.setVisible(False)
        self._btn_mes.setEnabled(False)
        self._btn_mes.clicked.connect(self._on_load_from_db)
        layout.addWidget(self._btn_mes)

        lbl = QLabel("제품 목록")
        lbl.setStyleSheet("font-size:13px; color:#777777;")
        layout.addWidget(lbl)

        self._list = QListWidget()
        self._list.setStyleSheet("""
            QListWidget {
                background:#222222; border:1px solid #333333;
                border-radius:4px; outline:none; font-size:15px;
            }
            QListWidget::item {
                padding:0px 14px; border-bottom:1px solid #2a2a2a;
            }
        """)
        self._list.currentRowChanged.connect(self._on_select)
        layout.addWidget(self._list, stretch=1)
        return w

    def _build_right_panel(self) -> QScrollArea:
        scroll = QScrollArea()
        scroll.setWidgetResizable(True)
        scroll.setFrameShape(QScrollArea.NoFrame)
        scroll.setStyleSheet("background:#1a1a1a;")

        inner = QWidget()
        inner.setStyleSheet("background:#1a1a1a;")
        layout = QVBoxLayout(inner)
        layout.setContentsMargins(8, 16, 16, 16)
        layout.setSpacing(0)

        layout.addWidget(self._build_detail_section())
        layout.addWidget(_divider())
        layout.addWidget(self._build_capture_section())
        layout.addStretch()

        scroll.setWidget(inner)
        return scroll

    # ── 섹션 1: 제품 상세 ──────────────────────────────────────────────

    def _build_detail_section(self) -> QGroupBox:
        g = QGroupBox("제품 상세 정보")
        g.setStyleSheet(_GRP_STYLE)
        layout = QVBoxLayout(g)
        layout.setSpacing(8)

        self._lbl_name  = _info_value("—")
        self._lbl_model = _info_value("—")
        self._lbl_type  = _info_value("—")
        self._lbl_wk    = _info_value("—")
        self._lbl_machine_id = _info_value("—")
        self._lbl_machine    = _info_value("—")
        self._lbl_work_date  = _info_value("—")
        self._lbl_work_time  = _info_value("—")
        layout.addLayout(_info_row("카테고리", self._lbl_name))
        layout.addLayout(_info_row("모델명",   self._lbl_model))
        layout.addLayout(_info_row("Type",     self._lbl_type))
        layout.addLayout(_info_row("작업상태", self._lbl_wk))
        layout.addLayout(_info_row("설비 ID",  self._lbl_machine_id))
        layout.addLayout(_info_row("설비명",   self._lbl_machine))
        layout.addLayout(_info_row("작업시작일", self._lbl_work_date))
        layout.addLayout(_info_row("작업시작", self._lbl_work_time))

        self._arrow_lbl = QLabel("")
        self._arrow_lbl.setAlignment(Qt.AlignCenter)
        self._arrow_lbl.setFixedHeight(80)
        self._arrow_lbl.setStyleSheet("font-size:60px; background:transparent;")
        layout.addWidget(self._arrow_lbl)
        return g

    # ── 섹션 2: 캡처 ──────────────────────────────────────────────────

    def _build_capture_section(self) -> QGroupBox:
        g = QGroupBox("기준 이미지 캡처")
        g.setStyleSheet(_GRP_STYLE)
        layout = QVBoxLayout(g)
        layout.setSpacing(12)

        btn = QPushButton("캡처 (In-Sight 트리거)")
        btn.setFixedHeight(56)
        btn.setStyleSheet(
            "background:#1a3a5c; color:#ffffff; border:none; border-radius:4px;"
            "font-size:15px; font-weight:bold;"
        )
        btn.clicked.connect(self._on_capture)

        self._preview = QLabel()
        self._preview.setAlignment(Qt.AlignCenter)
        self._preview.setFixedSize(400, 300)
        self._preview.setStyleSheet(
            "background:#111111; color:#555555; border:1px solid #333333;"
            "border-radius:4px; font-size:14px;"
        )
        self._preview.setText("캡처 이미지 없음")

        layout.addWidget(btn)
        layout.addWidget(self._preview, alignment=Qt.AlignHCenter)
        return g

    # ================================================================== #
    # 슬롯
    # ================================================================== #

    def _on_select(self, row: int):
        if row < 0:
            return
        item = self._list.item(row)
        if item is None or not (item.flags() & Qt.ItemIsSelectable):
            return

        article_id = item.data(Qt.UserRole)
        if article_id is None:
            return

        self._refresh_list_styles(row)

        db_item = next(
            (x for x in self._db_items
             if SQLClient._norm_id(x["article_id"]) == SQLClient._norm_id(article_id)),
            None,
        )
        name = item.data(Qt.UserRole + 1) or item.text()
        in_wk = bool(item.data(Qt.UserRole + 2))
        r = {
            "id":    article_id,
            "name":  name,
            "model": db_item.get("buyer_article_no", "") if db_item else "",
            "type":  "",
            "in_wk": in_wk,
        }

        self._selected     = r
        self._captured_img = None

        self._lbl_name.setText(r["name"])
        self._lbl_model.setText(r["model"])
        t = r.get("type", "")
        self._lbl_type.setText(t if t else "—")
        if in_wk:
            self._lbl_wk.setText("작업 대상")
            self._lbl_wk.setStyleSheet("color:#cccccc; font-size:16px; font-weight:bold;")
            wk = self._wk_map.get(SQLClient._norm_id(article_id), {})
            self._lbl_machine_id.setText(SQLClient.format_db_value(wk.get("machine_id")))
            self._lbl_machine.setText(SQLClient.format_db_value(wk.get("machine")))
            self._lbl_work_date.setText(SQLClient.format_db_value(wk.get("work_start_date")))
            self._lbl_work_time.setText(SQLClient.format_db_value(wk.get("work_start_time")))
        else:
            self._lbl_wk.setText("작업 대외")
            self._lbl_wk.setStyleSheet("color:#888888; font-size:16px; font-weight:bold;")
            for lbl in (self._lbl_machine_id, self._lbl_machine,
                        self._lbl_work_date, self._lbl_work_time):
                lbl.setText("—")

        if t == "RH":
            self._arrow_lbl.setText("→")
            self._arrow_lbl.setStyleSheet("font-size:60px; color:#4488ff; background:transparent;")
        elif t == "LH":
            self._arrow_lbl.setText("←")
            self._arrow_lbl.setStyleSheet("font-size:60px; color:#ff8844; background:transparent;")
        else:
            self._arrow_lbl.setText("")

        self._reset_preview()

    def _on_capture(self):
        if self._selected is None:
            QMessageBox.warning(self, "경고", "먼저 제품을 선택하세요.")
            return
        if not self._insight.is_connected():
            QMessageBox.critical(self, "오류", "Cognex 카메라가 연결되어 있지 않습니다.")
            return

        raw = self._insight.trigger_and_get_image()
        if not raw:
            QMessageBox.critical(self, "캡처 실패",
                                 "이미지를 수신하지 못했습니다.\n카메라 연결 상태를 확인하세요.")
            return

        arr = np.frombuffer(raw, dtype=np.uint8)
        img = cv2.imdecode(arr, cv2.IMREAD_UNCHANGED)
        if img is None:
            QMessageBox.critical(self, "캡처 실패", "이미지 디코딩에 실패했습니다.")
            return

        self._captured_img = img
        self._show_ndarray(img)

    def update_db(self, db_client):
        """MainWindow에서 DB 연결/해제 시 호출."""
        self._db_client = db_client
        self.load_products()

    def load_products(self):
        """관리자 설정에서 선택한 MES 제품 목록을 자동으로 불러온다."""
        self._list.clear()
        self._db_items = []
        self._wk_map   = {}
        self._selected = None
        self._lbl_name.setText("—")
        self._lbl_model.setText("—")
        self._lbl_type.setText("—")
        self._lbl_wk.setText("—")
        self._lbl_wk.setStyleSheet("color:#ffffff; font-size:16px; font-weight:bold;")
        for lbl in (self._lbl_machine_id, self._lbl_machine,
                    self._lbl_work_date, self._lbl_work_time):
            lbl.setText("—")
        self._arrow_lbl.setText("")
        self._reset_preview()

        if not self._db_client or not self._db_client.is_connected():
            return

        selected_ids = self._config.get("mes", {}).get("selected_article_ids")
        if selected_ids is not None and len(selected_ids) == 0:
            return

        all_items = self._db_client.get_reflector_list(
            article_ids=selected_ids if selected_ids is not None else None
        )
        if not all_items:
            return

        self._wk_map = self._db_client.get_wk_result_map()
        active, inactive = self._db_client.split_articles_by_wk(selected_ids)

        self._db_items = all_items

        if active:
            self._add_section_header(f"작업 대상 — WK_Result ({len(active)})")
            for item in active:
                self._add_product_item(item, in_wk=True)

        if inactive:
            self._add_section_header(f"기타 ({len(inactive)})")
            for item in inactive:
                self._add_product_item(item, in_wk=False)

        self._refresh_list_styles()

    def _on_load_from_db(self):
        pass

    def _add_section_header(self, text: str):
        hi = QListWidgetItem(text)
        hi.setFlags(Qt.NoItemFlags)
        hi.setForeground(QColor("#aaaaaa"))
        hi.setBackground(QColor("#2a2a2a"))
        hi.setSizeHint(QSize(0, 40))
        self._list.addItem(hi)

    def _add_product_item(self, item: dict, in_wk: bool):
        li = QListWidgetItem(item["article"])
        li.setSizeHint(QSize(0, 52))
        li.setData(Qt.UserRole, item["article_id"])
        li.setData(Qt.UserRole + 1, item["article"])
        li.setData(Qt.UserRole + 2, in_wk)
        if in_wk:
            wk = self._wk_map.get(SQLClient._norm_id(item["article_id"]), {})
            tips = []
            if wk.get("machine_id") is not None:
                tips.append(f"설비 ID: {SQLClient.format_db_value(wk.get('machine_id'))}")
            if wk.get("machine") is not None:
                tips.append(f"설비: {SQLClient.format_db_value(wk.get('machine'))}")
            if wk.get("work_start_date") is not None:
                tips.append(f"시작일: {SQLClient.format_db_value(wk.get('work_start_date'))}")
            if wk.get("work_start_time") is not None:
                tips.append(f"시작: {SQLClient.format_db_value(wk.get('work_start_time'))}")
            if tips:
                li.setToolTip("\n".join(tips))
        self._list.addItem(li)
        self._style_product_item(li, in_wk, selected=False)

    @staticmethod
    def _style_product_item(item: QListWidgetItem, in_wk: bool, selected: bool):
        if in_wk:
            if selected:
                bg, fg = "#777777", "#ffffff"
            else:
                bg, fg = "#555555", "#eeeeee"
        elif selected:
            bg, fg = "#3a3a3a", "#aaaaaa"
        else:
            bg, fg = "#1e1e1e", "#666666"
        item.setBackground(QColor(bg))
        item.setForeground(QColor(fg))

    def _refresh_list_styles(self, selected_row: int = -1):
        if selected_row < 0:
            selected_row = self._list.currentRow()
        for i in range(self._list.count()):
            item = self._list.item(i)
            if not (item.flags() & Qt.ItemIsSelectable):
                continue
            in_wk = bool(item.data(Qt.UserRole + 2))
            self._style_product_item(item, in_wk, selected=(i == selected_row))

    # ================================================================== #
    # 헬퍼
    # ================================================================== #

    def _show_ndarray(self, img: np.ndarray):
        h_img, w_img = img.shape[:2]
        if img.ndim == 2:
            qimg = QImage(img.data, w_img, h_img, w_img, QImage.Format_Grayscale8)
        else:
            rgb  = np.ascontiguousarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
            qimg = QImage(rgb.data, w_img, h_img, w_img * 3, QImage.Format_RGB888)
        pix = QPixmap.fromImage(qimg).scaled(400, 300, Qt.KeepAspectRatio, Qt.SmoothTransformation)
        self._preview.setPixmap(pix)
        self._preview.setText("")

    def _reset_preview(self):
        self._preview.clear()
        self._preview.setText("캡처 이미지 없음")


# ================================================================== #
# 모듈 수준 유틸리티
# ================================================================== #

def _divider() -> QFrame:
    f = QFrame()
    f.setFrameShape(QFrame.HLine)
    f.setFixedHeight(1)
    f.setStyleSheet("background:#333333; border:none;")
    return f


def _info_value(text: str) -> QLabel:
    lbl = QLabel(text)
    lbl.setStyleSheet("color:#ffffff; font-size:16px; font-weight:bold;")
    return lbl


def _info_row(label: str, value_widget: QLabel) -> QHBoxLayout:
    row = QHBoxLayout()
    key = QLabel(label + ":")
    key.setFixedWidth(80)
    key.setStyleSheet("color:#888888; font-size:14px;")
    row.addWidget(key)
    row.addWidget(value_widget, stretch=1)
    return row
