from __future__ import annotations

from pathlib import Path
import shutil

from PySide6.QtCore import Qt, QUrl, QEvent
from PySide6.QtGui import QDesktopServices
from PySide6.QtWidgets import (
    QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QTableWidget,
    QTableWidgetItem, QAbstractItemView, QHeaderView, QMessageBox, QFileDialog
)

from mi100.repository import Repo
from mi100.ui.delegates import RowTintDelegate
from mi100.ui.email_send_dialog import EmailSendDialog
from mi100.ui.studio_settings_dialog import StudioSettingsDialog

BTN_GREEN = (
    "QPushButton{background:#4FAF7A;color:#FFFFFF;border:1px solid #459E6E;"
    "border-radius:4px;padding:4px 10px;font-weight:600;}"
    "QPushButton:hover{background:#459E6E;}"
)
BTN_RED = (
    "QPushButton{background:#FFA8A8;color:#7C2D12;border:1px solid #E59494;"
    "border-radius:4px;padding:4px 10px;font-weight:600;}"
    "QPushButton:hover{background:#E59494;}"
)
BTN_GRAY=("QPushButton{background:#EBEBEB;color:#374151;border:1px solid #D7D7D7;"
"border-radius:4px;padding:4px 10px;font-weight:600;}"
"QPushButton:hover{background:#D7D7D7;}")

BTN_ORANGE = (
    "QPushButton{background:#FFD8A8;color:#8E6129;border:1px solid #E5BF90;"
    "border-radius:4px;padding:4px 10px;font-weight:600;}"
    "QPushButton:hover{background:#E5BF90;}"
)

BTN_EMAIL = (
    "QPushButton{background:#A0CFFF;color:#1C4064;border:1px solid #8CB7E6;"
    "border-radius:4px;padding:4px 10px;font-weight:600;}"
    "QPushButton:hover{background:#8CB7E6;}"
)


class ReportHistoryTab(QWidget):
    def __init__(self, repo: Repo, owner_type: str, id_provider, parent=None, generate_callback=None, settings_callback=None, show_templates_button: bool=False):
        super().__init__(parent)
        self.repo = repo
        self.owner_type = owner_type  # client / actor
        self.id_provider = id_provider
        self._action_holders: dict[int, QWidget] = {}
        self.generate_callback = generate_callback
        self.settings_callback = settings_callback
        self.show_templates_button = show_templates_button

        layout = QVBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(8)

        top = QHBoxLayout()
        self.btn_generate = QPushButton("Згенерувати звіт")
        self.btn_generate.setStyleSheet(BTN_GREEN)
        self.btn_generate.setMinimumHeight(24)
        self.btn_generate.clicked.connect(self._generate_report)
        top.addWidget(self.btn_generate, 0, Qt.AlignLeft)
        if self.show_templates_button:
            self.btn_templates = QPushButton("Шаблони звітів")
            self.btn_templates.setStyleSheet(BTN_GRAY)
            self.btn_templates.setMinimumHeight(24)
            self.btn_templates.clicked.connect(self._open_templates)
            top.addWidget(self.btn_templates, 0, Qt.AlignLeft)
        top.addStretch(1)
        layout.addLayout(top)

        self.table = QTableWidget(0, 3)
        self._row_delegate = RowTintDelegate(self.table)
        self.table.setHorizontalHeaderLabels(["Дата створення", "Період звітності", "Дії"])
        self.table.verticalHeader().setVisible(False)
        self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table.setSelectionMode(QAbstractItemView.SingleSelection)
        self.table.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents)
        self.table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(2, QHeaderView.ResizeToContents)
        self.table.setColumnWidth(1, 170)
        self.table.horizontalHeader().setMinimumSectionSize(90)
        self.table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.table.setWordWrap(False)
        self.table.verticalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
        self.table.setItemDelegate(self._row_delegate)
        self.table.setMouseTracking(True)
        self.table.viewport().setMouseTracking(True)
        self.table.cellEntered.connect(self._on_hover_row)
        self.table.viewport().installEventFilter(self)
        layout.addWidget(self.table, 1)

    def refresh(self) -> None:
        owner_id = self.id_provider()
        self.table.setRowCount(0)
        self._action_holders.clear()
        if not owner_id:
            return
        if self.owner_type == 'client':
            rows = self.repo.list_client_reports(int(owner_id))
        else:
            rows = self.repo.list_actor_reports(int(owner_id))
        for row in rows:
            r = self.table.rowCount()
            self.table.insertRow(r)
            period_parts = []
            if row.get('period_start') or row.get('period_end'):
                period_parts.append(f"{row.get('period_start') or '—'} — {row.get('period_end') or '—'}")
            if row.get('unpaid_only'):
                period_parts.append('Усі неоплачені')
            if row.get('free_only'):
                period_parts.append('Усі безкоштовні')
            period = ' | '.join(period_parts) if period_parts else '—'
            for c, value in enumerate((str(row.get('created_date') or ''), period)):
                item = QTableWidgetItem(value)
                item.setData(RowTintDelegate.ROLE_BG_KEY, 'blue')
                self.table.setItem(r, c, item)

            actions = QWidget()
            actions.setAttribute(Qt.WA_StyledBackground, True)
            actions.setStyleSheet('background:transparent; border:none;')
            hlay = QHBoxLayout(actions)
            hlay.setContentsMargins(0, 0, 0, 0)
            hlay.setSpacing(6)
            btn_open = QPushButton("Відкрити")
            btn_open.setFixedSize(92, 30)
            btn_open.setStyleSheet(BTN_ORANGE)
            btn_open.clicked.connect(lambda _=False, p=str(row.get("file_path") or ""): self._open_file(p))
            hlay.addWidget(btn_open)
            btn_save = QPushButton("Зберегти")
            btn_save.setFixedSize(92, 30)
            btn_save.setStyleSheet(BTN_ORANGE)
            btn_save.clicked.connect(lambda _=False, p=str(row.get("file_path") or ""): self._save_file(p))
            hlay.addWidget(btn_save)
            btn_send = QPushButton("Email")
            btn_send.setFixedSize(62, 30)
            btn_send.setStyleSheet(BTN_EMAIL)
            btn_send.clicked.connect(lambda _=False, d=dict(row): self._send_email(d))
            hlay.addWidget(btn_send)
            btn_del = QPushButton("Видалити")
            btn_del.setFixedSize(98, 30)
            btn_del.setStyleSheet(BTN_RED)
            btn_del.clicked.connect(lambda _=False, d=dict(row): self._delete_report(d))
            hlay.addWidget(btn_del)
            self.table.setCellWidget(r, 2, actions)
            self._action_holders[r] = actions
            self._apply_row_widget_bg(r, hovered=False)
        self.table.resizeRowsToContents()
        self.table.resizeColumnsToContents()
        self.table.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents)
        self.table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(2, QHeaderView.ResizeToContents)
        self.table.setColumnWidth(2, max(318, min(360, self.table.columnWidth(2))))
        for row in range(self.table.rowCount()):
            self.table.setRowHeight(row, max(20, min(24, self.table.rowHeight(row))))


    def _generate_report(self) -> None:
        if self.generate_callback:
            self.generate_callback()

    def _open_file(self, file_path: str) -> None:
        path = Path(file_path)
        if not path.exists():
            QMessageBox.warning(self, "Файл не знайдено", "Файл звіту не знайдено на диску.")
            return
        QDesktopServices.openUrl(QUrl.fromLocalFile(str(path)))

    def _save_file(self, file_path: str) -> None:
        src = Path(file_path)
        if not src.exists():
            QMessageBox.warning(self, "Файл не знайдено", "Файл звіту не знайдено на диску.")
            return
        dest, _ = QFileDialog.getSaveFileName(self, "Зберегти файл", src.name, "PDF Files (*.pdf)")
        if not dest:
            return
        shutil.copy2(src, dest)

    def _send_email(self, row: dict) -> None:
        owner_id = self.id_provider()
        if not owner_id:
            return
        recipient = ''
        client_id = None
        if self.owner_type == 'client':
            client = self.repo.get_client(int(owner_id))
            recipient = str(client['email'] or '').strip() if client else ''
            client_id = int(owner_id)
        else:
            actor = self.repo.get_voice_actor(int(owner_id))
            recipient = str(actor['email'] or '').strip() if actor else ''
            client_id = 0
        subject = f"Звіт {row.get('doc_number') or ''}"
        recipient_name = ''
        if self.owner_type == 'client' and client:
            recipient_name = str(client['display_name'] or client['company_name'] or '')
        elif self.owner_type != 'client' and actor:
            recipient_name = str(actor['display_name'] or '')
        body = self.repo.build_email_body(
            template_key='client_report' if self.owner_type == 'client' else 'actor_report',
            doc_number=str(row.get('doc_number') or ''),
            recipient_name=recipient_name,
        )
        dlg = EmailSendDialog(
            self.repo,
            client_id=int(client_id or 0),
            document_id=int(row['id']),
            recipient_email=recipient,
            subject=subject,
            body=body,
            attachment_path=str(row.get('file_path') or ''),
            document_kind='CLIENT_REPORT' if self.owner_type == 'client' else 'ACTOR_REPORT',
            recipient_kind='client' if self.owner_type == 'client' else 'actor',
            recipient_name=recipient_name,
            document_number=str(row.get('doc_number') or ''),
            parent=self,
        )
        dlg.exec()

    def _delete_report(self, row: dict) -> None:
        if QMessageBox.question(self, 'Видалення', 'Видалити звіт?', QMessageBox.Yes | QMessageBox.No, QMessageBox.No) != QMessageBox.Yes:
            return
        path = Path(str(row.get('file_path') or ''))
        try:
            if path.exists():
                path.unlink()
        except Exception:
            pass
        self.repo.delete_document(int(row['id']))
        self.refresh()

    def eventFilter(self, obj, event):
        if obj is self.table.viewport() and event.type() == QEvent.Leave:
            self._row_delegate.set_hover_row(-1)
            for row in list(self._action_holders):
                self._apply_row_widget_bg(row, hovered=False)
            self.table.viewport().update()
        return super().eventFilter(obj, event)

    def _on_hover_row(self, row: int, _col: int) -> None:
        self._row_delegate.set_hover_row(row)
        for r in list(self._action_holders):
            self._apply_row_widget_bg(r, hovered=(r == row))
        self.table.viewport().update()

    def _apply_row_widget_bg(self, row: int, hovered: bool) -> None:
        holder = self._action_holders.get(row)
        if not holder:
            return
        bg = '#A0CFFF'
        if hovered:
            bg = '#8EBCEB'
        holder.setStyleSheet(f'background:{bg}; border:none;')

    def _open_templates(self) -> None:
        if self.settings_callback:
            self.settings_callback("email_templates")
