from __future__ import annotations
from pathlib import Path
from PyQt6.QtWidgets import (
    QWidget, QVBoxLayout, QHBoxLayout, QTabWidget,
    QTableWidget, QTableWidgetItem, QPushButton,
    QLabel, QDialog, QFormLayout, QLineEdit, QMessageBox, QHeaderView,
)
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QColor
from core.taxonomy import TaxonomyModel, load_taxonomy, save_taxonomy, load_categories, save_categories
from core.article_scanner import scan_articles
from core.frontmatter import parse_frontmatter, write_frontmatter

class AddTermDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("Aggiungi termine")
        layout = QVBoxLayout(self)
        form = QFormLayout()
        self._it = QLineEdit()
        self._en = QLineEdit()
        form.addRow("IT:", self._it)
        form.addRow("EN:", self._en)
        layout.addLayout(form)
        btns = QHBoxLayout()
        ok = QPushButton("Aggiungi")
        ok.clicked.connect(self.accept)
        cancel = QPushButton("Annulla")
        cancel.clicked.connect(self.reject)
        btns.addStretch()
        btns.addWidget(cancel)
        btns.addWidget(ok)
        layout.addLayout(btns)

    @property
    def it_term(self) -> str:
        return self._it.text().strip()

    @property
    def en_term(self) -> str:
        return self._en.text().strip()

class TaxonomyView(QWidget):
    def __init__(self, blog_root: Path, parent=None):
        super().__init__(parent)
        self._blog_root = blog_root
        self._tags_it = blog_root / "docs" / "tags-it.txt"
        self._tags_en = blog_root / "docs" / "tags-en.txt"
        self._categories_path = blog_root / "docs" / "categories.txt"
        self._model: TaxonomyModel | None = None
        self._categories: list[str] = []
        self._build_ui()
        self.load()

    def _build_ui(self):
        layout = QVBoxLayout(self)

        tabs = QTabWidget()

        tags_tab = QWidget()
        tl = QVBoxLayout(tags_tab)
        self._tags_table = QTableWidget(0, 2)
        self._tags_table.setHorizontalHeaderLabels(["🇮🇹 Italiano", "🇬🇧 English"])
        self._tags_table.horizontalHeader().setStretchLastSection(True)
        tl.addWidget(self._tags_table)
        tag_btns = QHBoxLayout()
        add_tag_btn = QPushButton("➕ Aggiungi termine")
        add_tag_btn.clicked.connect(self._add_term)
        save_tags_btn = QPushButton("💾 Salva")
        save_tags_btn.clicked.connect(self._save)
        tag_btns.addWidget(add_tag_btn)
        tag_btns.addStretch()
        tag_btns.addWidget(save_tags_btn)
        tl.addLayout(tag_btns)
        tabs.addTab(tags_tab, "🏷 Tags")

        cats_tab = QWidget()
        cl = QVBoxLayout(cats_tab)
        self._cats_table = QTableWidget(0, 2)
        self._cats_table.setHorizontalHeaderLabels(["Categoria", "Articoli"])
        self._cats_table.setSelectionMode(QTableWidget.SelectionMode.ExtendedSelection)
        self._cats_table.horizontalHeader().setStretchLastSection(False)
        self._cats_table.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeMode.Stretch)
        self._cats_table.horizontalHeader().setSectionResizeMode(1, QHeaderView.ResizeMode.ResizeToContents)
        cl.addWidget(self._cats_table)
        cat_btns = QHBoxLayout()
        add_cat_btn = QPushButton("➕ Aggiungi")
        add_cat_btn.clicked.connect(self._add_category)
        remove_cat_btn = QPushButton("🗑 Rimuovi")
        remove_cat_btn.clicked.connect(self._remove_category)
        save_cats_btn = QPushButton("💾 Salva")
        save_cats_btn.clicked.connect(self._save_categories)
        cat_btns.addWidget(add_cat_btn)
        cat_btns.addWidget(remove_cat_btn)
        cat_btns.addStretch()
        cat_btns.addWidget(save_cats_btn)
        cl.addLayout(cat_btns)
        tabs.addTab(cats_tab, "📂 Categorie")

        layout.addWidget(tabs)

        self._status = QLabel("")
        self._status.setStyleSheet("color:#888;font-size:10px;padding:4px;")
        layout.addWidget(self._status)

    def load(self):
        if not self._tags_it.exists():
            self._status.setText("tags-it.txt non trovato.")
        else:
            self._model = load_taxonomy(self._tags_it, self._tags_en)
            self._populate_table()
        self._categories = load_categories(self._categories_path)
        self._populate_cats_table()

    def _populate_table(self):
        if not self._model:
            return
        self._tags_table.setRowCount(0)
        for it_term, en_term in sorted(self._model.it_to_en.items()):
            row = self._tags_table.rowCount()
            self._tags_table.insertRow(row)
            self._tags_table.setItem(row, 0, QTableWidgetItem(it_term))
            self._tags_table.setItem(row, 1, QTableWidgetItem(en_term))

        for orphan in self._model.orphans_it:
            row = self._tags_table.rowCount()
            self._tags_table.insertRow(row)
            it_item = QTableWidgetItem(orphan)
            it_item.setForeground(QColor("#ff6b6b"))
            en_item = QTableWidgetItem("⚠ mancante")
            en_item.setForeground(QColor("#ff6b6b"))
            self._tags_table.setItem(row, 0, it_item)
            self._tags_table.setItem(row, 1, en_item)

        self._status.setText(
            f"{len(self._model.it_to_en)} coppie · {len(self._model.orphans_it)} IT orfani · {len(self._model.orphans_en)} EN orfani"
        )

    def _add_term(self):
        dlg = AddTermDialog(self)
        if dlg.exec() and dlg.it_term and dlg.en_term:
            if self._model:
                self._model.it_to_en[dlg.it_term] = dlg.en_term
                self._populate_table()

    def _populate_cats_table(self):
        articles = scan_articles(self._blog_root)
        counts: dict[str, int] = {}
        for a in articles:
            for c in a.frontmatter.get("categories", []):
                key = str(c).strip()
                counts[key] = counts.get(key, 0) + 1

        self._cats_table.setRowCount(0)
        for cat in sorted(self._categories):
            row = self._cats_table.rowCount()
            self._cats_table.insertRow(row)
            self._cats_table.setItem(row, 0, QTableWidgetItem(cat))
            count_item = QTableWidgetItem(str(counts.get(cat, 0)))
            count_item.setFlags(count_item.flags() & ~Qt.ItemFlag.ItemIsEditable)
            count_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
            self._cats_table.setItem(row, 1, count_item)

    def _add_category(self):
        dlg = QDialog(self)
        dlg.setWindowTitle("Aggiungi categoria")
        layout = QVBoxLayout(dlg)
        form = QFormLayout()
        name_edit = QLineEdit()
        form.addRow("Nome:", name_edit)
        layout.addLayout(form)
        btns = QHBoxLayout()
        ok = QPushButton("Aggiungi")
        ok.clicked.connect(dlg.accept)
        cancel = QPushButton("Annulla")
        cancel.clicked.connect(dlg.reject)
        btns.addStretch()
        btns.addWidget(cancel)
        btns.addWidget(ok)
        layout.addLayout(btns)
        if dlg.exec() and name_edit.text().strip():
            name = name_edit.text().strip()
            if name not in self._categories:
                self._categories.append(name)
                self._populate_cats_table()

    def _remove_category(self):
        rows = {idx.row() for idx in self._cats_table.selectedIndexes()}
        if not rows:
            return
        names = [self._cats_table.item(r, 0).text() for r in rows if self._cats_table.item(r, 0)]
        if not names:
            return
        reply = QMessageBox.question(
            self, "Rimuovi categorie",
            f"Rimuovere {len(names)} categorie?",
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
        )
        if reply == QMessageBox.StandardButton.Yes:
            to_remove = set(names)
            self._categories = [c for c in self._categories if c not in to_remove]
            self._populate_cats_table()

    def _save_categories(self):
        cats: list[str] = []
        for row in range(self._cats_table.rowCount()):
            item = self._cats_table.item(row, 0)
            if item and item.text().strip():
                cats.append(item.text().strip())
        self._categories = sorted(set(cats))
        save_categories(self._categories_path, self._categories)
        self._status.setText("Categorie salvate.")

    @staticmethod
    def _detect_renames(
        old: dict[str, str], new: dict[str, str]
    ) -> tuple[dict[str, str], dict[str, str]]:
        it_renames: dict[str, str] = {}
        en_renames: dict[str, str] = {}
        old_en_to_it = {v: k for k, v in old.items()}
        for new_it, new_en in new.items():
            if new_it not in old:
                if new_en in old_en_to_it:
                    it_renames[old_en_to_it[new_en]] = new_it
            else:
                if old[new_it] != new_en:
                    en_renames[old[new_it]] = new_en
        return it_renames, en_renames

    def _propagate_renames(self, it_renames: dict[str, str], en_renames: dict[str, str]) -> int:
        if not it_renames and not en_renames:
            return 0
        articles = scan_articles(self._blog_root)
        count = 0
        for article in articles:
            renames = it_renames if article.lang == "it" else en_renames
            if not renames:
                continue
            current_tags = article.frontmatter.get("tags", [])
            if not isinstance(current_tags, list):
                continue
            new_tags = [renames.get(str(t), str(t)) for t in current_tags]
            if new_tags == [str(t) for t in current_tags]:
                continue
            try:
                fm, body = parse_frontmatter(article.path)
                fm["tags"] = new_tags
                write_frontmatter(article.path, fm, body)
                count += 1
            except Exception:
                pass
        return count

    def _save(self):
        if not self._model:
            return
        old_it_to_en = dict(self._model.it_to_en)
        updated: dict[str, str] = {}
        for row in range(self._tags_table.rowCount()):
            it_item = self._tags_table.item(row, 0)
            en_item = self._tags_table.item(row, 1)
            if it_item and en_item:
                it_val = it_item.text().strip()
                en_val = en_item.text().strip()
                if it_val and en_val and en_val != "⚠ mancante":
                    updated[it_val] = en_val
        self._model.it_to_en = updated
        try:
            save_taxonomy(self._model, self._tags_it, self._tags_en)
        except OSError as e:
            QMessageBox.critical(self, "Errore", f"Impossibile salvare: {e}")
            return
        it_renames, en_renames = self._detect_renames(old_it_to_en, updated)
        count = self._propagate_renames(it_renames, en_renames)
        if count:
            self._status.setText(f"Salvato · {count} articol{'o' if count == 1 else 'i'} aggiornati.")
        else:
            self._status.setText("Salvato.")
