import argparse
import hashlib
import os
import secrets
from datetime import datetime, timedelta

from hieromem_api.tenants import SqliteTenantRegistry, Tenant
from hieromem_api.settings import get_settings
from hieromem_api.vault import read_kv_secret, write_kv_secret

# Default to the same path as the app uses (from env or default)
DB_PATH = os.getenv("TENANT_REGISTRY_PATH", "tenants.db")


def generate_key():
    return secrets.token_urlsafe(32)


def hash_key(key: str):
    return hashlib.sha256(key.encode("utf-8")).hexdigest()


def get_registry():
    settings = get_settings()
    path = settings.tenant_registry_path or DB_PATH
    return SqliteTenantRegistry(path)


def _persist_vault_api_key(tenant_id: str, key_hash: str) -> None:
    settings = get_settings()
    if not settings.use_vault:
        return
    current = read_kv_secret(settings, settings.vault_api_key_path)
    current[tenant_id] = key_hash
    write_kv_secret(settings, settings.vault_api_key_path, current)


def create_key(tenant_id: str, expiry_days: int = 90):
    registry = get_registry()
    raw_key = generate_key()
    key_hash = hash_key(raw_key)

    now = datetime.utcnow()
    expires_at = now + timedelta(days=expiry_days)

    tenant = Tenant(
        tenant_id=tenant_id,
        api_key_hash=key_hash,
        api_key=raw_key,
        status="active",
        created_at=now,
        updated_at=now,
        expires_at=expires_at
    )

    registry.upsert(tenant)
    _persist_vault_api_key(tenant_id, key_hash)
    print(f"Created key for {tenant_id}")
    print(f"Key: {raw_key}")
    print(f"Expires: {expires_at.isoformat()}")
    print("SAVE THIS KEY! It will not be shown again.")


def list_keys(tenant_id: str = None):
    """List keys stored in the tenant registry."""

    registry = get_registry()
    tenants = registry.list_by_tenant(tenant_id) if tenant_id else registry.list_all()
    if not tenants:
        print("No keys found.")
        return

    print(f"{'Tenant ID':<20} {'Status':<10} {'Expires At':<30} {'Hash Prefix':<15}")
    print("-" * 75)
    for tenant in tenants:
        exp = tenant.expires_at.isoformat() if tenant.expires_at else "-"
        print(f"{tenant.tenant_id:<20} {tenant.status:<10} {exp:<30} {tenant.api_key_hash[:8]}...")


def revoke_key(tenant_id: str, key_hash_prefix: str):
    registry = get_registry()
    # We need to find the full hash first
    with registry._connect() as conn:
        cursor = conn.execute(
            "SELECT api_key_hash FROM tenants WHERE tenant_id = ? AND api_key_hash LIKE ?",
            (tenant_id, f"{key_hash_prefix}%")
        )
        row = cursor.fetchone()

        if not row:
            print("Key not found.")
            return

        full_hash = row[0]

        # Now update
        now = datetime.utcnow().isoformat()
        conn.execute(
            "UPDATE tenants SET status = 'revoked', revoked_at = ? WHERE api_key_hash = ?",
            (now, full_hash)
        )
        conn.commit()
        print(f"Revoked key {full_hash[:8]}...")


def rotate_key(tenant_id: str, expiry_days: int = 90):
    registry = get_registry()
    now = datetime.utcnow()
    # Revoke existing active keys for tenant
    for existing in registry.list_by_tenant(tenant_id):
        if existing.is_active():
            registry.revoke_key(existing.api_key_hash)

    raw_key = generate_key()
    key_hash = hash_key(raw_key)
    expires_at = now + timedelta(days=expiry_days)
    tenant = Tenant(
        tenant_id=tenant_id,
        api_key_hash=key_hash,
        api_key=raw_key,
        status="active",
        created_at=now,
        updated_at=now,
        expires_at=expires_at,
    )
    registry.upsert(tenant)
    _persist_vault_api_key(tenant_id, key_hash)
    print(f"Rotated key for {tenant_id}")
    print(f"New Key: {raw_key}")
    print(f"Expires: {expires_at.isoformat()}")


def main():
    parser = argparse.ArgumentParser(description="HIEROMEM API Key Manager")
    subparsers = parser.add_subparsers(dest="command")

    create = subparsers.add_parser("create")
    create.add_argument("tenant_id")
    create.add_argument("--days", type=int, default=90)

    list_cmd = subparsers.add_parser("list")
    list_cmd.add_argument("--tenant", help="Filter by tenant ID")

    revoke = subparsers.add_parser("revoke")
    revoke.add_argument("tenant_id")
    revoke.add_argument("hash_prefix", help="First few chars of key hash")

    rotate = subparsers.add_parser("rotate")
    rotate.add_argument("tenant_id")
    rotate.add_argument("--days", type=int, default=90)

    args = parser.parse_args()

    if args.command == "create":
        create_key(args.tenant_id, args.days)
    elif args.command == "list":
        list_keys(args.tenant)
    elif args.command == "revoke":
        revoke_key(args.tenant_id, args.hash_prefix)
    elif args.command == "rotate":
        rotate_key(args.tenant_id, args.days)
    else:
        parser.print_help()


if __name__ == "__main__":
    main()
