import argparse
import sys
from datetime import datetime, timezone

from nebula_cert_manager.exceptions import (
    CertAlreadyRevokedError,
    CertManagerError,
    CertNotFoundError,
    RegistryNotFoundError,
)
from nebula_cert_manager.models import ClientInfo
from nebula_cert_manager.registry import RegistryManager


def add_parser(subparsers: argparse._SubParsersAction) -> None:
    parser = subparsers.add_parser("revoke", help="Revoke a client certificate")
    parser.add_argument("--fingerprint", required=True, help="Certificate fingerprint")
    parser.set_defaults(func=run)


def revoke_cert(
    registry_mgr: RegistryManager,
    fingerprint: str,
) -> tuple[str, ClientInfo]:
    """Revoke a certificate by fingerprint.

    Returns (name, client) of the revoked certificate.
    Raises RegistryNotFoundError, CertNotFoundError, CertAlreadyRevokedError.
    """
    if not registry_mgr.exists():
        raise RegistryNotFoundError()

    registry = registry_mgr.load()

    result = registry.find_by_fingerprint(fingerprint)
    if result is None:
        raise CertNotFoundError(fingerprint=fingerprint)

    name, client = result
    if client.revoked:
        raise CertAlreadyRevokedError(name, fingerprint)

    client.revoked = True
    client.revoked_at = datetime.now(timezone.utc)

    registry_mgr.save(registry)
    return (name, client)


def run(args: argparse.Namespace) -> None:
    try:
        name, client = revoke_cert(args.registry_mgr, args.fingerprint)
    except CertManagerError as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)
    print(f"Certificate '{name}' ({args.fingerprint}) revoked.")
