"""Theme system for Encrypted Chat GUI — light + dark mode with live switching."""

from __future__ import annotations

import json
import logging
import os
from dataclasses import dataclass, fields
from pathlib import Path
from typing import Callable

logger = logging.getLogger(__name__)


@dataclass(frozen=True)
class ThemeColors:
    """All colour tokens for one theme."""

    # Surface hierarchy
    bg_primary: str      # Main background (messages area, right panel)
    bg_secondary: str    # Cards, inputs, elevated surfaces
    bg_tertiary: str     # Sidebar, deeper surfaces
    bg_hover: str        # Hover state on list items
    bg_selected: str     # Selected list item

    # Text
    text_primary: str    # Main text
    text_secondary: str  # Secondary / muted text
    text_muted: str      # Timestamps, counters, hints

    # Accent (brand blue)
    accent: str
    accent_hover: str
    accent_text: str     # Text on accent background

    # Message bubbles
    bubble_sent_bg: str
    bubble_sent_text: str
    bubble_recv_bg: str
    bubble_recv_text: str
    bubble_sent_meta: str   # Timestamp/read inside sent bubble
    bubble_recv_meta: str   # Timestamp inside received bubble

    # Semantic colours
    success: str
    warning: str
    error: str
    info: str

    # Chrome / borders
    border: str
    border_focus: str
    scrollbar: str
    separator: str
    overlay: str         # Privacy overlay background (rgba)

    # Links
    link_https: str
    link_http: str       # Insecure link (orange)

    # Mentions & search
    mention: str
    search_highlight: str
    search_current: str

    # Reactions
    reaction_bg: str
    reaction_bg_own: str
    reaction_border: str
    reaction_border_own: str

    # Misc
    online_dot: str
    online_dot_border: str
    pin_color: str
    sender_name_other: str  # Non-self sender name colour in groups
    receipt_read: str        # Read receipt checkmarks (must contrast with sent bubble bg)


# ---------------------------------------------------------------------------
# Dark theme — Catppuccin Mocha palette
# ---------------------------------------------------------------------------

DARK_THEME = ThemeColors(
    bg_primary="#1e1e2e",
    bg_secondary="#313244",
    bg_tertiary="#181825",
    bg_hover="#252536",
    bg_selected="#313244",

    text_primary="#cdd6f4",
    text_secondary="#bac2de",
    text_muted="#6c7086",

    accent="#89b4fa",
    accent_hover="#74c7ec",
    accent_text="#1e1e2e",

    bubble_sent_bg="#2a4a7f",
    bubble_sent_text="#cdd6f4",
    bubble_recv_bg="#2c2c3e",
    bubble_recv_text="#cdd6f4",
    bubble_sent_meta="#8899bb",
    bubble_recv_meta="#6c7086",

    success="#a6e3a1",
    warning="#f9e2af",
    error="#f38ba8",
    info="#74c7ec",

    border="#45475a",
    border_focus="#89b4fa",
    scrollbar="#45475a",
    separator="#45475a",
    overlay="rgba(30, 30, 46, 245)",

    link_https="#89b4fa",
    link_http="#fab387",

    mention="#89b4fa",
    search_highlight="#f9e2af",
    search_current="#fab387",

    reaction_bg="#313244",
    reaction_bg_own="#45475a",
    reaction_border="#45475a",
    reaction_border_own="#585b70",

    online_dot="#a6e3a1",
    online_dot_border="#181825",
    pin_color="#f9e2af",
    sender_name_other="#f9e2af",
    receipt_read="#74c7ec",
)

# ---------------------------------------------------------------------------
# Light theme — Signal-inspired palette
# ---------------------------------------------------------------------------

LIGHT_THEME = ThemeColors(
    bg_primary="#ffffff",
    bg_secondary="#f2f2f7",
    bg_tertiary="#e5e5ea",
    bg_hover="#dcdce4",
    bg_selected="#c7c7d1",

    text_primary="#1c1c1e",
    text_secondary="#3a3a3c",
    text_muted="#8a8a8e",

    accent="#3478f6",
    accent_hover="#2563eb",
    accent_text="#ffffff",

    bubble_sent_bg="#3478f6",
    bubble_sent_text="#ffffff",
    bubble_recv_bg="#e5e5ea",
    bubble_recv_text="#1c1c1e",
    bubble_sent_meta="#a3c4ff",
    bubble_recv_meta="#8a8a8e",

    success="#34c759",
    warning="#ff9500",
    error="#ff3b30",
    info="#5ac8fa",

    border="#c6c6c8",
    border_focus="#3478f6",
    scrollbar="#aeaeb2",
    separator="#c6c6c8",
    overlay="rgba(0, 0, 0, 200)",

    link_https="#2563eb",
    link_http="#ea580c",

    mention="#2563eb",
    search_highlight="#fde68a",
    search_current="#fb923c",

    reaction_bg="#e5e5ea",
    reaction_bg_own="#c7c7d1",
    reaction_border="#c6c6c8",
    reaction_border_own="#a0a0a8",

    online_dot="#34c759",
    online_dot_border="#e5e5ea",
    pin_color="#ff9500",
    sender_name_other="#7c3aed",
    receipt_read="#d0e8ff",
)


# ---------------------------------------------------------------------------
# ThemeManager singleton
# ---------------------------------------------------------------------------

class ThemeManager:
    """Manages the active theme, persistence and change notification."""

    _instance: ThemeManager | None = None

    @classmethod
    def instance(cls) -> ThemeManager:
        if cls._instance is None:
            cls._instance = cls()
        return cls._instance

    def __init__(self):
        self._is_dark: bool = True
        self._listeners: list[Callable[[], None]] = []
        self._email: str | None = None
        self._load_global()

    # -- Public API --

    @property
    def is_dark(self) -> bool:
        return self._is_dark

    @property
    def colors(self) -> ThemeColors:
        return DARK_THEME if self._is_dark else LIGHT_THEME

    def toggle(self):
        self._is_dark = not self._is_dark
        self._save()
        self._notify()

    def set_dark(self, dark: bool):
        if dark == self._is_dark:
            return
        self._is_dark = dark
        self._save()
        self._notify()

    def set_email(self, email: str):
        """After login, bind to user-specific preference file."""
        self._email = email
        self._load_user()

    def on_change(self, callback: Callable[[], None]):
        self._listeners.append(callback)

    def remove_listener(self, callback: Callable[[], None]):
        try:
            self._listeners.remove(callback)
        except ValueError:
            pass

    def generate_qss(self) -> str:
        return _build_qss(self.colors)

    # -- Persistence --

    def _global_path(self) -> Path:
        p = Path.home() / ".encrypted_chat"
        p.mkdir(parents=True, exist_ok=True)
        return p / "global_settings.json"

    def _user_path(self) -> Path | None:
        if not self._email:
            return None
        p = Path.home() / ".encrypted_chat" / self._email
        if not p.exists():
            return None
        return p / "theme.json"

    def _load_global(self):
        try:
            p = self._global_path()
            if p.exists():
                data = json.loads(p.read_text())
                self._is_dark = data.get("dark", True)
        except Exception:
            pass

    def _load_user(self):
        try:
            p = self._user_path()
            if p and p.exists():
                data = json.loads(p.read_text())
                self._is_dark = data.get("dark", self._is_dark)
        except Exception:
            pass

    def _save(self):
        data = {"dark": self._is_dark}
        try:
            self._global_path().write_text(json.dumps(data))
        except Exception:
            pass
        try:
            p = self._user_path()
            if p:
                p.write_text(json.dumps(data))
        except Exception:
            pass

    def _notify(self):
        for cb in list(self._listeners):
            try:
                cb()
            except Exception:
                logger.debug("Theme listener error", exc_info=True)


# ---------------------------------------------------------------------------
# Convenience accessors
# ---------------------------------------------------------------------------

def c() -> ThemeColors:
    """Shorthand for ThemeManager.instance().colors."""
    return ThemeManager.instance().colors


def qss() -> str:
    """Shorthand for ThemeManager.instance().generate_qss()."""
    return ThemeManager.instance().generate_qss()


def tm() -> ThemeManager:
    """Shorthand for ThemeManager.instance()."""
    return ThemeManager.instance()


# ---------------------------------------------------------------------------
# QSS generator
# ---------------------------------------------------------------------------

_FONT_STACK = (
    '"Segoe UI Variable", "Segoe UI", "Helvetica Neue", '
    '"SF Pro Text", "Calibri", sans-serif'
)


def _build_qss(t: ThemeColors) -> str:
    return f"""
/* ── Global ──────────────────────────────────────────────── */
QWidget {{
    background-color: {t.bg_primary};
    color: {t.text_primary};
    font-family: {_FONT_STACK};
    font-size: 11pt;
}}

/* ── Input fields ────────────────────────────────────────── */
QLineEdit {{
    background-color: {t.bg_secondary};
    border: 1px solid {t.border};
    border-radius: 6px;
    padding: 8px;
    color: {t.text_primary};
}}
QLineEdit:focus {{
    border: 1px solid {t.border_focus};
}}

/* ── Buttons ─────────────────────────────────────────────── */
QPushButton {{
    background-color: {t.accent};
    color: {t.accent_text};
    border: none;
    border-radius: 6px;
    padding: 8px 16px;
    font-weight: bold;
}}
QPushButton:hover {{
    background-color: {t.accent_hover};
}}
QPushButton:pressed {{
    background-color: {t.accent_hover};
}}
QPushButton#secondaryBtn {{
    background-color: {t.bg_secondary};
    color: {t.text_primary};
    font-weight: normal;
}}
QPushButton#secondaryBtn:hover {{
    background-color: {t.bg_hover};
}}
QPushButton#toolBtn {{
    background-color: transparent;
    border: none;
    border-radius: 4px;
    padding: 4px;
}}
QPushButton#toolBtn:hover {{
    background-color: {t.bg_hover};
}}

/* ── Lists ───────────────────────────────────────────────── */
QListWidget {{
    background-color: {t.bg_tertiary};
    border: none;
    border-radius: 6px;
    padding: 4px;
}}
QListWidget::item {{
    padding: 10px;
    border-radius: 4px;
}}
QListWidget::item:selected {{
    background-color: {t.bg_selected};
    border-left: 3px solid {t.accent};
}}
QListWidget::item:hover {{
    background-color: {t.bg_hover};
    color: {t.text_primary};
}}

/* ── Text areas ──────────────────────────────────────────── */
QTextEdit, QTextBrowser {{
    background-color: {t.bg_primary};
    border: none;
    border-radius: 6px;
    padding: 8px;
    color: {t.text_primary};
}}

/* ── Scrollbar ───────────────────────────────────────────── */
QScrollBar:vertical {{
    background: transparent;
    width: 8px;
    margin: 0;
}}
QScrollBar::handle:vertical {{
    background: {t.scrollbar};
    border-radius: 4px;
    min-height: 30px;
}}
QScrollBar::handle:vertical:hover {{
    background: {t.text_muted};
}}
QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {{
    height: 0;
}}
QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {{
    background: transparent;
}}
QScrollBar:horizontal {{
    background: transparent;
    height: 8px;
    margin: 0;
}}
QScrollBar::handle:horizontal {{
    background: {t.scrollbar};
    border-radius: 4px;
    min-width: 30px;
}}
QScrollBar::handle:horizontal:hover {{
    background: {t.text_muted};
}}
QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal {{
    width: 0;
}}
QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {{
    background: transparent;
}}

/* ── Title label ─────────────────────────────────────────── */
QLabel#title {{
    font-size: 15pt;
    font-weight: bold;
    color: {t.accent};
}}

/* ── Sidebar panel ───────────────────────────────────────── */
#sidebarPanel {{
    background-color: {t.bg_tertiary};
}}

/* ── Splitter ────────────────────────────────────────────── */
QSplitter::handle {{
    background-color: {t.separator};
    width: 1px;
}}

/* ── Checkbox ────────────────────────────────────────────── */
QCheckBox {{
    color: {t.text_primary};
}}

/* ── Menus ───────────────────────────────────────────────── */
QMenu {{
    background-color: {t.bg_secondary};
    border: 1px solid {t.border};
    border-radius: 6px;
    padding: 4px;
}}
QMenu::item {{
    padding: 6px 20px;
    color: {t.text_primary};
    border-radius: 4px;
}}
QMenu::item:selected {{
    background-color: {t.bg_hover};
}}
QMenu::separator {{
    height: 1px;
    background: {t.separator};
    margin: 4px 8px;
}}

/* ── Dialogs ─────────────────────────────────────────────── */
QDialog {{
    background-color: {t.bg_primary};
    color: {t.text_primary};
}}

/* ── MessageBox ──────────────────────────────────────────── */
QMessageBox {{
    background-color: {t.bg_primary};
    color: {t.text_primary};
}}
QMessageBox QLabel {{
    color: {t.text_primary};
}}

/* ── InputDialog ─────────────────────────────────────────── */
QInputDialog {{
    background-color: {t.bg_primary};
    color: {t.text_primary};
}}

/* ── ScrollArea ──────────────────────────────────────────── */
QScrollArea {{
    background-color: {t.bg_primary};
    border: none;
}}

/* ── ToolTip ─────────────────────────────────────────────── */
QToolTip {{
    background-color: {t.bg_secondary};
    color: {t.text_primary};
    border: 1px solid {t.border};
    padding: 4px 8px;
    font-size: 9pt;
}}
"""
