"""Mission-related domain models.

Mission represents an atomic investigation task within a campaign.
MissionChain groups related missions into learning paths.
Various link models represent many-to-many relationships.
"""

from __future__ import annotations

from datetime import (
    datetime,  # noqa: TCH003 — Pydantic resolves datetime at runtime for field schema
)

from pydantic import BaseModel, Field

from unfamiliar.constants import (  # noqa: TCH001
    CompletionMethod,
    InvestigationCategory,
    MissionDifficulty,
    MissionStatus,
)


class Mission(BaseModel):
    """An atomic investigation task within a campaign.

    Missions guide users through understanding specific aspects of
    the codebase. Each mission has a difficulty tier, category,
    and completion criteria.

    Attributes:
        id: Database primary key. None until persisted.
        campaign_id: Foreign key to the parent campaign.
        title: Themed mission title (may include narrative elements).
        title_plain: Plain-text version of title for search/sorting.
        description: Detailed instructions for completing the mission.
        category: Which investigation category this mission belongs to.
        difficulty: Difficulty tier determining time estimate.
        time_estimate_minutes: Estimated time to complete (derived from difficulty).
        completion_condition: Clear criteria for mission completion.
        security_tag: Whether this mission relates to security concerns.
        standard_tag: Optional reference to a coding standard being demonstrated.
        status: Current availability and completion state.
        completion_method: How the mission was completed, if applicable.
        narrative_intro: Optional themed introduction text.
        narrative_outro: Optional themed completion text.
        created_at: Timestamp when mission was created.
        updated_at: Timestamp when mission was last modified.
    """

    id: int | None = None
    campaign_id: int
    title: str
    title_plain: str
    description: str
    category: InvestigationCategory
    difficulty: MissionDifficulty
    time_estimate_minutes: int
    completion_condition: str
    security_tag: bool = False
    standard_tag: str | None = None
    status: MissionStatus = Field(default=MissionStatus.LOCKED)
    completion_method: CompletionMethod | None = None
    narrative_intro: str = ""
    narrative_outro: str = ""
    created_at: datetime | None = None
    updated_at: datetime | None = None


class MissionFileRef(BaseModel):
    """Links a mission to specific files/lines for investigation.

    File references help users locate the relevant code for a mission.
    Can reference entire files or specific line ranges.

    Attributes:
        id: Database primary key. None until persisted.
        mission_id: Foreign key to the parent mission.
        file_path: Path to the file, relative to repo root.
        line_start: Starting line number, or None for whole-file reference.
        line_end: Ending line number, or None for whole-file reference.
        description: Optional context about why this file is relevant.
        file_hash: SHA-256 hash of file contents at mission creation time.
    """

    id: int | None = None
    mission_id: int
    file_path: str
    line_start: int | None = None
    line_end: int | None = None
    description: str = ""
    file_hash: str = ""


class MissionChain(BaseModel):
    """A suggested learning path through related missions.

    Chains group missions that should be completed in sequence,
    providing a guided learning experience within a category.

    Attributes:
        id: Database primary key. None until persisted.
        campaign_id: Foreign key to the parent campaign.
        name: Themed chain name (may include narrative elements).
        name_plain: Plain-text version of name for search/sorting.
        description: Explanation of why these missions are grouped.
        category: Primary investigation category for the chain.
        sort_order: Display ordering within a campaign.
        created_at: Timestamp when chain was created.
        updated_at: Timestamp when chain was last modified.
    """

    id: int | None = None
    campaign_id: int
    name: str
    name_plain: str
    description: str
    category: InvestigationCategory
    sort_order: int = 0
    created_at: datetime | None = None
    updated_at: datetime | None = None


class ModuleMissionLink(BaseModel):
    """Links a mission to the modules it investigates.

    Many-to-many relationship between Mission and Module.
    Exactly one link per mission should have is_primary=True.

    Attributes:
        module_id: Foreign key to the module.
        mission_id: Foreign key to the mission.
        is_primary: Whether this is the primary module for the mission.
    """

    module_id: int
    mission_id: int
    is_primary: bool = False


class ChainMissionLink(BaseModel):
    """Links a chain to its constituent missions in order.

    Many-to-many relationship between MissionChain and Mission.
    Position determines the order within the chain.

    Attributes:
        chain_id: Foreign key to the chain.
        mission_id: Foreign key to the mission.
        position: Order position within the chain (0-indexed).
    """

    chain_id: int
    mission_id: int
    position: int
