"""
Strategy Domain — Repository Interfaces.
"""

from abc import ABC, abstractmethod
from typing import List, Optional
from uuid import UUID

from ..entities.vision import Vision
from ..entities.strategic_theme import StrategicTheme
from ..entities.objective import Objective
from ..entities.key_result import KeyResult
from ..entities.key_result_checkin import KeyResultCheckIn
from ..entities.kpi_definition import KPIDefinition
from ..entities.kpi_target import KPITarget
from ..entities.kpi_actual import KPIActual
from ..entities.kpi_assignment import KPIAssignment
from ..entities.strategy_map import StrategyMap
from ..entities.strategy_map_perspective import StrategyMapPerspective
from ..entities.strategy_map_objective import StrategyMapObjective
from ..entities.causal_link import CausalLink
from ..entities.scorecard import Scorecard
from ..entities.scorecard_perspective import ScorecardPerspective
from ..entities.scorecard_measure import ScorecardMeasure


# ─── Vision Repository ───────────────────────────

class VisionRepository(ABC):
    """واسط ریپازیتوری چشم‌انداز."""

    @abstractmethod
    def find_by_id(self, vision_id: UUID) -> Optional[Vision]:
        ...

    @abstractmethod
    def find_by_tenant(self, tenant_id: UUID) -> List[Vision]:
        ...

    @abstractmethod
    def find_active_by_tenant(self, tenant_id: UUID) -> List[Vision]:
        ...

    @abstractmethod
    def save(self, entity: Vision) -> Vision:
        ...

    @abstractmethod
    def delete(self, vision_id: UUID) -> bool:
        ...


# ─── Strategic Theme Repository ──────────────────

class StrategicThemeRepository(ABC):
    """واسط ریپازیتوری تم راهبردی."""

    @abstractmethod
    def find_by_id(self, theme_id: UUID) -> Optional[StrategicTheme]:
        ...

    @abstractmethod
    def find_by_tenant(self, tenant_id: UUID) -> List[StrategicTheme]:
        ...

    @abstractmethod
    def find_by_vision(self, vision_id: UUID) -> List[StrategicTheme]:
        ...

    @abstractmethod
    def find_active_by_tenant(self, tenant_id: UUID) -> List[StrategicTheme]:
        ...

    @abstractmethod
    def save(self, entity: StrategicTheme) -> StrategicTheme:
        ...

    @abstractmethod
    def delete(self, theme_id: UUID) -> bool:
        ...


# ─── Objective Repository ────────────────────────

class ObjectiveRepository(ABC):
    """واسط ریپازیتوری هدف."""

    @abstractmethod
    def find_by_id(self, objective_id: UUID) -> Optional[Objective]:
        ...

    @abstractmethod
    def find_by_tenant(self, tenant_id: UUID) -> List[Objective]:
        ...

    @abstractmethod
    def find_by_theme(self, theme_id: UUID) -> List[Objective]:
        ...

    @abstractmethod
    def find_children(self, parent_id: UUID) -> List[Objective]:
        ...

    @abstractmethod
    def find_active_by_tenant(self, tenant_id: UUID) -> List[Objective]:
        ...

    @abstractmethod
    def save(self, entity: Objective) -> Objective:
        ...

    @abstractmethod
    def delete(self, objective_id: UUID) -> bool:
        ...


# ─── Key Result Repository ───────────────────────

class KeyResultRepository(ABC):
    """واسط ریپازیتوری نتیجه کلیدی."""

    @abstractmethod
    def find_by_id(self, key_result_id: UUID) -> Optional[KeyResult]:
        ...

    @abstractmethod
    def find_by_objective(self, objective_id: UUID) -> List[KeyResult]:
        ...

    @abstractmethod
    def save(self, entity: KeyResult) -> KeyResult:
        ...

    @abstractmethod
    def delete(self, key_result_id: UUID) -> bool:
        ...


# ─── Key Result CheckIn Repository ───────────────

class KeyResultCheckInRepository(ABC):
    """واسط ریپازیتوری ثبت پیشرفت."""

    @abstractmethod
    def find_by_id(self, check_in_id: UUID) -> Optional[KeyResultCheckIn]:
        ...

    @abstractmethod
    def find_by_key_result(self, key_result_id: UUID) -> List[KeyResultCheckIn]:
        ...

    @abstractmethod
    def save(self, entity: KeyResultCheckIn) -> KeyResultCheckIn:
        ...

    @abstractmethod
    def delete(self, check_in_id: UUID) -> bool:
        ...


# ─── KPI Definition Repository ───────────────────

class KPIDefinitionRepository(ABC):
    """واسط ریپازیتوری شاخص کلیدی عملکرد."""

    @abstractmethod
    def find_by_id(self, kpi_id: UUID) -> Optional[KPIDefinition]:
        ...

    @abstractmethod
    def find_by_tenant(self, tenant_id: UUID) -> List[KPIDefinition]:
        ...

    @abstractmethod
    def find_by_code(self, code: str, tenant_id: UUID) -> Optional[KPIDefinition]:
        ...

    @abstractmethod
    def find_active_by_tenant(self, tenant_id: UUID) -> List[KPIDefinition]:
        ...

    @abstractmethod
    def save(self, entity: KPIDefinition) -> KPIDefinition:
        ...

    @abstractmethod
    def delete(self, kpi_id: UUID) -> bool:
        ...


# ─── KPI Target Repository ───────────────────────

class KPITargetRepository(ABC):
    """واسط ریپازیتوری هدف‌گذاری KPI."""

    @abstractmethod
    def find_by_id(self, target_id: UUID) -> Optional[KPITarget]:
        ...

    @abstractmethod
    def find_by_kpi(self, kpi_id: UUID) -> List[KPITarget]:
        ...

    @abstractmethod
    def find_by_kpi_and_period(self, kpi_id: UUID, period_start, period_end) -> Optional[KPITarget]:
        ...

    @abstractmethod
    def save(self, entity: KPITarget) -> KPITarget:
        ...

    @abstractmethod
    def delete(self, target_id: UUID) -> bool:
        ...


# ─── KPI Actual Repository ───────────────────────

class KPIActualRepository(ABC):
    """واسط ریپازیتوری مقادیر واقعی KPI."""

    @abstractmethod
    def find_by_id(self, actual_id: UUID) -> Optional[KPIActual]:
        ...

    @abstractmethod
    def find_by_kpi(self, kpi_id: UUID) -> List[KPIActual]:
        ...

    @abstractmethod
    def find_by_kpi_and_period(self, kpi_id: UUID, period_start, period_end) -> List[KPIActual]:
        ...

    @abstractmethod
    def save(self, entity: KPIActual) -> KPIActual:
        ...

    @abstractmethod
    def delete(self, actual_id: UUID) -> bool:
        ...


# ─── KPI Assignment Repository ───────────────────

class KPIAssignmentRepository(ABC):
    """واسط ریپازیتوری تخصیص KPI."""

    @abstractmethod
    def find_by_id(self, assignment_id: UUID) -> Optional[KPIAssignment]:
        ...

    @abstractmethod
    def find_by_kpi(self, kpi_id: UUID) -> List[KPIAssignment]:
        ...

    @abstractmethod
    def find_by_entity(self, level: str, entity_id: UUID) -> List[KPIAssignment]:
        ...

    @abstractmethod
    def find_active_by_kpi(self, kpi_id: UUID) -> List[KPIAssignment]:
        ...

    @abstractmethod
    def save(self, entity: KPIAssignment) -> KPIAssignment:
        ...

    @abstractmethod
    def delete(self, assignment_id: UUID) -> bool:
        ...


# ─── Strategy Map Repository ─────────────────────

class StrategyMapRepository(ABC):
    """واسط ریپازیتوری نقشه راهبردی."""

    @abstractmethod
    def find_by_id(self, map_id: UUID) -> Optional[StrategyMap]:
        ...

    @abstractmethod
    def find_by_tenant(self, tenant_id: UUID) -> List[StrategyMap]:
        ...

    @abstractmethod
    def save(self, entity: StrategyMap) -> StrategyMap:
        ...

    @abstractmethod
    def delete(self, map_id: UUID) -> bool:
        ...


# ─── Strategy Map Perspective Repository ─────────

class StrategyMapPerspectiveRepository(ABC):
    """واسط ریپازیتوری دیدگاه نقشه."""

    @abstractmethod
    def find_by_id(self, perspective_id: UUID) -> Optional[StrategyMapPerspective]:
        ...

    @abstractmethod
    def find_by_map(self, map_id: UUID) -> List[StrategyMapPerspective]:
        ...

    @abstractmethod
    def save(self, entity: StrategyMapPerspective) -> StrategyMapPerspective:
        ...

    @abstractmethod
    def delete(self, perspective_id: UUID) -> bool:
        ...


# ─── Strategy Map Objective Repository ───────────

class StrategyMapObjectiveRepository(ABC):
    """واسط ریپازیتوری هدف روی نقشه."""

    @abstractmethod
    def find_by_id(self, smo_id: UUID) -> Optional[StrategyMapObjective]:
        ...

    @abstractmethod
    def find_by_map(self, map_id: UUID) -> List[StrategyMapObjective]:
        ...

    @abstractmethod
    def save(self, entity: StrategyMapObjective) -> StrategyMapObjective:
        ...

    @abstractmethod
    def delete(self, smo_id: UUID) -> bool:
        ...


# ─── Causal Link Repository ─────────────────────

class CausalLinkRepository(ABC):
    """واسط ریپازیتوری ارتباط علّی."""

    @abstractmethod
    def find_by_id(self, link_id: UUID) -> Optional[CausalLink]:
        ...

    @abstractmethod
    def find_by_map(self, map_id: UUID) -> List[CausalLink]:
        ...

    @abstractmethod
    def save(self, entity: CausalLink) -> CausalLink:
        ...

    @abstractmethod
    def delete(self, link_id: UUID) -> bool:
        ...


# ─── Scorecard Repository ────────────────────────

class ScorecardRepository(ABC):
    """واسط ریپازیتوری کارت امتیازی."""

    @abstractmethod
    def find_by_id(self, scorecard_id: UUID) -> Optional[Scorecard]:
        ...

    @abstractmethod
    def find_by_tenant(self, tenant_id: UUID) -> List[Scorecard]:
        ...

    @abstractmethod
    def save(self, entity: Scorecard) -> Scorecard:
        ...

    @abstractmethod
    def delete(self, scorecard_id: UUID) -> bool:
        ...


# ─── Scorecard Perspective Repository ────────────

class ScorecardPerspectiveRepository(ABC):
    """واسط ریپازیتوری دیدگاه کارت امتیازی."""

    @abstractmethod
    def find_by_id(self, perspective_id: UUID) -> Optional[ScorecardPerspective]:
        ...

    @abstractmethod
    def find_by_scorecard(self, scorecard_id: UUID) -> List[ScorecardPerspective]:
        ...

    @abstractmethod
    def save(self, entity: ScorecardPerspective) -> ScorecardPerspective:
        ...

    @abstractmethod
    def delete(self, perspective_id: UUID) -> bool:
        ...


# ─── Scorecard Measure Repository ────────────────

class ScorecardMeasureRepository(ABC):
    """واسط ریپازیتوری سنجه کارت امتیازی."""

    @abstractmethod
    def find_by_id(self, measure_id: UUID) -> Optional[ScorecardMeasure]:
        ...

    @abstractmethod
    def find_by_perspective(self, perspective_id: UUID) -> List[ScorecardMeasure]:
        ...

    @abstractmethod
    def save(self, entity: ScorecardMeasure) -> ScorecardMeasure:
        ...

    @abstractmethod
    def delete(self, measure_id: UUID) -> bool:
        ...


# ═══════════════════════════════════════════════════
# Stage-Gate Repositories
# ═══════════════════════════════════════════════════

from ..entities.gate_process import GateProcess
from ..entities.gate import Gate
from ..entities.gate_review import GateReview
from ..entities.gate_reviewer import GateReviewer
from ..entities.gate_deliverable import GateDeliverable


# ─── Gate Process Repository ─────────────────────

class GateProcessRepository(ABC):
    """واسط ریپازیتوری فرآیند Stage-Gate."""

    @abstractmethod
    def find_by_id(self, process_id: UUID) -> Optional[GateProcess]:
        ...

    @abstractmethod
    def find_all(self, tenant_id: UUID) -> List[GateProcess]:
        ...

    @abstractmethod
    def save(self, entity: GateProcess) -> GateProcess:
        ...

    @abstractmethod
    def delete(self, process_id: UUID) -> bool:
        ...


# ─── Gate Repository ─────────────────────────────

class GateRepository(ABC):
    """واسط ریپازیتوری دروازه."""

    @abstractmethod
    def find_by_id(self, gate_id: UUID) -> Optional[Gate]:
        ...

    @abstractmethod
    def find_by_process(self, process_id: UUID) -> List[Gate]:
        ...

    @abstractmethod
    def save(self, entity: Gate) -> Gate:
        ...

    @abstractmethod
    def delete(self, gate_id: UUID) -> bool:
        ...


# ─── Gate Review Repository ──────────────────────

class GateReviewRepository(ABC):
    """واسط ریپازیتوری بازبینی دروازه."""

    @abstractmethod
    def find_by_id(self, review_id: UUID) -> Optional[GateReview]:
        ...

    @abstractmethod
    def find_by_gate(self, gate_id: UUID) -> List[GateReview]:
        ...

    @abstractmethod
    def find_by_entity(self, entity_id: UUID, entity_type: str) -> List[GateReview]:
        ...

    @abstractmethod
    def save(self, entity: GateReview) -> GateReview:
        ...

    @abstractmethod
    def delete(self, review_id: UUID) -> bool:
        ...


# ─── Gate Reviewer Repository ────────────────────

class GateReviewerRepository(ABC):
    """واسط ریپازیتوری بازبین دروازه."""

    @abstractmethod
    def find_by_id(self, reviewer_id: UUID) -> Optional[GateReviewer]:
        ...

    @abstractmethod
    def find_by_review(self, review_id: UUID) -> List[GateReviewer]:
        ...

    @abstractmethod
    def save(self, entity: GateReviewer) -> GateReviewer:
        ...

    @abstractmethod
    def delete(self, reviewer_id: UUID) -> bool:
        ...


# ─── Gate Deliverable Repository ─────────────────

class GateDeliverableRepository(ABC):
    """واسط ریپازیتوری تحویل‌دادنی دروازه."""

    @abstractmethod
    def find_by_id(self, deliverable_id: UUID) -> Optional[GateDeliverable]:
        ...

    @abstractmethod
    def find_by_review(self, review_id: UUID) -> List[GateDeliverable]:
        ...

    @abstractmethod
    def save(self, entity: GateDeliverable) -> GateDeliverable:
        ...

    @abstractmethod
    def delete(self, deliverable_id: UUID) -> bool:
        ...


# ═══════════════════════════════════════════════════
# Policy Repositories
# ═══════════════════════════════════════════════════

from ..entities.policy import Policy
from ..entities.policy_acknowledgment import PolicyAcknowledgment


class PolicyRepository(ABC):
    """واسط ریپازیتوری سیاست سازمانی."""

    @abstractmethod
    def find_by_id(self, policy_id: UUID) -> Optional[Policy]:
        ...

    @abstractmethod
    def find_all(self, tenant_id: UUID) -> List[Policy]:
        ...

    @abstractmethod
    def find_by_code(self, code: str, tenant_id: UUID) -> Optional[Policy]:
        ...

    @abstractmethod
    def save(self, entity: Policy) -> Policy:
        ...

    @abstractmethod
    def delete(self, policy_id: UUID) -> bool:
        ...


class PolicyAcknowledgmentRepository(ABC):
    """واسط ریپازیتوری تأیید آشنایی سیاست."""

    @abstractmethod
    def find_by_id(self, ack_id: UUID) -> Optional[PolicyAcknowledgment]:
        ...

    @abstractmethod
    def find_by_policy(self, policy_id: UUID) -> List[PolicyAcknowledgment]:
        ...

    @abstractmethod
    def find_by_user(self, user_id: UUID) -> List[PolicyAcknowledgment]:
        ...

    @abstractmethod
    def save(self, entity: PolicyAcknowledgment) -> PolicyAcknowledgment:
        ...

    @abstractmethod
    def delete(self, ack_id: UUID) -> bool:
        ...
