# -*- coding: utf-8 -*-
# hub/ticket/ui/cards/task_card_view.py

"""Ticket task card view."""

from __future__ import annotations

from PySide6.QtCore import Qt, QTimer, Signal
from PySide6.QtWidgets import QSizePolicy

from gui.components import Label
from gui.containers import SContainer, VContainer

from domain import TicketTaskSnapshot
from domain.ticket_constants import (
    STATE_COMPLETED,
    STATE_CONFIRMATION,
    STATE_IN_PROGRESS,
    STATE_REFUSED,
    STATE_TODO,
)
from ui.task_view_formatters import (
    build_specialist_card_text,
    build_specialist_photo_path,
    build_task_fault_title,
)
from .task_card_pixmap_factory import (
    build_placeholder_avatar_pixmap,
    compute_square_size,
    load_avatar_pixmap,
)


class TaskCardView(SContainer):
    """Compact Ticket card without action logic."""

    card_clicked = Signal(object)
    card_height_changed = Signal()

    _ROOT_STYLE_BY_STATE = {
        STATE_TODO: "TICKET_TASK_CARD_ROOT_TODO",
        STATE_IN_PROGRESS: "TICKET_TASK_CARD_ROOT_IN_PROGRESS",
        STATE_CONFIRMATION: "TICKET_TASK_CARD_ROOT_CONFIRMATION",
        STATE_COMPLETED: "TICKET_TASK_CARD_ROOT_COMPLETED",
        STATE_REFUSED: "TICKET_TASK_CARD_ROOT_REFUSED",
    }
    _DARK_TEXT_STATES = {STATE_TODO, STATE_CONFIRMATION, STATE_REFUSED}

    def __init__(
        self,
        task: TicketTaskSnapshot,
        parent=None,
    ):
        super().__init__(
            width_percent=100,
            margin=0,
            content_fit=True,
            parent=parent,
        )
        self._card_id = task.task_id
        self._fault_title_label: Label | None = None
        self._avatar_label: Label | None = None
        self._current_task: TicketTaskSnapshot | None = None
        self._height_sync_in_progress = False
        self._pixmap_refresh_pending = False
        self._setup_ui()
        self.update_task(task)

    @property
    def card_id(self) -> object:
        return self._card_id

    def _setup_ui(self) -> None:
        self.setObjectName("ticket_task_card")
        self.setAttribute(Qt.WidgetAttribute.WA_StyledBackground, True)
        self.setCursor(Qt.CursorShape.PointingHandCursor)
        self.set_size_policy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)

        # Content-shell: горизонтальное разделение текстовой зоны и аватара.
        content = SContainer(
            width_percent=100,
            height_percent=100,
            orientation="h",
            margin=8,
            spacing=0,
            style="TICKET_TASK_CARD_CONTENT",
            parent=self,
        )

        # Text-column: левая вертикальная зона с единственным текстовым полем заголовка.
        text_column = VContainer(
            width_percent=70,
            spacing=0,
            parent=content,
        )

        # Единственное текстовое поле карточки: краткий заголовок неисправности.
        self._fault_title_label = Label(
            "",
            alignment="left",
            height_percent=100,
            parent=text_column,
        )

        # Avatar-column: правая зона для фото или плейсхолдера специалиста.
        avatar_column = VContainer(
            width_percent=26,
            spacing=0,
            parent=content,
        )
        self._avatar_label = Label(
            "",
            alignment="center",
            width_percent=100,
            height_percent=100,
            style="TICKET_TASK_CARD_AVATAR_IMAGE",
            parent=avatar_column,
        )

    def update_task(self, task: TicketTaskSnapshot) -> None:
        self._card_id = task.task_id
        self._current_task = task

        if self._fault_title_label is not None:
            self._fault_title_label.set_text(build_task_fault_title(task))
            self._fault_title_label.set_tooltip(task.location or "")

        self._apply_state_styles(task)
        self._update_avatar(task)
        self._sync_card_height()
        self._schedule_pixmap_refresh()

    def _apply_state_styles(self, task: TicketTaskSnapshot) -> None:
        style_suffix = "DARK" if task.state_code in self._DARK_TEXT_STATES else "LIGHT"
        self.style(self._ROOT_STYLE_BY_STATE.get(task.state_code, "TICKET_TASK_CARD_ROOT_TODO"))
        if self._fault_title_label is not None:
            self._fault_title_label.style(f"TICKET_TASK_CARD_TITLE_{style_suffix}")

    def _update_avatar(self, task: TicketTaskSnapshot) -> None:
        if self._avatar_label is None:
            return
        avatar_path = build_specialist_photo_path(task.assigned_specialist, task.specialist_photo)
        self._avatar_label.set_tooltip(task.assigned_specialist or "Специалист не назначен")
        pixmap = load_avatar_pixmap(avatar_path, self._avatar_label.width(), self._avatar_label.height(), padding=4)
        if pixmap is not None:
            self._avatar_label.set_text("")
            self._avatar_label.set_pixmap(pixmap)
            return
        self._avatar_label.set_text("")
        placeholder_size = self._label_square_size(self._avatar_label)
        if placeholder_size > 0:
            self._avatar_label.set_pixmap(build_placeholder_avatar_pixmap(placeholder_size))

    @staticmethod
    def _label_square_size(label: Label, padding: int = 0) -> int:
        return compute_square_size(label.width(), label.height(), padding)

    def resizeEvent(self, event) -> None:
        super().resizeEvent(event)
        self._sync_card_height()
        if self._current_task is not None:
            self._update_avatar(self._current_task)
        self._schedule_pixmap_refresh()

    def _schedule_pixmap_refresh(self) -> None:
        """Запланировать отложенный рендер pixmap-контента.

        Процентные размеры дочерних Label вычисляются через
        QTimer.singleShot(0) в PercentSizedWidget, поэтому при первом
        показе карточки (или при динамической вставке из COM-сигнала)
        label.width()/height() ещё равны 0 в момент resizeEvent.
        Отложенный вызов гарантирует, что к моменту рендера layout
        дочерних виджетов уже завершён.
        """
        if self._pixmap_refresh_pending:
            return
        self._pixmap_refresh_pending = True
        QTimer.singleShot(0, self._deferred_pixmap_refresh)

    def _deferred_pixmap_refresh(self) -> None:
        self._pixmap_refresh_pending = False
        if self._current_task is not None:
            self._update_avatar(self._current_task)

    def _sync_card_height(self) -> None:
        if self._height_sync_in_progress or self.width() <= 0:
            return
        target_height = max(1, round(self.width() / 2.745))
        if self.height() == target_height:
            return
        self._height_sync_in_progress = True
        self.setFixedHeight(target_height)
        self._height_sync_in_progress = False
        self.card_height_changed.emit()

    def _on_parent_rebuild_finished(self) -> None:
        # Фаза 2 каскада percent-sized: родительская колонка завершила
        # перестроение, ширина карточки уже стабильная. Только теперь
        # пересчитываем собственную высоту по соотношению width/2.745
        # и обновляем pixmap-контент.
        super()._on_parent_rebuild_finished()
        self._sync_card_height()
        if self._current_task is not None:
            self._schedule_pixmap_refresh()

    def mousePressEvent(self, event) -> None:
        if event.button() == Qt.MouseButton.LeftButton:
            self.card_clicked.emit(self._card_id)
        super().mousePressEvent(event)
