"""
PPM Application — Data Transfer Objects

DTO‌های ماژول مدیریت پرتفولیو و برنامه.
"""

from dataclasses import dataclass, field
from datetime import date, datetime
from decimal import Decimal
from typing import Optional, List, Dict
from uuid import UUID


# ─── Portfolio DTOs ──────────────────────────────────────────

@dataclass
class PortfolioCreateDTO:
    code: str
    name: str
    description: str = ""
    parent_id: Optional[UUID] = None
    risk_tolerance: str = "medium"
    total_budget: Decimal = Decimal("0")
    start_date: Optional[date] = None
    end_date: Optional[date] = None
    review_cycle: str = "quarterly"
    owner_id: Optional[UUID] = None
    company_id: Optional[UUID] = None
    org_unit_id: Optional[UUID] = None
    tags: Optional[list] = None
    metadata: Optional[dict] = None


@dataclass
class PortfolioResponseDTO:
    id: UUID
    code: str
    name: str
    description: str
    parent_id: Optional[UUID]
    status: str
    strategic_alignment_score: Decimal
    risk_tolerance: str
    total_budget: Decimal
    allocated_budget: Decimal
    start_date: Optional[date]
    end_date: Optional[date]
    review_cycle: str
    owner_id: Optional[UUID]
    company_id: Optional[UUID]
    org_unit_id: Optional[UUID]
    tags: list
    metadata: dict


# ─── Program DTOs ────────────────────────────────────────────

@dataclass
class ProgramCreateDTO:
    code: str
    name: str
    description: str = ""
    portfolio_id: Optional[UUID] = None
    manager_id: Optional[UUID] = None
    objectives: str = ""
    expected_benefits: str = ""
    budget: Decimal = Decimal("0")
    start_date: Optional[date] = None
    end_date: Optional[date] = None
    risk_level: str = "medium"
    tags: Optional[list] = None
    metadata: Optional[dict] = None


@dataclass
class ProgramResponseDTO:
    id: UUID
    code: str
    name: str
    description: str
    portfolio_id: Optional[UUID]
    manager_id: Optional[UUID]
    status: str
    objectives: str
    expected_benefits: str
    budget: Decimal
    start_date: Optional[date]
    end_date: Optional[date]
    risk_level: str
    progress: Decimal
    tags: list
    metadata: dict


# ─── ProgramProject DTOs ────────────────────────────────────

@dataclass
class ProgramProjectCreateDTO:
    program_id: UUID
    project_id: UUID
    role: str = "core"
    priority: int = 0
    notes: str = ""


@dataclass
class ProgramProjectResponseDTO:
    id: UUID
    program_id: UUID
    project_id: UUID
    role: str
    priority: int
    notes: str


# ─── BusinessCase DTOs ──────────────────────────────────────

@dataclass
class BusinessCaseCreateDTO:
    title: str
    description: str = ""
    program_id: Optional[UUID] = None
    project_id: Optional[UUID] = None
    sponsor_id: Optional[UUID] = None
    prepared_by_id: Optional[UUID] = None
    strategic_fit_score: Decimal = Decimal("0")
    total_investment: Decimal = Decimal("0")
    expected_revenue: Decimal = Decimal("0")
    expected_savings: Decimal = Decimal("0")
    payback_period_months: int = 0
    assumptions: str = ""
    constraints: str = ""
    risks_summary: str = ""
    metadata: Optional[dict] = None


@dataclass
class BusinessCaseResponseDTO:
    id: UUID
    title: str
    description: str
    program_id: Optional[UUID]
    project_id: Optional[UUID]
    status: str
    sponsor_id: Optional[UUID]
    prepared_by_id: Optional[UUID]
    strategic_fit_score: Decimal
    total_investment: Decimal
    expected_revenue: Decimal
    expected_savings: Decimal
    payback_period_months: int
    assumptions: str
    constraints: str
    risks_summary: str
    metadata: dict


# ─── CashFlow DTOs ──────────────────────────────────────────

@dataclass
class CashFlowCreateDTO:
    business_case_id: UUID
    year: int
    investment: Decimal = Decimal("0")
    revenue: Decimal = Decimal("0")
    savings: Decimal = Decimal("0")
    operational_cost: Decimal = Decimal("0")


@dataclass
class CashFlowResponseDTO:
    id: UUID
    business_case_id: UUID
    year: int
    investment: Decimal
    revenue: Decimal
    savings: Decimal
    operational_cost: Decimal
    net_cash_flow: Decimal


# ─── Financial Evaluation DTOs ──────────────────────────────

@dataclass
class FinancialEvaluationDTO:
    npv: Decimal = Decimal("0")
    irr: Decimal = Decimal("0")
    payback_period: Decimal = Decimal("0")
    roi: Decimal = Decimal("0")
    benefit_cost_ratio: Decimal = Decimal("0")


# ─── ScoringModel DTOs ──────────────────────────────────────

@dataclass
class ScoringModelCreateDTO:
    name: str
    description: str = ""
    portfolio_id: Optional[UUID] = None
    is_active: bool = True
    metadata: Optional[dict] = None


@dataclass
class ScoringModelResponseDTO:
    id: UUID
    name: str
    description: str
    portfolio_id: Optional[UUID]
    is_active: bool
    metadata: dict
    criteria_count: int = 0


# ─── ScoringCriterion DTOs ──────────────────────────────────

@dataclass
class ScoringCriterionCreateDTO:
    scoring_model_id: UUID
    name: str
    description: str = ""
    weight: Decimal = Decimal("0")
    scale_min: int = 1
    scale_max: int = 10
    category: str = "strategic"
    order: int = 0


@dataclass
class ScoringCriterionResponseDTO:
    id: UUID
    scoring_model_id: UUID
    name: str
    description: str
    weight: Decimal
    scale_min: int
    scale_max: int
    category: str
    order: int


# ─── ProjectScore DTOs ──────────────────────────────────────

@dataclass
class ProjectScoreCreateDTO:
    scoring_model_id: UUID
    project_id: UUID
    criterion_id: UUID
    score: Decimal
    justification: str = ""
    scored_by_id: Optional[UUID] = None


@dataclass
class ProjectScoreResponseDTO:
    id: UUID
    scoring_model_id: UUID
    project_id: UUID
    criterion_id: UUID
    score: Decimal
    justification: str
    scored_by_id: Optional[UUID]
    scored_at: Optional[datetime]


# ─── Ranking DTOs ────────────────────────────────────────────

@dataclass
class ProjectRankingDTO:
    project_id: UUID
    weighted_score: Decimal
    rank: int
    scores_by_category: Dict[str, Decimal] = field(default_factory=dict)


# ─── BenefitPlan DTOs ───────────────────────────────────────

@dataclass
class BenefitPlanCreateDTO:
    name: str
    description: str = ""
    program_id: Optional[UUID] = None
    portfolio_id: Optional[UUID] = None
    is_active: bool = True
    metadata: Optional[dict] = None


@dataclass
class BenefitPlanResponseDTO:
    id: UUID
    name: str
    description: str
    program_id: Optional[UUID]
    portfolio_id: Optional[UUID]
    is_active: bool
    metadata: dict
    benefits_count: int = 0


# ─── Benefit DTOs ────────────────────────────────────────────

@dataclass
class BenefitCreateDTO:
    benefit_plan_id: UUID
    title: str
    description: str = ""
    benefit_type: str = "financial"
    category: str = ""
    target_value: Decimal = Decimal("0")
    actual_value: Decimal = Decimal("0")
    measurement_method: str = ""
    frequency: str = "quarterly"
    owner_id: Optional[UUID] = None
    target_date: Optional[date] = None
    metadata: Optional[dict] = None


@dataclass
class BenefitResponseDTO:
    id: UUID
    benefit_plan_id: UUID
    title: str
    description: str
    benefit_type: str
    category: str
    target_value: Decimal
    actual_value: Decimal
    measurement_method: str
    frequency: str
    owner_id: Optional[UUID]
    status: str
    target_date: Optional[date]
    realization_percentage: Decimal
    metadata: dict


# ─── BenefitMeasurement DTOs ────────────────────────────────

@dataclass
class BenefitMeasurementCreateDTO:
    benefit_id: UUID
    measurement_date: Optional[date] = None
    value: Decimal = Decimal("0")
    notes: str = ""
    measured_by_id: Optional[UUID] = None


@dataclass
class BenefitMeasurementResponseDTO:
    id: UUID
    benefit_id: UUID
    measurement_date: Optional[date]
    value: Decimal
    notes: str
    measured_by_id: Optional[UUID]


# ─── CapacityPlan DTOs ──────────────────────────────────────

@dataclass
class CapacityPlanCreateDTO:
    name: str
    description: str = ""
    portfolio_id: Optional[UUID] = None
    period_start: Optional[date] = None
    period_end: Optional[date] = None
    is_active: bool = True
    metadata: Optional[dict] = None


@dataclass
class CapacityPlanResponseDTO:
    id: UUID
    name: str
    description: str
    portfolio_id: Optional[UUID]
    period_start: Optional[date]
    period_end: Optional[date]
    is_active: bool
    metadata: dict
    demands_count: int = 0
    supplies_count: int = 0


# ─── ResourceDemand DTOs ────────────────────────────────────

@dataclass
class ResourceDemandCreateDTO:
    capacity_plan_id: UUID
    resource_type: str
    project_id: Optional[UUID] = None
    demand_hours: Decimal = Decimal("0")
    period: str = ""
    notes: str = ""


@dataclass
class ResourceDemandResponseDTO:
    id: UUID
    capacity_plan_id: UUID
    resource_type: str
    project_id: Optional[UUID]
    demand_hours: Decimal
    period: str
    notes: str


# ─── ResourceSupply DTOs ────────────────────────────────────

@dataclass
class ResourceSupplyCreateDTO:
    capacity_plan_id: UUID
    resource_type: str
    available_hours: Decimal = Decimal("0")
    period: str = ""
    notes: str = ""


@dataclass
class ResourceSupplyResponseDTO:
    id: UUID
    capacity_plan_id: UUID
    resource_type: str
    available_hours: Decimal
    period: str
    notes: str


# ─── Capacity Analysis DTOs ─────────────────────────────────

@dataclass
class CapacityGapDTO:
    resource_type: str
    period: str
    demand_hours: Decimal
    supply_hours: Decimal
    gap_hours: Decimal
    utilization_pct: Decimal


@dataclass
class BottleneckDTO:
    resource_type: str
    period: str
    gap_hours: Decimal
    utilization_pct: Decimal
    affected_projects: List[UUID] = field(default_factory=list)


# ─── Cross-Project Dependency DTOs ─────────────────────────

@dataclass
class CrossProjectDependencyCreateDTO:
    predecessor_project_id: Optional[UUID] = None
    successor_project_id: Optional[UUID] = None
    predecessor_milestone_id: Optional[UUID] = None
    successor_milestone_id: Optional[UUID] = None
    dependency_type: str = "FS"
    lag_days: int = 0
    impact_description: str = ""
    metadata: Optional[dict] = None


@dataclass
class CrossProjectDependencyResponseDTO:
    id: UUID
    predecessor_project_id: Optional[UUID]
    successor_project_id: Optional[UUID]
    predecessor_milestone_id: Optional[UUID]
    successor_milestone_id: Optional[UUID]
    dependency_type: str
    lag_days: int
    status: str
    impact_description: str
    metadata: dict
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


@dataclass
class CircularDependencyDTO:
    cycle: List[str] = field(default_factory=list)
    description: str = ""


@dataclass
class CriticalChainLinkDTO:
    project_id: str
    predecessor_id: Optional[str] = None
    dependency_type: str = "FS"
    lag_days: int = 0
    total_slack: int = 0


@dataclass
class ImpactResultDTO:
    delayed_project_id: str
    delay_days: int
    affected_projects: List[Dict] = field(default_factory=list)
    total_cascade_days: int = 0
