#!/usr/bin/env python3
from __future__ import annotations

import os
from pathlib import Path
from typing import Any

from fastapi import FastAPI, HTTPException, Query
from fastapi.middleware.cors import CORSMiddleware

from case_rules import is_self_test_case
from case_schema import CaseCommentCreate, CaseCreate, CaseHayabusaLink, CaseUpdate
from case_storage import CaseStorage, ForensicsHostMismatchError

DB = Path(os.environ.get("AW_DLP_CASE_DB_PATH", "/opt/activitywatch/dlp-case-management/cases.db"))
APP = FastAPI(title="AWatch DLP Case Management")
APP.add_middleware(
    CORSMiddleware,
    allow_origins=["http://127.0.0.1:5600", "http://localhost:5600", "http://10.10.10.13:5600", "*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
STORE = CaseStorage(DB)


@APP.get("/health")
def health() -> dict[str, Any]:
    return {"ok": True, "db": str(DB)}


@APP.post("/api/0/dlp/cases")
def create_case(payload: CaseCreate) -> dict[str, Any]:
    if is_self_test_case(payload.incident_id, payload.title):
        raise HTTPException(status_code=422, detail="self_test cases are not allowed")
    return STORE.create_case(payload.model_dump(exclude_none=True), actor="api")


@APP.get("/api/0/dlp/cases")
def list_cases(
    status: str | None = Query(default=None),
    host: str | None = Query(default=None),
    limit: int = Query(default=200, ge=1, le=2000),
) -> list[dict[str, Any]]:
    return STORE.list_cases(status=status, host=host, limit=limit)


@APP.get("/api/0/dlp/cases/{case_id}")
def get_case(case_id: int) -> dict[str, Any]:
    try:
        case = STORE.get_case(case_id)
    except KeyError:
        raise HTTPException(status_code=404, detail="case not found")
    case["comments"] = STORE.list_comments(case_id, limit=200)
    case["audit"] = STORE.list_audit(case_id, limit=200)
    return case


@APP.patch("/api/0/dlp/cases/{case_id}")
def update_case(case_id: int, payload: CaseUpdate) -> dict[str, Any]:
    patch = payload.model_dump(exclude_none=True)
    if not patch:
        return STORE.get_case(case_id)
    try:
        return STORE.update_case(case_id, patch=patch, actor="api")
    except KeyError:
        raise HTTPException(status_code=404, detail="case not found")


@APP.post("/api/0/dlp/cases/{case_id}/comments")
def add_comment(case_id: int, payload: CaseCommentCreate) -> dict[str, Any]:
    try:
        STORE.get_case(case_id)
    except KeyError:
        raise HTTPException(status_code=404, detail="case not found")
    return STORE.add_comment(case_id=case_id, comment=payload.comment, author=payload.author)


@APP.get("/api/0/dlp/cases/{case_id}/comments")
def list_comments(case_id: int, limit: int = Query(default=200, ge=1, le=2000)) -> list[dict[str, Any]]:
    return STORE.list_comments(case_id=case_id, limit=limit)


@APP.post("/api/0/dlp/cases/{case_id}/forensics/hayabusa")
def link_hayabusa(case_id: int, payload: CaseHayabusaLink) -> dict[str, Any]:
    try:
        return STORE.link_hayabusa(case_id=case_id, payload=payload.model_dump(exclude_none=True), actor="api")
    except ForensicsHostMismatchError as exc:
        raise HTTPException(status_code=409, detail=str(exc))
    except KeyError:
        raise HTTPException(status_code=404, detail="case not found")
