"""
PM Module — Repository Interfaces (ABC)

اینترفیس‌های Repository — Domain Layer.
پیاده‌سازی در Infrastructure Layer.
"""

from abc import ABC, abstractmethod
from typing import Optional, List, Dict
from uuid import UUID
from datetime import date

from shared.base_classes.repository import BaseRepository, TenantAwareRepository

from ..entities.project import Project
from ..entities.task import Task, Dependency, TaskAssignment
from ..entities.resource import Resource, ResourceAssignment
from ..entities.cost import Budget, CostEntry
from ..entities.risk import Risk
from ..entities.supporting import (
    Baseline, Calendar, Holiday,
    ChangeRequest, Timesheet,
    ProjectMember, Comment, ActivityLog,
)
from ..entities.kanban import (
    TaskLabel, TaskLabelAssignment,
    TaskAttachment, TaskChecklist, TaskChecklistItem,
    RACIAssignment,
)
from ..entities.advanced import (
    ActivityCodeType, ActivityCodeValue, TaskActivityCode,
    UDFDefinition, UDFValue,
    ResourceSkill, ResourceAvailability, ResourceCostRate,
    CostAccount, FundingSource, CashFlowEntry,
    ScheduleHealthSnapshot, ProjectTemplate,
)
from ..entities.issue import Issue


class ProjectRepository(BaseRepository[Project], ABC):
    """Repository برای پروژه."""

    @abstractmethod
    def find_by_code(self, code: str, tenant_id: UUID) -> Optional[Project]:
        pass

    @abstractmethod
    def find_by_company(self, company_id: UUID, tenant_id: UUID) -> List[Project]:
        pass

    @abstractmethod
    def find_by_manager(self, manager_id: UUID, tenant_id: UUID) -> List[Project]:
        pass

    @abstractmethod
    def find_by_status(self, status: str, tenant_id: UUID) -> List[Project]:
        pass

    @abstractmethod
    def find_children(self, parent_id: UUID, tenant_id: UUID) -> List[Project]:
        pass

    @abstractmethod
    def find_portfolio_tree(self, tenant_id: UUID) -> List[Project]:
        pass


class TaskRepository(BaseRepository[Task], ABC):
    """Repository برای تسک."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID) -> List[Task]:
        pass

    @abstractmethod
    def find_children(self, parent_id: UUID, tenant_id: UUID) -> List[Task]:
        pass

    @abstractmethod
    def find_root_tasks(self, project_id: UUID, tenant_id: UUID) -> List[Task]:
        pass

    @abstractmethod
    def find_milestones(self, project_id: UUID, tenant_id: UUID) -> List[Task]:
        pass

    @abstractmethod
    def find_critical_path(self, project_id: UUID, tenant_id: UUID) -> List[Task]:
        pass

    @abstractmethod
    def find_by_assignee(self, assignee_id: UUID, tenant_id: UUID) -> List[Task]:
        pass

    @abstractmethod
    def get_max_sort_order(self, project_id: UUID, parent_id: Optional[UUID], tenant_id: UUID) -> int:
        pass

    @abstractmethod
    def bulk_update(self, tasks: List[Task]) -> List[Task]:
        pass


class DependencyRepository(BaseRepository[Dependency], ABC):
    """Repository برای وابستگی."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID) -> List[Dependency]:
        pass

    @abstractmethod
    def find_predecessors(self, task_id: UUID, tenant_id: UUID) -> List[Dependency]:
        pass

    @abstractmethod
    def find_successors(self, task_id: UUID, tenant_id: UUID) -> List[Dependency]:
        pass

    @abstractmethod
    def exists_dependency(self, predecessor_id: UUID, successor_id: UUID, tenant_id: UUID) -> bool:
        pass


class TaskAssignmentRepository(BaseRepository[TaskAssignment], ABC):
    """Repository برای تخصیص تسک."""

    @abstractmethod
    def find_by_task(self, task_id: UUID, tenant_id: UUID) -> List[TaskAssignment]:
        pass

    @abstractmethod
    def find_by_user(self, user_id: UUID, tenant_id: UUID) -> List[TaskAssignment]:
        pass

    @abstractmethod
    def find_active_by_task(self, task_id: UUID, tenant_id: UUID) -> List[TaskAssignment]:
        pass

    @abstractmethod
    def find_primary_assignee(self, task_id: UUID, tenant_id: UUID) -> Optional[TaskAssignment]:
        pass


class ResourceRepository(BaseRepository[Resource], ABC):
    """Repository برای منبع."""

    @abstractmethod
    def find_by_type(self, resource_type: str, tenant_id: UUID) -> List[Resource]:
        pass

    @abstractmethod
    def find_by_company(self, company_id: UUID, tenant_id: UUID) -> List[Resource]:
        pass

    @abstractmethod
    def find_by_employee(self, employee_id: UUID, tenant_id: UUID) -> Optional[Resource]:
        pass


class ResourceAssignmentRepository(BaseRepository[ResourceAssignment], ABC):
    """Repository برای تخصیص منبع."""

    @abstractmethod
    def find_by_task(self, task_id: UUID, tenant_id: UUID) -> List[ResourceAssignment]:
        pass

    @abstractmethod
    def find_by_resource(self, resource_id: UUID, tenant_id: UUID) -> List[ResourceAssignment]:
        pass

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID) -> List[ResourceAssignment]:
        pass

    @abstractmethod
    def get_resource_utilization(
        self, resource_id: UUID, start_date: date, end_date: date, tenant_id: UUID
    ) -> Dict:
        pass


class BudgetRepository(BaseRepository[Budget], ABC):
    """Repository برای بودجه."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID) -> List[Budget]:
        pass


class CostEntryRepository(BaseRepository[CostEntry], ABC):
    """Repository برای ثبت هزینه."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID) -> List[CostEntry]:
        pass

    @abstractmethod
    def find_by_task(self, task_id: UUID, tenant_id: UUID) -> List[CostEntry]:
        pass

    @abstractmethod
    def get_total_cost(self, project_id: UUID, tenant_id: UUID) -> dict:
        pass


class RiskRepository(BaseRepository[Risk], ABC):
    """Repository برای ریسک."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID) -> List[Risk]:
        pass

    @abstractmethod
    def find_by_status(self, status: str, project_id: UUID, tenant_id: UUID) -> List[Risk]:
        pass

    @abstractmethod
    def get_risk_matrix(self, project_id: UUID, tenant_id: UUID) -> Dict:
        pass


class BaselineRepository(BaseRepository[Baseline], ABC):
    """Repository برای خط پایه."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID) -> List[Baseline]:
        pass

    @abstractmethod
    def find_active(self, project_id: UUID, tenant_id: UUID) -> Optional[Baseline]:
        pass


class CalendarRepository(BaseRepository[Calendar], ABC):
    """Repository برای تقویم."""

    @abstractmethod
    def find_default(self, tenant_id: UUID) -> Optional[Calendar]:
        pass


class HolidayRepository(BaseRepository[Holiday], ABC):
    """Repository برای تعطیلات."""

    @abstractmethod
    def find_by_calendar(self, calendar_id: UUID, tenant_id: UUID) -> List[Holiday]:
        pass

    @abstractmethod
    def find_by_date_range(
        self, calendar_id: UUID, start_date: date, end_date: date, tenant_id: UUID
    ) -> List[Holiday]:
        pass


class ChangeRequestRepository(BaseRepository[ChangeRequest], ABC):
    """Repository برای درخواست تغییر."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID) -> List[ChangeRequest]:
        pass

    @abstractmethod
    def find_by_status(self, status: str, project_id: UUID, tenant_id: UUID) -> List[ChangeRequest]:
        pass


class TimesheetRepository(BaseRepository[Timesheet], ABC):
    """Repository برای تایم‌شیت."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID) -> List[Timesheet]:
        pass

    @abstractmethod
    def find_by_user(self, user_id: UUID, tenant_id: UUID) -> List[Timesheet]:
        pass

    @abstractmethod
    def find_by_date_range(
        self, project_id: UUID, start_date: date, end_date: date, tenant_id: UUID
    ) -> List[Timesheet]:
        pass


class ProjectMemberRepository(BaseRepository[ProjectMember], ABC):
    """Repository برای عضو پروژه."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID) -> List[ProjectMember]:
        pass

    @abstractmethod
    def find_by_user(self, user_id: UUID, tenant_id: UUID) -> List[ProjectMember]:
        pass

    @abstractmethod
    def find_member(self, project_id: UUID, user_id: UUID, tenant_id: UUID) -> Optional[ProjectMember]:
        pass


class CommentRepository(BaseRepository[Comment], ABC):
    """Repository برای نظر."""

    @abstractmethod
    def find_by_task(self, task_id: UUID, tenant_id: UUID) -> List[Comment]:
        pass

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID) -> List[Comment]:
        pass


class ActivityLogRepository(BaseRepository[ActivityLog], ABC):
    """Repository برای لاگ فعالیت."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID) -> List[ActivityLog]:
        pass

    @abstractmethod
    def find_recent(self, project_id: UUID, limit: int, tenant_id: UUID) -> List[ActivityLog]:
        pass


# ═══════════════════════════════════════════════════
# Kanban Repositories
# ═══════════════════════════════════════════════════

class TaskLabelRepository(BaseRepository[TaskLabel], ABC):
    """Repository برای برچسب تسک."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID) -> List[TaskLabel]:
        pass


class TaskLabelAssignmentRepository(BaseRepository[TaskLabelAssignment], ABC):
    """Repository برای اختصاص برچسب به تسک."""

    @abstractmethod
    def find_by_task(self, task_id: UUID, tenant_id: UUID) -> List[TaskLabelAssignment]:
        pass

    @abstractmethod
    def find_by_label(self, label_id: UUID, tenant_id: UUID) -> List[TaskLabelAssignment]:
        pass


class TaskAttachmentRepository(BaseRepository[TaskAttachment], ABC):
    """Repository برای پیوست تسک."""

    @abstractmethod
    def find_by_task(self, task_id: UUID, tenant_id: UUID) -> List[TaskAttachment]:
        pass


class TaskChecklistRepository(BaseRepository[TaskChecklist], ABC):
    """Repository برای چک‌لیست تسک."""

    @abstractmethod
    def find_by_task(self, task_id: UUID, tenant_id: UUID) -> List[TaskChecklist]:
        pass


class TaskChecklistItemRepository(BaseRepository[TaskChecklistItem], ABC):
    """Repository برای آیتم چک‌لیست."""

    @abstractmethod
    def find_by_checklist(self, checklist_id: UUID, tenant_id: UUID) -> List[TaskChecklistItem]:
        pass


class RACIAssignmentRepository(BaseRepository[RACIAssignment], ABC):
    """Repository برای اختصاص RACI."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID) -> List[RACIAssignment]:
        pass

    @abstractmethod
    def find_by_task(self, task_id: UUID, tenant_id: UUID) -> List[RACIAssignment]:
        pass

    @abstractmethod
    def find_by_user(self, user_id: UUID, project_id: UUID, tenant_id: UUID) -> List[RACIAssignment]:
        pass


# ═══════════════════════════════════════════════════
# Activity Code Repositories
# ═══════════════════════════════════════════════════

class ActivityCodeTypeRepository(BaseRepository[ActivityCodeType], ABC):
    """Repository برای نوع کد فعالیت."""

    @abstractmethod
    def find_by_scope(self, scope: str, tenant_id: UUID) -> List[ActivityCodeType]:
        pass

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID) -> List[ActivityCodeType]:
        pass

    @abstractmethod
    def find_global(self, tenant_id: UUID) -> List[ActivityCodeType]:
        pass


class ActivityCodeValueRepository(BaseRepository[ActivityCodeValue], ABC):
    """Repository برای مقدار کد فعالیت."""

    @abstractmethod
    def find_by_type(self, code_type_id: UUID, tenant_id: UUID) -> List[ActivityCodeValue]:
        pass

    @abstractmethod
    def find_children(self, parent_id: UUID, tenant_id: UUID) -> List[ActivityCodeValue]:
        pass

    @abstractmethod
    def find_root_values(self, code_type_id: UUID, tenant_id: UUID) -> List[ActivityCodeValue]:
        pass


class TaskActivityCodeRepository(BaseRepository[TaskActivityCode], ABC):
    """Repository برای اختصاص کد فعالیت به تسک."""

    @abstractmethod
    def find_by_task(self, task_id: UUID, tenant_id: UUID) -> List[TaskActivityCode]:
        pass

    @abstractmethod
    def find_by_code_value(self, code_value_id: UUID, tenant_id: UUID) -> List[TaskActivityCode]:
        pass

    @abstractmethod
    def find_tasks_by_code_type(
        self, code_type_id: UUID, code_value_id: UUID, tenant_id: UUID
    ) -> List[TaskActivityCode]:
        pass


# ═══════════════════════════════════════════════════
# UDF Repositories
# ═══════════════════════════════════════════════════

class UDFDefinitionRepository(BaseRepository[UDFDefinition], ABC):
    """Repository برای تعریف فیلد سفارشی."""

    @abstractmethod
    def find_by_entity_type(self, entity_type: str, tenant_id: UUID) -> List[UDFDefinition]:
        pass

    @abstractmethod
    def find_active(self, entity_type: str, tenant_id: UUID) -> List[UDFDefinition]:
        pass

    @abstractmethod
    def find_by_code(self, code: str, tenant_id: UUID) -> Optional[UDFDefinition]:
        pass


class UDFValueRepository(BaseRepository[UDFValue], ABC):
    """Repository برای مقدار فیلد سفارشی."""

    @abstractmethod
    def find_by_entity(self, entity_id: UUID, entity_type: str, tenant_id: UUID) -> List[UDFValue]:
        pass

    @abstractmethod
    def find_by_definition(self, definition_id: UUID, tenant_id: UUID) -> List[UDFValue]:
        pass

    @abstractmethod
    def find_value(
        self, definition_id: UUID, entity_id: UUID, tenant_id: UUID
    ) -> Optional[UDFValue]:
        pass


# ═══════════════════════════════════════════════════
# Advanced Resource Repositories
# ═══════════════════════════════════════════════════

class ResourceSkillRepository(BaseRepository[ResourceSkill], ABC):
    """Repository برای مهارت منبع."""

    @abstractmethod
    def find_by_resource(self, resource_id: UUID, tenant_id: UUID) -> List[ResourceSkill]:
        pass

    @abstractmethod
    def find_by_skill(self, skill_name: str, tenant_id: UUID) -> List[ResourceSkill]:
        pass


class ResourceAvailabilityRepository(BaseRepository[ResourceAvailability], ABC):
    """Repository برای دسترسی منبع."""

    @abstractmethod
    def find_by_resource(self, resource_id: UUID, tenant_id: UUID) -> List[ResourceAvailability]:
        pass

    @abstractmethod
    def find_by_date_range(
        self, resource_id: UUID, start_date: date, end_date: date, tenant_id: UUID
    ) -> List[ResourceAvailability]:
        pass


class ResourceCostRateRepository(BaseRepository[ResourceCostRate], ABC):
    """Repository برای نرخ هزینه منبع."""

    @abstractmethod
    def find_by_resource(self, resource_id: UUID, tenant_id: UUID) -> List[ResourceCostRate]:
        pass

    @abstractmethod
    def find_effective_rate(
        self, resource_id: UUID, on_date: date, tenant_id: UUID
    ) -> Optional[ResourceCostRate]:
        pass


# ═══════════════════════════════════════════════════
# CBS & Funding Repositories
# ═══════════════════════════════════════════════════

class CostAccountRepository(BaseRepository[CostAccount], ABC):
    """Repository برای حساب هزینه."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID) -> List[CostAccount]:
        pass

    @abstractmethod
    def find_children(self, parent_id: UUID, tenant_id: UUID) -> List[CostAccount]:
        pass

    @abstractmethod
    def find_root_accounts(self, project_id: UUID, tenant_id: UUID) -> List[CostAccount]:
        pass

    @abstractmethod
    def find_by_code(self, code: str, project_id: UUID, tenant_id: UUID) -> Optional[CostAccount]:
        pass


class FundingSourceRepository(BaseRepository[FundingSource], ABC):
    """Repository برای منبع مالی."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID) -> List[FundingSource]:
        pass

    @abstractmethod
    def find_active(self, project_id: UUID, tenant_id: UUID) -> List[FundingSource]:
        pass


class CashFlowEntryRepository(BaseRepository[CashFlowEntry], ABC):
    """Repository برای جریان نقدی."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID) -> List[CashFlowEntry]:
        pass

    @abstractmethod
    def find_by_period(
        self, project_id: UUID, start_date: date, end_date: date, tenant_id: UUID
    ) -> List[CashFlowEntry]:
        pass


# ═══════════════════════════════════════════════════
# Schedule Health & Template Repositories
# ═══════════════════════════════════════════════════

class ScheduleHealthSnapshotRepository(BaseRepository[ScheduleHealthSnapshot], ABC):
    """Repository برای اسنپ‌شات سلامت زمان‌بندی."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID) -> List[ScheduleHealthSnapshot]:
        pass

    @abstractmethod
    def find_latest(self, project_id: UUID, tenant_id: UUID) -> Optional[ScheduleHealthSnapshot]:
        pass

    @abstractmethod
    def find_by_date_range(
        self, project_id: UUID, start_date: date, end_date: date, tenant_id: UUID
    ) -> List[ScheduleHealthSnapshot]:
        pass


class ProjectTemplateRepository(BaseRepository[ProjectTemplate], ABC):
    """Repository برای قالب پروژه."""

    @abstractmethod
    def find_active(self, tenant_id: UUID) -> List[ProjectTemplate]:
        pass

    @abstractmethod
    def find_by_category(self, category: str, tenant_id: UUID) -> List[ProjectTemplate]:
        pass


# ═══════════════════════════════════════════════════
# Issue Repository
# ═══════════════════════════════════════════════════

class IssueRepository(BaseRepository[Issue], ABC):
    """Repository برای مسئله (Issue Log)."""

    @abstractmethod
    def find_by_project(self, project_id: UUID) -> List[Issue]:
        pass

    @abstractmethod
    def find_open_issues(self, project_id: UUID) -> List[Issue]:
        pass

    @abstractmethod
    def find_by_assignee(self, assignee_id: UUID) -> List[Issue]:
        pass

    @abstractmethod
    def find_critical(self, project_id: UUID) -> List[Issue]:
        pass

    @abstractmethod
    def count_by_status(self, project_id: UUID) -> dict:
        pass


# ═══════════════════════════════════════════════════
# OBS Node Repository
# ═══════════════════════════════════════════════════

class OBSNodeRepository(BaseRepository['OBSNode'], ABC):
    """Repository برای گره ساختار شکست سازمانی (OBS)."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID = None) -> List['OBSNode']:
        pass

    @abstractmethod
    def find_root_nodes(self, project_id: UUID, tenant_id: UUID = None) -> List['OBSNode']:
        pass

    @abstractmethod
    def find_children(self, parent_id: UUID, tenant_id: UUID = None) -> List['OBSNode']:
        pass

    @abstractmethod
    def find_by_code(self, code: str, project_id: UUID, tenant_id: UUID = None):
        pass

    @abstractmethod
    def find_by_manager(self, manager_id: UUID, tenant_id: UUID = None) -> List['OBSNode']:
        pass


# ═══════════════════════════════════════════════════
# RBS Node Repository
# ═══════════════════════════════════════════════════

class RBSNodeRepository(BaseRepository['RBSNode'], ABC):
    """Repository برای گره ساختار شکست منابع (RBS)."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID = None) -> List['RBSNode']:
        pass

    @abstractmethod
    def find_root_nodes(self, project_id: UUID, tenant_id: UUID = None) -> List['RBSNode']:
        pass

    @abstractmethod
    def find_children(self, parent_id: UUID, tenant_id: UUID = None) -> List['RBSNode']:
        pass

    @abstractmethod
    def find_by_code(self, code: str, project_id: UUID, tenant_id: UUID = None):
        pass

    @abstractmethod
    def find_by_resource_type(self, resource_type: str, project_id: UUID, tenant_id: UUID = None) -> List['RBSNode']:
        pass


# ═══════════════════════════════════════════════════
# Quality Plan Repository
# ═══════════════════════════════════════════════════

class QualityPlanRepository(BaseRepository['QualityPlan'], ABC):
    """Repository برای طرح کیفیت."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID = None) -> List['QualityPlan']:
        pass

    @abstractmethod
    def find_active_by_project(self, project_id: UUID, tenant_id: UUID = None) -> List['QualityPlan']:
        pass


# ═══════════════════════════════════════════════════
# Inspection Repository
# ═══════════════════════════════════════════════════

class InspectionRepository(BaseRepository['Inspection'], ABC):
    """Repository برای بازرسی."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID = None) -> List['Inspection']:
        pass

    @abstractmethod
    def find_by_inspector(self, inspector_id: UUID, tenant_id: UUID = None) -> List['Inspection']:
        pass

    @abstractmethod
    def find_by_quality_plan(self, quality_plan_id: UUID, tenant_id: UUID = None) -> List['Inspection']:
        pass

    @abstractmethod
    def find_by_code(self, code: str, project_id: UUID, tenant_id: UUID = None):
        pass


# ═══════════════════════════════════════════════════
# NCR Repository
# ═══════════════════════════════════════════════════

class NCRRepository(BaseRepository['NCR'], ABC):
    """Repository برای عدم انطباق."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID = None) -> List['NCR']:
        pass

    @abstractmethod
    def find_by_inspection(self, inspection_id: UUID, tenant_id: UUID = None) -> List['NCR']:
        pass

    @abstractmethod
    def find_by_code(self, code: str, project_id: UUID, tenant_id: UUID = None):
        pass

    @abstractmethod
    def find_open_by_project(self, project_id: UUID, tenant_id: UUID = None) -> List['NCR']:
        pass


# ═══════════════════════════════════════════════════
# Quality Checklist Repository
# ═══════════════════════════════════════════════════

class QualityChecklistRepository(BaseRepository['QualityChecklist'], ABC):
    """Repository برای چک‌لیست کیفیت."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID = None) -> List['QualityChecklist']:
        pass

    @abstractmethod
    def find_by_quality_plan(self, quality_plan_id: UUID, tenant_id: UUID = None) -> List['QualityChecklist']:
        pass


class QualityChecklistItemRepository(BaseRepository['QualityChecklistItem'], ABC):
    """Repository برای آیتم چک‌لیست."""

    @abstractmethod
    def find_by_checklist(self, checklist_id: UUID, tenant_id: UUID = None) -> List['QualityChecklistItem']:
        pass


class ProjectDocumentRepository(BaseRepository['ProjectDocument'], ABC):
    """Repository برای ارتباط اسناد با پروژه."""

    @abstractmethod
    def find_by_project(self, project_id: UUID, tenant_id: UUID = None) -> List['ProjectDocument']:
        pass

    @abstractmethod
    def find_by_entity(self, entity_type: str, entity_id: UUID, tenant_id: UUID = None) -> List['ProjectDocument']:
        pass

    @abstractmethod
    def find_by_document(self, document_id: UUID, tenant_id: UUID = None) -> Optional['ProjectDocument']:
        pass


# ═══════════════════════════════════════════════════
# Backward-compatible aliases (I-prefix convention)
# ═══════════════════════════════════════════════════

IProjectRepository = ProjectRepository
ITaskRepository = TaskRepository
IDependencyRepository = DependencyRepository
ITaskAssignmentRepository = TaskAssignmentRepository
IResourceRepository = ResourceRepository
IResourceAssignmentRepository = ResourceAssignmentRepository
IBudgetRepository = BudgetRepository
ICostEntryRepository = CostEntryRepository
IRiskRepository = RiskRepository
IBaselineRepository = BaselineRepository
ICalendarRepository = CalendarRepository
IHolidayRepository = HolidayRepository
IChangeRequestRepository = ChangeRequestRepository
ITimesheetRepository = TimesheetRepository
IProjectMemberRepository = ProjectMemberRepository
ICommentRepository = CommentRepository
IActivityLogRepository = ActivityLogRepository
ITaskLabelRepository = TaskLabelRepository
ITaskLabelAssignmentRepository = TaskLabelAssignmentRepository
ITaskAttachmentRepository = TaskAttachmentRepository
ITaskChecklistRepository = TaskChecklistRepository
ITaskChecklistItemRepository = TaskChecklistItemRepository
IRACIAssignmentRepository = RACIAssignmentRepository
IActivityCodeTypeRepository = ActivityCodeTypeRepository
IActivityCodeValueRepository = ActivityCodeValueRepository
ITaskActivityCodeRepository = TaskActivityCodeRepository
IUDFDefinitionRepository = UDFDefinitionRepository
IUDFValueRepository = UDFValueRepository
IResourceSkillRepository = ResourceSkillRepository
IResourceAvailabilityRepository = ResourceAvailabilityRepository
IResourceCostRateRepository = ResourceCostRateRepository
ICostAccountRepository = CostAccountRepository
IFundingSourceRepository = FundingSourceRepository
ICashFlowEntryRepository = CashFlowEntryRepository
IScheduleHealthSnapshotRepository = ScheduleHealthSnapshotRepository
IProjectTemplateRepository = ProjectTemplateRepository
IIssueRepository = IssueRepository
IOBSNodeRepository = OBSNodeRepository
IRBSNodeRepository = RBSNodeRepository
IQualityPlanRepository = QualityPlanRepository
IInspectionRepository = InspectionRepository
INCRRepository = NCRRepository
IQualityChecklistRepository = QualityChecklistRepository
IQualityChecklistItemRepository = QualityChecklistItemRepository
IProjectDocumentRepository = ProjectDocumentRepository
