"""Campaign progress tracker — compute completion stats across categories.

Aggregates mission status from the database to provide:
- Per-category progress (total, completed, available, locked)
- Overall completion percentage
- Security-tagged mission tracking
"""

import logging
from collections import defaultdict

from unfamiliar.campaign.types import CampaignProgress, CategoryProgress
from unfamiliar.constants import InvestigationCategory, MissionStatus
from unfamiliar.db import CampaignDB

logger = logging.getLogger(__name__)

# All 7 investigation categories, in canonical order (immutable)
ALL_CATEGORIES = tuple(InvestigationCategory)


def get_campaign_progress(
    db: CampaignDB,
    campaign_id: int,
) -> CampaignProgress:
    """Compute progress stats for a campaign across all categories.

    Ensures all 7 categories appear in results even if they have 0 missions.
    Percentages are 0-100 integers.

    Args:
        db: Open campaign database with all repositories.
        campaign_id: ID of the campaign to analyze.

    Returns:
        CampaignProgress with per-category and overall stats.

    Raises:
        ValueError: If campaign not found.
    """
    # Verify campaign exists
    campaign = db.campaign_repo.get(campaign_id)
    if campaign is None:
        raise ValueError(f"Campaign {campaign_id} not found")

    # Load all missions for this campaign
    missions = db.mission_repo.get_by_campaign(campaign_id)

    # Group missions by category
    by_category: dict[InvestigationCategory, list] = defaultdict(list)
    for mission in missions:
        by_category[mission.category].append(mission)

    # Compute per-category stats
    category_progress_list: list[CategoryProgress] = []
    total_missions = 0
    total_completed = 0
    total_available = 0
    total_locked = 0
    total_in_progress = 0
    security_total = 0
    security_completed = 0

    for category in ALL_CATEGORIES:
        category_missions = by_category.get(category, [])

        completed = sum(
            1 for m in category_missions if m.status == MissionStatus.COMPLETED
        )
        available = sum(
            1 for m in category_missions if m.status == MissionStatus.AVAILABLE
        )
        locked = sum(
            1 for m in category_missions if m.status == MissionStatus.LOCKED
        )
        in_progress = sum(
            1 for m in category_missions if m.status == MissionStatus.IN_PROGRESS
        )
        total = len(category_missions)

        # Compute percentage (0 if no missions)
        percent = int((completed / total) * 100) if total > 0 else 0

        category_progress_list.append(
            CategoryProgress(
                category=category,
                total=total,
                completed=completed,
                available=available,
                locked=locked,
                percent=percent,
            )
        )

        # Accumulate totals
        total_missions += total
        total_completed += completed
        total_available += available
        total_locked += locked
        total_in_progress += in_progress

        # Security-tagged missions
        security_in_category = sum(
            1 for m in category_missions if m.security_tag
        )
        security_completed_in_category = sum(
            1
            for m in category_missions
            if m.security_tag and m.status == MissionStatus.COMPLETED
        )
        security_total += security_in_category
        security_completed += security_completed_in_category

    # Compute overall percentage
    overall_percent = (
        int((total_completed / total_missions) * 100) if total_missions > 0 else 0
    )

    logger.debug(
        "Campaign %d progress: %d/%d missions (%d%%), %d security (%d completed)",
        campaign_id,
        total_completed,
        total_missions,
        overall_percent,
        security_total,
        security_completed,
    )

    return CampaignProgress(
        category_progress=category_progress_list,
        total_missions=total_missions,
        completed_missions=total_completed,
        available_missions=total_available,
        locked_missions=total_locked,
        in_progress_missions=total_in_progress,
        overall_percent=overall_percent,
        security_total=security_total,
        security_completed=security_completed,
    )
