"""
Router blockchain — ancrer, remplacer et vérifier des credentials CertiChain.
"""
import logging

from fastapi import APIRouter, HTTPException

from app.schemas.blockchain import (
    AnchorCredentialRequest,
    AnchorCredentialResponse,
    ReplaceCredentialRequest,
    ReplaceCredentialResponse,
    VerifyCredentialResponse,
)
from app.services.blockchain_service import blockchain_service, compute_credential_hash

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/blockchain", tags=["blockchain"])


@router.post(
    "/anchor",
    response_model=AnchorCredentialResponse,
    summary="Ancrer un credential sur Polygon",
)
async def anchor_credential(payload: AnchorCredentialRequest) -> AnchorCredentialResponse:
    """
    Calcule le hash SHA-256 canonique du credential et l'inscrit sur le smart
    contract CertiChain via une transaction Polygon signée par le wallet admin.

    Appelé de manière asynchrone par le Job Laravel après acceptation étudiant.
    """
    try:
        result = blockchain_service.anchor_credential(payload.model_dump())
        return AnchorCredentialResponse(**result)
    except RuntimeError as exc:
        raise HTTPException(status_code=503, detail=str(exc))
    except Exception as exc:
        logger.exception("Erreur anchor_credential : %s", exc)
        raise HTTPException(status_code=500, detail=f"Erreur blockchain : {exc}")


@router.post(
    "/replace",
    response_model=ReplaceCredentialResponse,
    summary="Remplacer un credential par un correctif",
)
async def replace_credential(payload: ReplaceCredentialRequest) -> ReplaceCredentialResponse:
    """
    Marque le credential original comme remplacé sur la blockchain et ancre
    le credential correctif en une seule transaction.

    Le hash de l'original (old_hash) doit déjà être ancré sur la chaîne.
    """
    try:
        data = payload.model_dump()
        old_hash = data.pop("old_hash")
        result   = blockchain_service.replace_credential(old_hash, data)
        return ReplaceCredentialResponse(**result)
    except RuntimeError as exc:
        raise HTTPException(status_code=503, detail=str(exc))
    except Exception as exc:
        logger.exception("Erreur replace_credential : %s", exc)
        raise HTTPException(status_code=500, detail=f"Erreur blockchain : {exc}")


@router.get(
    "/verify/{hash_hex}",
    response_model=VerifyCredentialResponse,
    summary="Vérifier un credential (lecture seule)",
)
async def verify_credential(hash_hex: str) -> VerifyCredentialResponse:
    """
    Vérifie l'authenticité d'un credential sur la blockchain (pas de transaction).
    Utilisé par la page publique /verifier et les employeurs.
    """
    if len(hash_hex) != 64:
        raise HTTPException(status_code=422, detail="Le hash doit faire exactement 64 caractères hex")

    try:
        result = blockchain_service.verify_credential(hash_hex)
        return VerifyCredentialResponse(**result)
    except RuntimeError as exc:
        raise HTTPException(status_code=503, detail=str(exc))
    except Exception as exc:
        logger.exception("Erreur verify_credential : %s", exc)
        raise HTTPException(status_code=500, detail=f"Erreur blockchain : {exc}")


@router.get(
    "/hash",
    summary="Calculer le hash d'un credential (sans transaction)",
)
async def compute_hash(
    numero_serie:       str,
    etablissement_slug: str,
    titulaire_email:    str,
    type:               str,
    intitule:           str,
    date_emission:      str,
    mention:            str = "",
    annee_academique:   str = "",
) -> dict:
    """Utilitaire — calcule le hash SHA-256 sans inscrire sur la blockchain."""
    data = {
        "numero_serie":       numero_serie,
        "etablissement_slug": etablissement_slug,
        "titulaire_email":    titulaire_email,
        "type":               type,
        "intitule":           intitule,
        "mention":            mention,
        "date_emission":      date_emission,
        "annee_academique":   annee_academique,
    }
    return {"hash": compute_credential_hash(data)}
