"""complyform verify command -- attestation verification."""

from __future__ import annotations

import base64
import hashlib
import json
import sys
from typing import Annotated, Any

import typer

from complyform.cli.exit_codes import EXIT_COMPLIANCE_FAILURE, EXIT_SUCCESS
from complyform.cli.main import AppContext, app
from complyform.core.errors import AttestationVerificationFailedError

_BF = "Brownfield (Existing Infrastructure)"


@app.command(name="verify", rich_help_panel=_BF)
def verify_cmd(
    ctx: typer.Context,
    attestation_file: Annotated[
        str,
        typer.Argument(help="Path to attestation JSON file"),
    ],
    assessment: Annotated[
        str | None,
        typer.Option(
            "--assessment", help="Verify attestation matches this assessment file"
        ),
    ] = None,
    format: Annotated[
        str,
        typer.Option("--format", help="Output format: json, terminal"),
    ] = "terminal",
) -> None:
    """Verify an in-toto attestation."""
    app_ctx: AppContext = ctx.obj

    try:
        result = _verify(attestation_file, assessment)
    except AttestationVerificationFailedError:
        raise
    except Exception as exc:
        raise AttestationVerificationFailedError(str(exc)) from exc

    if format == "json":
        envelope: dict[str, Any] = {
            "schema_version": 1,
            "command": "verify",
            "result": result,
        }
        sys.stdout.write(json.dumps(envelope, indent=2) + "\n")
    else:
        from rich.console import Console
        from rich.panel import Panel

        console = app_ctx.console
        if isinstance(console, Console) and not app_ctx.quiet:
            status = result["status"]
            style = "green" if status in {"PASS", "PARTIAL"} else "red"
            body = (
                f"Status: {status}\nSigned: {result['signed']}"
                f"\nHash Match: {result['hash_match']}"
            )
            if result.get("reason"):
                body += f"\nReason: {result['reason']}"
            console.print(Panel(body, title="Attestation Verification", style=style))

    exit_code = (
        EXIT_SUCCESS
        if result["status"] in {"PASS", "PARTIAL"}
        else EXIT_COMPLIANCE_FAILURE
    )
    raise typer.Exit(code=exit_code)


def _verify(
    attestation_path: str,
    assessment_path: str | None,
) -> dict[str, Any]:
    from pathlib import Path

    from complyform.core.attestation.signer import (
        _dsse_pae,
        load_public_key,
        verify_signature,
    )

    att_path = Path(attestation_path)
    if not att_path.exists():
        raise AttestationVerificationFailedError(
            f"Attestation file not found: {attestation_path}"
        )

    raw = json.loads(att_path.read_text(encoding="utf-8"))

    if raw.get("payloadType") != "application/vnd.in-toto+json":
        raise AttestationVerificationFailedError("Not a valid DSSE envelope")

    payload_b64 = raw.get("payload", "")
    try:
        payload_bytes = base64.b64decode(payload_b64)
        statement = json.loads(payload_bytes)
    except Exception as exc:
        raise AttestationVerificationFailedError(
            f"Cannot decode payload: {exc}"
        ) from exc

    if statement.get("_type") != "https://in-toto.io/Statement/v1":
        raise AttestationVerificationFailedError("Not an in-toto Statement v1")

    signatures = raw.get("signatures", [])
    signed = bool(signatures)
    hash_match: bool | None = None
    signature_valid: bool | None = None
    reason = ""

    # Check hash match if assessment provided
    if assessment_path is not None:
        assess_path = Path(assessment_path)
        if not assess_path.exists():
            raise AttestationVerificationFailedError(
                f"Assessment file not found: {assessment_path}"
            )

        assess_content = assess_path.read_bytes()
        actual_hash = hashlib.sha256(assess_content).hexdigest()

        subjects = statement.get("subject", [])
        if subjects:
            expected_hash = subjects[0].get("digest", {}).get("sha256", "")
            hash_match = actual_hash == expected_hash
            if not hash_match:
                return {
                    "status": "FAIL",
                    "signed": signed,
                    "signature_valid": None,
                    "hash_match": False,
                    "key_id": None,
                    "attestation_timestamp": statement.get("predicate", {}).get(
                        "timestamp"
                    ),
                    "reason": "Assessment hash mismatch",
                }

    # Verify signature if present
    if signed:
        try:
            public_key = load_public_key()
            pae = _dsse_pae("application/vnd.in-toto+json", payload_bytes)

            sig_entry = signatures[0]
            sig_bytes = base64.b64decode(sig_entry.get("sig", ""))
            signature_valid = verify_signature(pae, sig_bytes, public_key)

            if signature_valid:
                reason = "Signature valid"
                status = "PASS"
            else:
                reason = "Invalid signature"
                status = "FAIL"
        except AttestationVerificationFailedError:
            raise
        except Exception as exc:
            reason = f"Signature verification error: {exc}"
            status = "FAIL"
            signature_valid = False
    else:
        reason = "Unsigned attestation -- signature verification not available"
        status = "PARTIAL"

    return {
        "status": status,
        "signed": signed,
        "signature_valid": signature_valid,
        "hash_match": hash_match,
        "key_id": signatures[0].get("keyid") if signed else None,
        "attestation_timestamp": statement.get("predicate", {}).get("timestamp"),
        "reason": reason,
    }
