"""Phase 10: Attack Paths & Advanced Purple Team router."""

from typing import Optional
from uuid import UUID

from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session

from app.database import get_db
from app.dependencies.auth import get_current_user, require_any_role
from app.schemas.attack_path_schema import (
    AttackPathCreate, AttackPathUpdate, AttackPathOut,
    AttackPathStepCreate, AttackPathStepUpdate, AttackPathStepOut,
    ExecutionCreate, ExecutionOut,
    StepExecuteRequest, StepResultOut,
    TimelineEntryCreate, TimelineEntryOut,
)
from app.services import attack_path_service as svc

router = APIRouter(prefix="/attack-paths", tags=["attack-paths"])


# ── Attack Paths CRUD ─────────────────────────────────────────────────────────

@router.post("", response_model=AttackPathOut, status_code=201)
def create_attack_path(
    body: AttackPathCreate,
    db: Session = Depends(get_db),
    user=Depends(get_current_user),
):
    return svc.create_attack_path(db, body.model_dump(), user.id)


@router.get("", response_model=list[AttackPathOut])
def list_attack_paths(
    is_template: Optional[bool] = None,
    technique_id: Optional[UUID] = None,
    is_active: Optional[bool] = True,
    db: Session = Depends(get_db),
    user=Depends(get_current_user),
):
    paths = svc.list_attack_paths(db, is_template=is_template,
                                   technique_id=technique_id, is_active=is_active)
    # Inject step_count
    result = []
    for p in paths:
        d = AttackPathOut.model_validate(p)
        d.step_count = len(p.steps)
        result.append(d)
    return result


@router.get("/{path_id}", response_model=AttackPathOut)
def get_attack_path(
    path_id: UUID,
    db: Session = Depends(get_db),
    user=Depends(get_current_user),
):
    p = svc.get_attack_path(db, path_id)
    d = AttackPathOut.model_validate(p)
    d.step_count = len(p.steps)
    return d


@router.patch("/{path_id}", response_model=AttackPathOut)
def update_attack_path(
    path_id: UUID,
    body: AttackPathUpdate,
    db: Session = Depends(get_db),
    user=Depends(get_current_user),
):
    return svc.update_attack_path(db, path_id, body.model_dump(exclude_unset=True), user.id)


@router.delete("/{path_id}", status_code=204)
def delete_attack_path(
    path_id: UUID,
    db: Session = Depends(get_db),
    user=Depends(require_any_role("admin", "red_lead", "blue_lead")),
):
    svc.delete_attack_path(db, path_id, user.id)


# ── Steps ─────────────────────────────────────────────────────────────────────

@router.get("/{path_id}/steps", response_model=list[AttackPathStepOut])
def list_steps(
    path_id: UUID,
    db: Session = Depends(get_db),
    user=Depends(get_current_user),
):
    path = svc.get_attack_path(db, path_id)
    return path.steps


@router.post("/{path_id}/steps", response_model=AttackPathStepOut, status_code=201)
def add_step(
    path_id: UUID,
    body: AttackPathStepCreate,
    db: Session = Depends(get_db),
    user=Depends(get_current_user),
):
    return svc.add_step(db, path_id, body.model_dump(), user.id)


@router.patch("/{path_id}/steps/{step_id}", response_model=AttackPathStepOut)
def update_step(
    path_id: UUID,
    step_id: UUID,
    body: AttackPathStepUpdate,
    db: Session = Depends(get_db),
    user=Depends(get_current_user),
):
    return svc.update_step(db, step_id, body.model_dump(exclude_unset=True), user.id)


@router.delete("/{path_id}/steps/{step_id}", status_code=204)
def delete_step(
    path_id: UUID,
    step_id: UUID,
    db: Session = Depends(get_db),
    user=Depends(get_current_user),
):
    svc.delete_step(db, step_id, user.id)


@router.post("/{path_id}/steps/reorder", response_model=list[AttackPathStepOut])
def reorder_steps(
    path_id: UUID,
    step_ids: list[UUID],
    db: Session = Depends(get_db),
    user=Depends(get_current_user),
):
    """Pass an ordered list of step UUIDs to reorder the steps."""
    return svc.reorder_steps(db, path_id, step_ids, user.id)


# ── Executions ────────────────────────────────────────────────────────────────

@router.post("/{path_id}/executions", response_model=ExecutionOut, status_code=201)
def create_execution(
    path_id: UUID,
    body: ExecutionCreate,
    db: Session = Depends(get_db),
    user=Depends(get_current_user),
):
    return svc.create_execution(db, path_id, body.model_dump(), user.id)


@router.get("/{path_id}/executions", response_model=list[ExecutionOut])
def list_executions(
    path_id: UUID,
    db: Session = Depends(get_db),
    user=Depends(get_current_user),
):
    return svc.list_executions(db, path_id)


@router.get("/executions/{execution_id}", response_model=ExecutionOut)
def get_execution(
    execution_id: UUID,
    db: Session = Depends(get_db),
    user=Depends(get_current_user),
):
    return svc.get_execution(db, execution_id)


@router.post("/executions/{execution_id}/start", response_model=ExecutionOut)
def start_execution(
    execution_id: UUID,
    db: Session = Depends(get_db),
    user=Depends(get_current_user),
):
    return svc.start_execution(db, execution_id, user.id)


@router.post("/executions/{execution_id}/steps/{step_id}", response_model=StepResultOut)
def execute_step(
    execution_id: UUID,
    step_id: UUID,
    body: StepExecuteRequest,
    db: Session = Depends(get_db),
    user=Depends(get_current_user),
):
    """Record the result of one step (detected / not_detected / skipped)."""
    return svc.execute_step(db, execution_id, step_id, body.model_dump(), user.id)


@router.get("/executions/{execution_id}/steps", response_model=list[StepResultOut])
def list_step_results(
    execution_id: UUID,
    db: Session = Depends(get_db),
    user=Depends(get_current_user),
):
    ex = svc.get_execution(db, execution_id)
    return ex.step_results


@router.post("/executions/{execution_id}/complete", response_model=ExecutionOut)
def complete_execution(
    execution_id: UUID,
    db: Session = Depends(get_db),
    user=Depends(get_current_user),
):
    """Mark execution as complete and compute kill-chain metrics."""
    return svc.complete_execution(db, execution_id, user.id)


@router.post("/executions/{execution_id}/abort", response_model=ExecutionOut)
def abort_execution(
    execution_id: UUID,
    db: Session = Depends(get_db),
    user=Depends(require_any_role("admin", "red_lead", "blue_lead")),
):
    return svc.abort_execution(db, execution_id, user.id)


# ── Timeline ──────────────────────────────────────────────────────────────────

@router.post("/executions/{execution_id}/timeline",
             response_model=TimelineEntryOut, status_code=201)
def add_timeline_entry(
    execution_id: UUID,
    body: TimelineEntryCreate,
    db: Session = Depends(get_db),
    user=Depends(get_current_user),
):
    return svc.add_timeline_entry(db, execution_id, body.model_dump(), user.id)


@router.get("/executions/{execution_id}/timeline", response_model=list[TimelineEntryOut])
def get_timeline(
    execution_id: UUID,
    db: Session = Depends(get_db),
    user=Depends(get_current_user),
):
    return svc.get_timeline(db, execution_id)


# ── Kill-Chain Metrics ────────────────────────────────────────────────────────

@router.get("/executions/{execution_id}/metrics")
def get_metrics(
    execution_id: UUID,
    db: Session = Depends(get_db),
    user=Depends(get_current_user),
):
    """Return full kill-chain metrics for a completed (or partial) execution."""
    return svc.get_kill_chain_metrics(db, execution_id)
