"""
Strategy Application — DTOs.
"""

from dataclasses import dataclass, field
from datetime import date, datetime
from decimal import Decimal
from typing import Optional, List, Dict
from uuid import UUID


# ─── Vision DTOs ─────────────────────────────────

@dataclass
class VisionCreateDTO:
    tenant_id: UUID
    title: str
    description: str = ""
    time_horizon_start: Optional[date] = None
    time_horizon_end: Optional[date] = None
    owner_id: Optional[UUID] = None
    tags: Optional[list] = field(default_factory=list)
    metadata: Optional[dict] = field(default_factory=dict)


@dataclass
class VisionUpdateDTO:
    title: Optional[str] = None
    description: Optional[str] = None
    time_horizon_start: Optional[date] = None
    time_horizon_end: Optional[date] = None
    owner_id: Optional[UUID] = None
    tags: Optional[list] = None
    metadata: Optional[dict] = None


@dataclass
class VisionResponseDTO:
    id: UUID
    tenant_id: UUID
    title: str
    description: str
    time_horizon_start: Optional[date]
    time_horizon_end: Optional[date]
    status: str
    owner_id: Optional[UUID]
    tags: list
    metadata: dict
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


# ─── Strategic Theme DTOs ────────────────────────

@dataclass
class StrategicThemeCreateDTO:
    tenant_id: UUID
    vision_id: UUID
    name: str
    description: str = ""
    priority: str = "medium"
    owner_id: Optional[UUID] = None
    start_date: Optional[date] = None
    end_date: Optional[date] = None
    sort_order: int = 0
    tags: Optional[list] = field(default_factory=list)
    metadata: Optional[dict] = field(default_factory=dict)


@dataclass
class StrategicThemeUpdateDTO:
    name: Optional[str] = None
    description: Optional[str] = None
    priority: Optional[str] = None
    owner_id: Optional[UUID] = None
    start_date: Optional[date] = None
    end_date: Optional[date] = None
    sort_order: Optional[int] = None
    tags: Optional[list] = None
    metadata: Optional[dict] = None


@dataclass
class StrategicThemeResponseDTO:
    id: UUID
    tenant_id: UUID
    vision_id: UUID
    name: str
    description: str
    priority: str
    status: str
    owner_id: Optional[UUID]
    start_date: Optional[date]
    end_date: Optional[date]
    sort_order: int
    tags: list
    metadata: dict
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


# ─── Objective DTOs ──────────────────────────────

@dataclass
class ObjectiveCreateDTO:
    tenant_id: UUID
    title: str
    theme_id: Optional[UUID] = None
    parent_id: Optional[UUID] = None
    description: str = ""
    level: str = "enterprise"
    time_frame: str = "annual"
    period_start: Optional[date] = None
    period_end: Optional[date] = None
    weight: Decimal = Decimal("1.00")
    owner_id: Optional[UUID] = None
    tags: Optional[list] = field(default_factory=list)
    metadata: Optional[dict] = field(default_factory=dict)


@dataclass
class ObjectiveUpdateDTO:
    title: Optional[str] = None
    description: Optional[str] = None
    theme_id: Optional[UUID] = None
    parent_id: Optional[UUID] = None
    level: Optional[str] = None
    time_frame: Optional[str] = None
    period_start: Optional[date] = None
    period_end: Optional[date] = None
    weight: Optional[Decimal] = None
    owner_id: Optional[UUID] = None
    tags: Optional[list] = None
    metadata: Optional[dict] = None


@dataclass
class ObjectiveResponseDTO:
    id: UUID
    tenant_id: UUID
    title: str
    description: str
    theme_id: Optional[UUID]
    parent_id: Optional[UUID]
    level: str
    time_frame: str
    period_start: Optional[date]
    period_end: Optional[date]
    status: str
    weight: Decimal
    progress: Decimal
    owner_id: Optional[UUID]
    tags: list
    metadata: dict
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


# ─── Key Result DTOs ─────────────────────────────

@dataclass
class KeyResultCreateDTO:
    tenant_id: UUID
    objective_id: UUID
    title: str
    metric_type: str = "number"
    start_value: Decimal = Decimal("0")
    target_value: Decimal = Decimal("100")
    weight: Decimal = Decimal("1.00")
    owner_id: Optional[UUID] = None
    due_date: Optional[date] = None
    metadata: Optional[dict] = field(default_factory=dict)


@dataclass
class KeyResultUpdateDTO:
    title: Optional[str] = None
    metric_type: Optional[str] = None
    start_value: Optional[Decimal] = None
    target_value: Optional[Decimal] = None
    current_value: Optional[Decimal] = None
    weight: Optional[Decimal] = None
    owner_id: Optional[UUID] = None
    due_date: Optional[date] = None
    metadata: Optional[dict] = None


@dataclass
class KeyResultResponseDTO:
    id: UUID
    tenant_id: UUID
    objective_id: UUID
    title: str
    metric_type: str
    start_value: Decimal
    target_value: Decimal
    current_value: Decimal
    weight: Decimal
    status: str
    owner_id: Optional[UUID]
    due_date: Optional[date]
    progress: Decimal = Decimal("0")
    metadata: Optional[dict] = field(default_factory=dict)
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


# ─── CheckIn DTOs ────────────────────────────────

@dataclass
class CheckInCreateDTO:
    tenant_id: UUID
    key_result_id: UUID
    value: Decimal
    confidence: str = "medium"
    notes: str = ""
    checked_by: Optional[UUID] = None
    metadata: Optional[dict] = field(default_factory=dict)


@dataclass
class CheckInResponseDTO:
    id: UUID
    tenant_id: UUID
    key_result_id: UUID
    value: Decimal
    confidence: str
    notes: str
    checked_by: Optional[UUID]
    check_date: Optional[date]
    metadata: Optional[dict] = field(default_factory=dict)
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


# ─── OKR Analysis DTOs ───────────────────────────

@dataclass
class ObjectiveProgressDTO:
    objective_id: UUID
    weighted_progress: Decimal
    key_results_count: int
    completed_count: int
    at_risk_count: int


@dataclass
class CascadeProgressDTO:
    objective_id: UUID
    own_progress: Decimal
    children_progress: Decimal
    combined_progress: Decimal
    children_count: int


# ─── KPI Definition DTOs ─────────────────────────

@dataclass
class KPIDefinitionCreateDTO:
    tenant_id: UUID
    name: str
    code: str
    description: str = ""
    category: str = ""
    unit_of_measure: str = ""
    direction: str = "higher_is_better"
    frequency: str = "monthly"
    data_source: str = "manual"
    formula: Optional[str] = None
    threshold_red: Optional[float] = None
    threshold_yellow: Optional[float] = None
    threshold_green: Optional[float] = None
    owner_id: Optional[UUID] = None
    responsible_role: str = ""
    tags: Optional[list] = field(default_factory=list)
    metadata: Optional[dict] = field(default_factory=dict)


@dataclass
class KPIDefinitionUpdateDTO:
    name: Optional[str] = None
    code: Optional[str] = None
    description: Optional[str] = None
    category: Optional[str] = None
    unit_of_measure: Optional[str] = None
    direction: Optional[str] = None
    frequency: Optional[str] = None
    data_source: Optional[str] = None
    formula: Optional[str] = None
    threshold_red: Optional[float] = None
    threshold_yellow: Optional[float] = None
    threshold_green: Optional[float] = None
    owner_id: Optional[UUID] = None
    responsible_role: Optional[str] = None
    tags: Optional[list] = None
    metadata: Optional[dict] = None


@dataclass
class KPIDefinitionResponseDTO:
    id: UUID
    tenant_id: UUID
    name: str
    code: str
    description: str
    category: str
    unit_of_measure: str
    direction: str
    frequency: str
    data_source: str
    formula: Optional[str]
    threshold_red: Optional[float]
    threshold_yellow: Optional[float]
    threshold_green: Optional[float]
    owner_id: Optional[UUID]
    responsible_role: str
    status: str
    tags: Optional[list] = field(default_factory=list)
    metadata: Optional[dict] = field(default_factory=dict)
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


# ─── KPI Target DTOs ─────────────────────────────

@dataclass
class KPITargetCreateDTO:
    tenant_id: UUID
    kpi_id: UUID
    target_value: float
    period_start: Optional[date] = None
    period_end: Optional[date] = None
    stretch_value: Optional[float] = None
    notes: str = ""
    metadata: Optional[dict] = field(default_factory=dict)


@dataclass
class KPITargetUpdateDTO:
    target_value: Optional[float] = None
    stretch_value: Optional[float] = None
    period_start: Optional[date] = None
    period_end: Optional[date] = None
    notes: Optional[str] = None
    metadata: Optional[dict] = None


@dataclass
class KPITargetResponseDTO:
    id: UUID
    tenant_id: UUID
    kpi_id: UUID
    period_start: Optional[date]
    period_end: Optional[date]
    target_value: float
    stretch_value: Optional[float]
    notes: str
    metadata: Optional[dict] = field(default_factory=dict)
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


# ─── KPI Actual DTOs ─────────────────────────────

@dataclass
class KPIActualCreateDTO:
    tenant_id: UUID
    kpi_id: UUID
    actual_value: float
    period_start: Optional[date] = None
    period_end: Optional[date] = None
    notes: str = ""
    source: str = "manual"
    recorded_by: Optional[UUID] = None
    metadata: Optional[dict] = field(default_factory=dict)


@dataclass
class KPIActualUpdateDTO:
    actual_value: Optional[float] = None
    period_start: Optional[date] = None
    period_end: Optional[date] = None
    notes: Optional[str] = None
    source: Optional[str] = None
    metadata: Optional[dict] = None


@dataclass
class KPIActualResponseDTO:
    id: UUID
    tenant_id: UUID
    kpi_id: UUID
    period_start: Optional[date]
    period_end: Optional[date]
    actual_value: float
    notes: str
    source: str
    recorded_by: Optional[UUID]
    metadata: Optional[dict] = field(default_factory=dict)
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


# ─── KPI Assignment DTOs ─────────────────────────

@dataclass
class KPIAssignmentCreateDTO:
    tenant_id: UUID
    kpi_id: UUID
    level: str
    entity_id: Optional[UUID] = None
    weight: float = 1.0
    notes: str = ""
    metadata: Optional[dict] = field(default_factory=dict)


@dataclass
class KPIAssignmentUpdateDTO:
    level: Optional[str] = None
    entity_id: Optional[UUID] = None
    weight: Optional[float] = None
    notes: Optional[str] = None
    metadata: Optional[dict] = None


@dataclass
class KPIAssignmentResponseDTO:
    id: UUID
    tenant_id: UUID
    kpi_id: UUID
    level: str
    entity_id: Optional[UUID]
    weight: float
    status: str
    notes: str
    metadata: Optional[dict] = field(default_factory=dict)
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


# ─── KPI Score/Trend DTOs ────────────────────────

@dataclass
class KPIScoreDTO:
    kpi_id: UUID
    actual_value: float
    target_value: float
    achievement_rate: float
    rag_status: str


@dataclass
class KPITrendDTO:
    kpi_id: UUID
    slope: float
    direction: str  # improving / declining / stable
    forecast_next: Optional[float] = None
    points: Optional[list] = field(default_factory=list)


# ─── Strategy Map DTOs ───────────────────────────

@dataclass
class StrategyMapCreateDTO:
    tenant_id: UUID
    name: str
    description: str = ""
    metadata: Optional[dict] = field(default_factory=dict)


@dataclass
class StrategyMapUpdateDTO:
    name: Optional[str] = None
    description: Optional[str] = None
    metadata: Optional[dict] = None


@dataclass
class StrategyMapResponseDTO:
    id: UUID
    tenant_id: UUID
    name: str
    description: str
    version: int
    status: str
    metadata: Optional[dict] = field(default_factory=dict)
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


# ─── Strategy Map Perspective DTOs ───────────────

@dataclass
class PerspectiveCreateDTO:
    tenant_id: UUID
    map_id: UUID
    name: str
    description: str = ""
    sort_order: int = 0
    color: str = ""
    metadata: Optional[dict] = field(default_factory=dict)


@dataclass
class PerspectiveUpdateDTO:
    name: Optional[str] = None
    description: Optional[str] = None
    sort_order: Optional[int] = None
    color: Optional[str] = None
    metadata: Optional[dict] = None


@dataclass
class PerspectiveResponseDTO:
    id: UUID
    tenant_id: UUID
    map_id: UUID
    name: str
    description: str
    sort_order: int
    color: str
    metadata: Optional[dict] = field(default_factory=dict)
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


# ─── Strategy Map Objective DTOs ─────────────────

@dataclass
class MapObjectiveCreateDTO:
    tenant_id: UUID
    map_id: UUID
    perspective_id: UUID
    objective_id: UUID
    x_position: float = 0.0
    y_position: float = 0.0
    metadata: Optional[dict] = field(default_factory=dict)


@dataclass
class MapObjectiveUpdateDTO:
    perspective_id: Optional[UUID] = None
    x_position: Optional[float] = None
    y_position: Optional[float] = None
    metadata: Optional[dict] = None


@dataclass
class MapObjectiveResponseDTO:
    id: UUID
    tenant_id: UUID
    map_id: UUID
    perspective_id: UUID
    objective_id: UUID
    x_position: float
    y_position: float
    metadata: Optional[dict] = field(default_factory=dict)
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


# ─── Causal Link DTOs ────────────────────────────

@dataclass
class CausalLinkCreateDTO:
    tenant_id: UUID
    map_id: UUID
    from_objective_id: UUID
    to_objective_id: UUID
    strength: str = "medium"
    description: str = ""
    metadata: Optional[dict] = field(default_factory=dict)


@dataclass
class CausalLinkUpdateDTO:
    strength: Optional[str] = None
    description: Optional[str] = None
    metadata: Optional[dict] = None


@dataclass
class CausalLinkResponseDTO:
    id: UUID
    tenant_id: UUID
    map_id: UUID
    from_objective_id: UUID
    to_objective_id: UUID
    strength: str
    description: str
    metadata: Optional[dict] = field(default_factory=dict)
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


# ─── Scorecard DTOs ──────────────────────────────

@dataclass
class ScorecardCreateDTO:
    tenant_id: UUID
    name: str
    description: str = ""
    owner_id: Optional[UUID] = None
    period_start: Optional[date] = None
    period_end: Optional[date] = None
    metadata: Optional[dict] = field(default_factory=dict)


@dataclass
class ScorecardUpdateDTO:
    name: Optional[str] = None
    description: Optional[str] = None
    owner_id: Optional[UUID] = None
    period_start: Optional[date] = None
    period_end: Optional[date] = None
    metadata: Optional[dict] = None


@dataclass
class ScorecardResponseDTO:
    id: UUID
    tenant_id: UUID
    name: str
    description: str
    owner_id: Optional[UUID]
    period_start: Optional[date]
    period_end: Optional[date]
    status: str
    metadata: Optional[dict] = field(default_factory=dict)
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


# ─── Scorecard Perspective DTOs ──────────────────

@dataclass
class ScPerspectiveCreateDTO:
    tenant_id: UUID
    scorecard_id: UUID
    name: str
    weight: float = 1.0
    sort_order: int = 0
    metadata: Optional[dict] = field(default_factory=dict)


@dataclass
class ScPerspectiveUpdateDTO:
    name: Optional[str] = None
    weight: Optional[float] = None
    sort_order: Optional[int] = None
    metadata: Optional[dict] = None


@dataclass
class ScPerspectiveResponseDTO:
    id: UUID
    tenant_id: UUID
    scorecard_id: UUID
    name: str
    weight: float
    sort_order: int
    metadata: Optional[dict] = field(default_factory=dict)
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


# ─── Scorecard Measure DTOs ──────────────────────

@dataclass
class ScMeasureCreateDTO:
    tenant_id: UUID
    perspective_id: UUID
    kpi_assignment_id: Optional[UUID] = None
    weight: float = 1.0
    target_value: float = 0.0
    actual_value: float = 0.0
    metadata: Optional[dict] = field(default_factory=dict)


@dataclass
class ScMeasureUpdateDTO:
    kpi_assignment_id: Optional[UUID] = None
    weight: Optional[float] = None
    target_value: Optional[float] = None
    actual_value: Optional[float] = None
    metadata: Optional[dict] = None


@dataclass
class ScMeasureResponseDTO:
    id: UUID
    tenant_id: UUID
    perspective_id: UUID
    kpi_assignment_id: Optional[UUID]
    weight: float
    target_value: float
    actual_value: float
    score: float
    status: str
    metadata: Optional[dict] = field(default_factory=dict)
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


# ─── Scorecard Report DTOs ───────────────────────

@dataclass
class PerspectiveScoreDTO:
    perspective_id: UUID
    name: str
    weight: float
    score: float
    weighted_score: float
    measure_count: int


@dataclass
class ScorecardReportDTO:
    scorecard_id: UUID
    overall_score: float
    perspectives: List[PerspectiveScoreDTO] = field(default_factory=list)


# ═══════════════════════════════════════════════════
# Stage-Gate Governance DTOs
# ═══════════════════════════════════════════════════

# ─── GateProcess DTOs ─────────────────────────────

@dataclass
class GateProcessCreateDTO:
    name: str
    description: str = ""
    applicable_to: str = "project"
    tenant_id: Optional[UUID] = None

@dataclass
class GateProcessUpdateDTO:
    name: Optional[str] = None
    description: Optional[str] = None
    applicable_to: Optional[str] = None
    is_active: Optional[bool] = None

@dataclass
class GateProcessResponseDTO:
    id: UUID
    name: str
    description: str
    applicable_to: str
    is_active: bool
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


# ─── Gate DTOs ────────────────────────────────────

@dataclass
class GateCreateDTO:
    process_id: UUID
    name: str
    sequence: int = 0
    description: str = ""
    mandatory_deliverables: List[str] = field(default_factory=list)
    criteria: str = ""
    tenant_id: Optional[UUID] = None

@dataclass
class GateUpdateDTO:
    name: Optional[str] = None
    sequence: Optional[int] = None
    description: Optional[str] = None
    mandatory_deliverables: Optional[List[str]] = None
    criteria: Optional[str] = None

@dataclass
class GateResponseDTO:
    id: UUID
    process_id: UUID
    name: str
    sequence: int
    description: str
    mandatory_deliverables: List[str] = field(default_factory=list)
    criteria: str = ""
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


# ─── GateReview DTOs ─────────────────────────────

@dataclass
class GateReviewCreateDTO:
    gate_id: UUID
    entity_id: UUID
    entity_type: str = "project"
    review_date: Optional[date] = None
    notes: str = ""
    tenant_id: Optional[UUID] = None

@dataclass
class GateReviewUpdateDTO:
    status: Optional[str] = None
    review_date: Optional[date] = None
    notes: Optional[str] = None

@dataclass
class GateReviewResponseDTO:
    id: UUID
    gate_id: UUID
    entity_id: UUID
    entity_type: str
    status: str
    review_date: Optional[date] = None
    notes: str = ""
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


# ─── GateReviewer DTOs ───────────────────────────

@dataclass
class GateReviewerCreateDTO:
    review_id: UUID
    user_id: UUID
    role: str = ""
    tenant_id: Optional[UUID] = None

@dataclass
class GateReviewerUpdateDTO:
    decision: Optional[str] = None
    comments: Optional[str] = None

@dataclass
class GateReviewerResponseDTO:
    id: UUID
    review_id: UUID
    user_id: UUID
    role: str
    decision: str
    comments: str
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


# ─── GateDeliverable DTOs ────────────────────────

@dataclass
class GateDeliverableCreateDTO:
    review_id: UUID
    name: str
    document_id: Optional[UUID] = None
    tenant_id: Optional[UUID] = None

@dataclass
class GateDeliverableUpdateDTO:
    name: Optional[str] = None
    status: Optional[str] = None
    document_id: Optional[UUID] = None

@dataclass
class GateDeliverableResponseDTO:
    id: UUID
    review_id: UUID
    name: str
    status: str
    document_id: Optional[UUID] = None
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


# ─── Policy DTOs ─────────────────────────────────

@dataclass
class PolicyCreateDTO:
    tenant_id: UUID
    title: str
    code: str = ""
    category: str = ""
    content: str = ""
    effective_date: Optional[date] = None
    review_date: Optional[date] = None
    owner_id: Optional[UUID] = None
    approver_id: Optional[UUID] = None
    document_id: Optional[UUID] = None
    metadata: Optional[dict] = field(default_factory=dict)

@dataclass
class PolicyUpdateDTO:
    title: Optional[str] = None
    code: Optional[str] = None
    category: Optional[str] = None
    content: Optional[str] = None
    effective_date: Optional[date] = None
    review_date: Optional[date] = None
    owner_id: Optional[UUID] = None
    approver_id: Optional[UUID] = None
    document_id: Optional[UUID] = None
    metadata: Optional[dict] = None

@dataclass
class PolicyResponseDTO:
    id: UUID
    tenant_id: UUID
    title: str
    code: str
    category: str
    content: str
    version: int
    status: str
    effective_date: Optional[date] = None
    review_date: Optional[date] = None
    owner_id: Optional[UUID] = None
    approver_id: Optional[UUID] = None
    document_id: Optional[UUID] = None
    metadata: Optional[dict] = field(default_factory=dict)
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None


# ─── Policy Acknowledgment DTOs ──────────────────

@dataclass
class PolicyAckCreateDTO:
    tenant_id: UUID
    policy_id: UUID
    user_id: UUID
    acknowledged_at: Optional[datetime] = None
    metadata: Optional[dict] = field(default_factory=dict)

@dataclass
class PolicyAckResponseDTO:
    id: UUID
    tenant_id: UUID
    policy_id: UUID
    user_id: UUID
    acknowledged_at: Optional[datetime] = None
    metadata: Optional[dict] = field(default_factory=dict)
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None
