"""
Right-side panel: tabbed previews for Sync XML, POST JSON, block details,
warnings, and live log output.
"""
from __future__ import annotations

import json as _json
from datetime import datetime

from PySide6.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QTabWidget, QTextEdit,
)
from PySide6.QtGui import QFont, QColor, QPalette, QTextCursor, QTextCharFormat

from seq_interp.src.gui.adapters import BlockRow


_MONO = QFont("Courier New", 9)

# Tab indices (keep in sync with addTab order below)
_TAB_DETAILS  = 0
_TAB_WARNINGS = 1
_TAB_XML      = 2
_TAB_JSON     = 3
_TAB_LOG      = 4


class PreviewPanel(QWidget):
    def __init__(self, parent: QWidget | None = None):
        super().__init__(parent)
        layout = QVBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)

        self.tabs = QTabWidget()
        layout.addWidget(self.tabs)

        self._detail_edit = self._make_edit(
            "Click a block in the scheme, plot or table to see details..."
        )
        self.tabs.addTab(self._detail_edit, "Block Details")   # 0

        self._warn_edit = self._make_edit("No warnings yet.")
        self.tabs.addTab(self._warn_edit, "Warnings")           # 1

        self._xml_edit = self._make_edit(
            "Run interpretation to populate XML preview..."
        )
        self.tabs.addTab(self._xml_edit, "Sync XML")            # 2

        self._json_edit = self._make_edit(
            "Export artifacts to populate POST JSON preview..."
        )
        self.tabs.addTab(self._json_edit, "POST JSON")          # 3

        self._log_edit = self._make_edit("")
        self._log_edit.setLineWrapMode(QTextEdit.WidgetWidth)
        self.tabs.addTab(self._log_edit, "Log")                 # 4

    # -- block details ---------------------------------------------------------

    def show_block_details(self, row: BlockRow | None) -> None:
        if row is None:
            self._detail_edit.clear()
            return
        lines = [
            f"Sync index    : {row.sync_index}",
            f"Orig index    : {row.orig_index if row.orig_index >= 0 else '- (inserted)'}",
            f"Type          : {row.block_type}",
            f"Duration      : {row.duration * 1e6:.4f} uss",
            f"T start       : {row.t_start * 1e6:.4f} uss",
            f"T end         : {row.t_end * 1e6:.4f} uss",
            f"Is delay      : {row.is_delay}  ({row.delay_type or '-'})",
            "-" * 32,
            f"Gate RF       : {row.gate_rf}",
            f"Gate ADC      : {row.gate_adc}",
            f"Gate TR       : {row.gate_tr}",
            "-" * 32,
            f"Has RF        : {row.has_rf}",
            f"Has ADC       : {row.has_adc}",
            f"Has Grad      : {row.has_grad}",
        ]
        self._detail_edit.setPlainText("\n".join(lines))
        self.tabs.setCurrentIndex(_TAB_DETAILS)

    # -- warnings --------------------------------------------------------------

    def set_warnings(self, warnings: list[str]) -> None:
        if warnings:
            self._warn_edit.setPlainText("\n".join(f"WARN  {w}" for w in warnings))
            self.tabs.setTabText(_TAB_WARNINGS, f"Warnings ({len(warnings)})")
        else:
            self._warn_edit.setPlainText("No warnings.")
            self.tabs.setTabText(_TAB_WARNINGS, "Warnings")

    def add_error(self, msg: str) -> None:
        current = self._warn_edit.toPlainText()
        self._warn_edit.setPlainText(
            (current + "\n" if current else "") + f"ERR  {msg}"
        )
        n = self._warn_edit.toPlainText().count("\n") + 1
        self.tabs.setTabText(_TAB_WARNINGS, f"Warnings ({n})")
        self.tabs.setCurrentIndex(_TAB_WARNINGS)

    # -- xml / json previews ---------------------------------------------------

    def set_xml_text(self, text: str) -> None:
        self._xml_edit.setPlainText(text)

    def set_post_json(self, data: dict) -> None:
        self._json_edit.setPlainText(_json.dumps(data, indent=2, default=str))

    def set_post_json_text(self, text: str) -> None:
        self._json_edit.setPlainText(text)

    # -- log -------------------------------------------------------------------

    def append_log(self, msg: str, error: bool = False) -> None:
        ts   = datetime.now().strftime("%H:%M:%S")
        line = f"[{ts}] {msg}"
        cursor = self._log_edit.textCursor()
        cursor.movePosition(QTextCursor.End)
        fmt = QTextCharFormat()
        if error:
            fmt.setForeground(QColor("#ef5350"))
        else:
            fmt.setForeground(QApplication.palette().color(QPalette.Text))
        cursor.setCharFormat(fmt)
        cursor.insertText(line + "\n")
        self._log_edit.setTextCursor(cursor)
        self._log_edit.ensureCursorVisible()

    def clear_log(self) -> None:
        self._log_edit.clear()

    # -- helpers ---------------------------------------------------------------

    @staticmethod
    def _make_edit(placeholder: str = "") -> QTextEdit:
        edit = QTextEdit()
        edit.setReadOnly(True)
        edit.setFont(_MONO)
        edit.setLineWrapMode(QTextEdit.NoWrap)
        if placeholder:
            edit.setPlaceholderText(placeholder)
        return edit
