from __future__ import annotations

from pathlib import Path
from typing import Iterable

from fpdf import FPDF  # type: ignore[import-untyped]

from .schemas import AuroraJob


def _line(pdf: FPDF, text: str) -> None:
    full_width = pdf.w - pdf.l_margin - pdf.r_margin
    pdf.set_x(pdf.l_margin)
    pdf.set_font("Helvetica", size=10)
    pdf.multi_cell(full_width, 5, txt=_soft_wrap_tokens(text))


def _section(pdf: FPDF, title: str) -> None:
    pdf.ln(2)
    pdf.set_x(pdf.l_margin)
    pdf.set_font("Helvetica", style="B", size=12)
    full_width = pdf.w - pdf.l_margin - pdf.r_margin
    pdf.cell(full_width, 7, txt=title, ln=1)


def _soft_wrap_tokens(text: str, chunk: int = 40) -> str:
    parts = []
    for token in str(text).split(" "):
        if len(token) <= chunk:
            parts.append(token)
            continue
        segments = [token[i : i + chunk] for i in range(0, len(token), chunk)]
        parts.append(" ".join(segments))
    return " ".join(parts)


def _iter_output_rows(job: AuroraJob) -> Iterable[str]:
    if not job.result:
        return []
    for item in job.result.output_files:
        yield f"[{item.type}] {item.name} | {item.hash}"


def generate_forensic_report_pdf(job: AuroraJob, output_path: Path) -> Path:
    if not job.result:
        raise RuntimeError("Job has no result data")

    output_path.parent.mkdir(parents=True, exist_ok=True)
    pdf = FPDF(unit="mm", format="A4")
    pdf.set_auto_page_break(auto=True, margin=14)
    pdf.add_page()

    pdf.set_font("Helvetica", style="B", size=16)
    pdf.cell(0, 10, txt="Aurora Forensic Report", ln=1)
    pdf.set_font("Helvetica", size=9)
    pdf.cell(0, 5, txt="Autonomous Media Forensics Agent", ln=1)
    pdf.ln(3)

    _section(pdf, "Case Summary")
    _line(pdf, f"Job ID: {job.job_id}")
    _line(pdf, f"Mode: {job.mode}")
    _line(pdf, f"Media Type: {job.media_type}")
    _line(pdf, f"Status: {job.status}")
    _line(pdf, f"Created At: {job.created_at}")
    _line(pdf, f"Started At: {job.started_at or '-'}")
    _line(pdf, f"Completed At: {job.completed_at or '-'}")
    _line(pdf, f"Input File: {job.file_name}")
    _line(pdf, f"Input Hash: {job.input_hash}")
    _line(pdf, f"Digital Signature: {job.result.digital_signature or '-'}")

    _section(pdf, "Processing Log")
    if not job.result.processing_log:
        _line(pdf, "No processing steps were recorded.")
    for idx, step in enumerate(job.result.processing_log, start=1):
        _line(
            pdf,
            f"{idx}. {step.step} | agent={step.agent} | model={step.model} | time_ms={step.time_ms}",
        )

    _section(pdf, "Output Artifacts")
    rows = list(_iter_output_rows(job))
    if not rows:
        _line(pdf, "No output artifacts available.")
    for row in rows:
        _line(pdf, row)

    _section(pdf, "Metadata")
    for k, v in (job.result.metadata or {}).items():
        _line(pdf, f"{k}: {v}")

    pdf.output(str(output_path))
    return output_path
