"""
PPM Domain — Repository Interfaces

اینترفیس‌های ریپازیتوری ماژول مدیریت پرتفولیو و برنامه.
"""

from abc import ABC, abstractmethod
from typing import List, Optional
from uuid import UUID


class PortfolioRepository(ABC):
    """اینترفیس ریپازیتوری پرتفولیو."""

    @abstractmethod
    def save(self, entity): ...

    @abstractmethod
    def get_by_id(self, id: UUID): ...

    @abstractmethod
    def find(self, **filters) -> list: ...

    @abstractmethod
    def delete(self, id: UUID) -> None: ...

    @abstractmethod
    def find_by_status(self, status: str) -> list: ...

    @abstractmethod
    def find_by_owner(self, owner_id: UUID) -> list: ...

    @abstractmethod
    def find_children(self, parent_id: UUID) -> list: ...


# Alias for DDD convention
IPortfolioRepository = PortfolioRepository


class ProgramRepository(ABC):
    """اینترفیس ریپازیتوری برنامه."""

    @abstractmethod
    def save(self, entity): ...

    @abstractmethod
    def get_by_id(self, id: UUID): ...

    @abstractmethod
    def find(self, **filters) -> list: ...

    @abstractmethod
    def delete(self, id: UUID) -> None: ...

    @abstractmethod
    def find_by_portfolio(self, portfolio_id: UUID) -> list: ...

    @abstractmethod
    def find_by_status(self, status: str) -> list: ...

    @abstractmethod
    def find_by_manager(self, manager_id: UUID) -> list: ...


IProgramRepository = ProgramRepository


class ProgramProjectRepository(ABC):
    """اینترفیس ریپازیتوری ارتباط برنامه-پروژه."""

    @abstractmethod
    def save(self, entity): ...

    @abstractmethod
    def get_by_id(self, id: UUID): ...

    @abstractmethod
    def find(self, **filters) -> list: ...

    @abstractmethod
    def delete(self, id: UUID) -> None: ...

    @abstractmethod
    def find_by_program(self, program_id: UUID) -> list: ...

    @abstractmethod
    def find_by_project(self, project_id: UUID) -> list: ...


IProgramProjectRepository = ProgramProjectRepository


class BusinessCaseRepository(ABC):
    """اینترفیس ریپازیتوری کیس تجاری."""

    @abstractmethod
    def save(self, entity): ...

    @abstractmethod
    def get_by_id(self, id: UUID): ...

    @abstractmethod
    def find(self, **filters) -> list: ...

    @abstractmethod
    def delete(self, id: UUID) -> None: ...

    @abstractmethod
    def find_by_program(self, program_id: UUID) -> list: ...

    @abstractmethod
    def find_by_status(self, status: str) -> list: ...


IBusinessCaseRepository = BusinessCaseRepository


class CashFlowProjectionRepository(ABC):
    """اینترفیس ریپازیتوری پیش‌بینی جریان نقدی."""

    @abstractmethod
    def save(self, entity): ...

    @abstractmethod
    def get_by_id(self, id: UUID): ...

    @abstractmethod
    def find(self, **filters) -> list: ...

    @abstractmethod
    def delete(self, id: UUID) -> None: ...

    @abstractmethod
    def find_by_business_case(self, business_case_id: UUID) -> list: ...


ICashFlowProjectionRepository = CashFlowProjectionRepository


class ScoringModelRepository(ABC):
    """اینترفیس ریپازیتوری مدل امتیازدهی."""

    @abstractmethod
    def save(self, entity): ...

    @abstractmethod
    def get_by_id(self, id: UUID): ...

    @abstractmethod
    def find(self, **filters) -> list: ...

    @abstractmethod
    def delete(self, id: UUID) -> None: ...

    @abstractmethod
    def find_active_by_portfolio(self, portfolio_id: UUID): ...


IScoringModelRepository = ScoringModelRepository


class ScoringCriterionRepository(ABC):
    """اینترفیس ریپازیتوری معیار امتیازدهی."""

    @abstractmethod
    def save(self, entity): ...

    @abstractmethod
    def get_by_id(self, id: UUID): ...

    @abstractmethod
    def find(self, **filters) -> list: ...

    @abstractmethod
    def delete(self, id: UUID) -> None: ...

    @abstractmethod
    def find_by_model(self, scoring_model_id: UUID) -> list: ...


IScoringCriterionRepository = ScoringCriterionRepository


class ProjectScoreRepository(ABC):
    """اینترفیس ریپازیتوری امتیاز پروژه."""

    @abstractmethod
    def save(self, entity): ...

    @abstractmethod
    def get_by_id(self, id: UUID): ...

    @abstractmethod
    def find(self, **filters) -> list: ...

    @abstractmethod
    def delete(self, id: UUID) -> None: ...

    @abstractmethod
    def find_by_project(self, project_id: UUID, scoring_model_id: UUID) -> list: ...

    @abstractmethod
    def find_by_model(self, scoring_model_id: UUID) -> list: ...


IProjectScoreRepository = ProjectScoreRepository


class BenefitPlanRepository(ABC):
    """اینترفیس ریپازیتوری برنامه تحقق منافع."""

    @abstractmethod
    def save(self, entity): ...

    @abstractmethod
    def get_by_id(self, id: UUID): ...

    @abstractmethod
    def find(self, **filters) -> list: ...

    @abstractmethod
    def delete(self, id: UUID) -> None: ...

    @abstractmethod
    def find_by_program(self, program_id: UUID) -> list: ...

    @abstractmethod
    def find_by_portfolio(self, portfolio_id: UUID) -> list: ...


IBenefitPlanRepository = BenefitPlanRepository


class BenefitRepository(ABC):
    """اینترفیس ریپازیتوری منفعت."""

    @abstractmethod
    def save(self, entity): ...

    @abstractmethod
    def get_by_id(self, id: UUID): ...

    @abstractmethod
    def find(self, **filters) -> list: ...

    @abstractmethod
    def delete(self, id: UUID) -> None: ...

    @abstractmethod
    def find_by_plan(self, benefit_plan_id: UUID) -> list: ...

    @abstractmethod
    def find_by_status(self, status: str) -> list: ...


IBenefitRepository = BenefitRepository


class BenefitMeasurementRepository(ABC):
    """اینترفیس ریپازیتوری اندازه‌گیری منفعت."""

    @abstractmethod
    def save(self, entity): ...

    @abstractmethod
    def get_by_id(self, id: UUID): ...

    @abstractmethod
    def find(self, **filters) -> list: ...

    @abstractmethod
    def delete(self, id: UUID) -> None: ...

    @abstractmethod
    def find_by_benefit(self, benefit_id: UUID) -> list: ...


IBenefitMeasurementRepository = BenefitMeasurementRepository


class CapacityPlanRepository(ABC):
    """اینترفیس ریپازیتوری برنامه ظرفیت."""

    @abstractmethod
    def save(self, entity): ...

    @abstractmethod
    def get_by_id(self, id: UUID): ...

    @abstractmethod
    def find(self, **filters) -> list: ...

    @abstractmethod
    def delete(self, id: UUID) -> None: ...

    @abstractmethod
    def find_by_portfolio(self, portfolio_id: UUID) -> list: ...


ICapacityPlanRepository = CapacityPlanRepository


class ResourceDemandRepository(ABC):
    """اینترفیس ریپازیتوری تقاضای منابع."""

    @abstractmethod
    def save(self, entity): ...

    @abstractmethod
    def get_by_id(self, id: UUID): ...

    @abstractmethod
    def find(self, **filters) -> list: ...

    @abstractmethod
    def delete(self, id: UUID) -> None: ...

    @abstractmethod
    def find_by_plan(self, capacity_plan_id: UUID) -> list: ...

    @abstractmethod
    def find_by_project(self, project_id: UUID) -> list: ...


IResourceDemandRepository = ResourceDemandRepository


class ResourceSupplyRepository(ABC):
    """اینترفیس ریپازیتوری عرضه منابع."""

    @abstractmethod
    def save(self, entity): ...

    @abstractmethod
    def get_by_id(self, id: UUID): ...

    @abstractmethod
    def find(self, **filters) -> list: ...

    @abstractmethod
    def delete(self, id: UUID) -> None: ...

    @abstractmethod
    def find_by_plan(self, capacity_plan_id: UUID) -> list: ...


IResourceSupplyRepository = ResourceSupplyRepository


class CrossProjectDependencyRepository(ABC):
    """اینترفیس ریپازیتوری وابستگی بین پروژه‌ای."""

    @abstractmethod
    def save(self, entity): ...

    @abstractmethod
    def get_by_id(self, id: UUID): ...

    @abstractmethod
    def find(self, **filters) -> list: ...

    @abstractmethod
    def delete(self, id: UUID) -> None: ...

    @abstractmethod
    def find_by_predecessor(self, project_id: UUID) -> list: ...

    @abstractmethod
    def find_by_successor(self, project_id: UUID) -> list: ...

    @abstractmethod
    def find_by_project(self, project_id: UUID) -> list:
        """تمام وابستگی‌هایی که پروژه در آنها predecessor یا successor است."""
        ...

    @abstractmethod
    def find_active(self) -> list: ...


ICrossProjectDependencyRepository = CrossProjectDependencyRepository
