"""
PPM Application — PM Event Handlers

هندلرهای رویدادهای ماژول PM (مدیریت پروژه) برای واکنش در ماژول PPM.
از contracts/v1/events.py ماژول PM استفاده می‌شود.
"""

import logging

from modules.pm.contracts.v1.events import (
    ProjectCreated,
    ProjectStatusChanged,
    ProjectCompleted,
    MilestoneReached,
)
from apps.core.event_bus.events import event_bus

logger = logging.getLogger(__name__)


# ─── Project Created Handler ────────────────────────────────

def handle_project_created(event: ProjectCreated) -> None:
    """واکنش به ایجاد پروژه جدید — اتصال خودکار به برنامه."""
    logger.info(
        "PPM: Received project.created — project_id=%s, code=%s",
        event.project_id, event.code,
    )
    if event.project_id and event.tenant_id:
        try:
            from ...infrastructure.persistence.models import ProgramProjectModel

            # Check if project is already linked to any program
            existing = ProgramProjectModel.objects.filter(
                tenant_id=event.tenant_id,
                project_id=event.project_id,
            ).exists()
            if existing:
                logger.info(
                    "PPM: Project %s already linked to a program.", event.project_id,
                )
            else:
                logger.info(
                    "PPM: Project %s not yet linked — available for program assignment.",
                    event.project_id,
                )
        except Exception as exc:
            logger.warning("PPM: Failed to check project linkage: %s", exc)


# ─── Project Status Changed Handler ─────────────────────────

def handle_project_status_changed(event: ProjectStatusChanged) -> None:
    """واکنش به تغییر وضعیت — بازمحاسبه پیشرفت برنامه."""
    logger.info(
        "PPM: Received project.status_changed — project_id=%s, %s → %s",
        event.project_id, event.old_status, event.new_status,
    )
    if event.project_id and event.tenant_id:
        try:
            from ...infrastructure.persistence.models import (
                ProgramProjectModel, ProgramModel,
            )
            # Find programs containing this project
            program_links = ProgramProjectModel.objects.filter(
                tenant_id=event.tenant_id,
                project_id=event.project_id,
            ).select_related("program")
            for link in program_links:
                program = link.program
                logger.info(
                    "PPM: Project %s status change affects program '%s' (%s).",
                    event.project_id, program.name, program.id,
                )
                # Recalculate program progress based on all linked projects
                project_count = ProgramProjectModel.objects.filter(
                    program=program, tenant_id=event.tenant_id,
                ).count()
                logger.info(
                    "PPM: Program '%s' has %d linked projects — progress recalculation triggered.",
                    program.name, project_count,
                )
        except Exception as exc:
            logger.warning("PPM: Failed to recalculate program progress: %s", exc)


# ─── Project Completed Handler ───────────────────────────────

def handle_project_completed(event: ProjectCompleted) -> None:
    """واکنش به اتمام پروژه — resolve وابستگی‌ها."""
    logger.info(
        "PPM: Received project.completed — project_id=%s",
        event.project_id,
    )
    if event.project_id:
        try:
            from ...infrastructure.persistence.models import CrossProjectDependencyModel

            deps = CrossProjectDependencyModel.objects.filter(
                predecessor_project_id=event.project_id,
                status="active",
            )
            resolved_count = deps.update(status="resolved")
            if resolved_count:
                logger.info(
                    "PPM: Auto-resolved %d dependencies for completed project %s",
                    resolved_count, event.project_id,
                )
        except Exception as exc:
            logger.warning("PPM: Failed to auto-resolve dependencies: %s", exc)


# ─── Milestone Reached Handler ───────────────────────────────

def handle_milestone_reached(event: MilestoneReached) -> None:
    """واکنش به رسیدن به مایلستون — resolve وابستگی مایلستون."""
    logger.info(
        "PPM: Received milestone.reached — project_id=%s, task_id=%s",
        event.project_id, event.task_id,
    )
    if event.task_id:
        try:
            from ...infrastructure.persistence.models import CrossProjectDependencyModel

            deps = CrossProjectDependencyModel.objects.filter(
                predecessor_milestone_id=event.task_id,
                status="active",
            )
            resolved_count = deps.update(status="resolved")
            if resolved_count:
                logger.info(
                    "PPM: Auto-resolved %d milestone dependencies for %s",
                    resolved_count, event.task_id,
                )
        except Exception as exc:
            logger.warning("PPM: Failed to auto-resolve milestone dependencies: %s", exc)


# ─── Register Handlers ──────────────────────────────────────

def register_pm_event_handlers() -> None:
    """ثبت هندلرهای رویدادهای PM در Event Bus."""
    event_bus.subscribe("pm.project.created", handle_project_created)
    event_bus.subscribe("pm.project.status_changed", handle_project_status_changed)
    event_bus.subscribe("pm.project.completed", handle_project_completed)
    event_bus.subscribe("pm.milestone.reached", handle_milestone_reached)
    logger.info("PPM: Registered PM event handlers")
