"""PipelineTask -- rich view over a WorkItem's metadata dict.

All pipeline-specific fields are stored in ``WorkItem.metadata`` so the
base WorkQueue remains unchanged.  PipelineTask is a read/write lens:

    item  = queue.enqueue(...)
    task  = PipelineTask(item)
    task.file_manifest = ["src/foo.py"]
    task.flush()   # writes back to item.metadata

Intermediate review states are tracked via ``review_status`` inside
metadata rather than by adding new top-level statuses to WorkQueue.
"""

from __future__ import annotations

from dataclasses import dataclass
from enum import Enum
from typing import Any, Dict, List, Optional

from cohort.work_queue import WorkItem


class StalenessLevel(str, Enum):
    CLEAN = "clean"           # No changes since queue time
    TRIVIAL = "trivial"       # Changes exist, no file overlap
    UNCERTAIN = "uncertain"   # Code file overlap -- needs review
    CONFLICTED = "conflicted" # Heavy overlap (>50% or >=3 files) -- needs human


class ReviewStatus(str, Enum):
    PENDING = "pending"       # Awaiting review
    APPROVED = "approved"     # Approved, ready to apply
    REJECTED = "rejected"     # Rejected, may requeue
    APPLIED = "applied"       # Changes applied, awaiting completion


@dataclass
class PipelineTask:
    """Rich view over a WorkItem with pipeline-specific fields.

    Parameters
    ----------
    item:
        The underlying WorkItem from WorkQueue.
    """

    item: WorkItem

    # -- git context -------------------------------------------------------
    @property
    def git_sha_at_queue(self) -> Optional[str]:
        return self.item.metadata.get("git_sha_at_queue")

    @git_sha_at_queue.setter
    def git_sha_at_queue(self, value: str) -> None:
        self.item.metadata["git_sha_at_queue"] = value

    @property
    def git_branch(self) -> Optional[str]:
        return self.item.metadata.get("git_branch")

    @git_branch.setter
    def git_branch(self, value: str) -> None:
        self.item.metadata["git_branch"] = value

    # -- file tracking -----------------------------------------------------
    @property
    def file_manifest(self) -> List[str]:
        return self.item.metadata.get("file_manifest", [])

    @file_manifest.setter
    def file_manifest(self, value: List[str]) -> None:
        self.item.metadata["file_manifest"] = value

    @property
    def files_modified(self) -> List[str]:
        return self.item.metadata.get("files_modified", [])

    @files_modified.setter
    def files_modified(self, value: List[str]) -> None:
        self.item.metadata["files_modified"] = value

    # -- staleness ---------------------------------------------------------
    @property
    def staleness_level(self) -> Optional[str]:
        return self.item.metadata.get("staleness_level")

    @staleness_level.setter
    def staleness_level(self, value: str) -> None:
        self.item.metadata["staleness_level"] = value

    @property
    def staleness_report(self) -> Optional[str]:
        return self.item.metadata.get("staleness_report")

    @staleness_report.setter
    def staleness_report(self, value: str) -> None:
        self.item.metadata["staleness_report"] = value

    # -- deliverables ------------------------------------------------------
    @property
    def deliverables(self) -> List[Dict[str, Any]]:
        return self.item.metadata.get("deliverables", [])

    @deliverables.setter
    def deliverables(self, value: List[Dict[str, Any]]) -> None:
        self.item.metadata["deliverables"] = value

    @property
    def deliverables_set_at(self) -> Optional[str]:
        return self.item.metadata.get("deliverables_set_at")

    @deliverables_set_at.setter
    def deliverables_set_at(self, value: str) -> None:
        self.item.metadata["deliverables_set_at"] = value

    # -- review ------------------------------------------------------------
    @property
    def review_status(self) -> Optional[str]:
        return self.item.metadata.get("review_status")

    @review_status.setter
    def review_status(self, value: str) -> None:
        self.item.metadata["review_status"] = value

    @property
    def self_review_report(self) -> Optional[Dict[str, Any]]:
        return self.item.metadata.get("self_review_report")

    @self_review_report.setter
    def self_review_report(self, value: Dict[str, Any]) -> None:
        self.item.metadata["self_review_report"] = value

    @property
    def changes_summary(self) -> Optional[str]:
        return self.item.metadata.get("changes_summary")

    @changes_summary.setter
    def changes_summary(self, value: str) -> None:
        self.item.metadata["changes_summary"] = value

    # -- requeue tracking --------------------------------------------------
    @property
    def requeue_count(self) -> int:
        return self.item.metadata.get("requeue_count", 0)

    @requeue_count.setter
    def requeue_count(self, value: int) -> None:
        self.item.metadata["requeue_count"] = value

    @property
    def requeued_from(self) -> Optional[str]:
        return self.item.metadata.get("requeued_from")

    @requeued_from.setter
    def requeued_from(self, value: str) -> None:
        self.item.metadata["requeued_from"] = value

    # -- escalation --------------------------------------------------------
    @property
    def escalated_to(self) -> Optional[str]:
        return self.item.metadata.get("escalated_to")

    @escalated_to.setter
    def escalated_to(self, value: str) -> None:
        self.item.metadata["escalated_to"] = value

    @property
    def escalation_reason(self) -> Optional[str]:
        return self.item.metadata.get("escalation_reason")

    @escalation_reason.setter
    def escalation_reason(self, value: str) -> None:
        self.item.metadata["escalation_reason"] = value

    # -- services ----------------------------------------------------------
    @property
    def services_to_restart(self) -> List[str]:
        return self.item.metadata.get("services_to_restart", [])

    @services_to_restart.setter
    def services_to_restart(self, value: List[str]) -> None:
        self.item.metadata["services_to_restart"] = value

    # -- helpers -----------------------------------------------------------
    def to_dict(self) -> Dict[str, Any]:
        return self.item.to_dict()

    def __repr__(self) -> str:
        return (
            f"PipelineTask(id={self.item.id!r}, status={self.item.status!r}, "
            f"review={self.review_status!r}, staleness={self.staleness_level!r})"
        )
