"""Phase 14: API Key model for programmatic access."""

import hashlib
import secrets
import uuid
from datetime import datetime

from sqlalchemy import Boolean, Column, DateTime, ForeignKey, Index, String, Text
from sqlalchemy.dialects.postgresql import JSONB, UUID
from sqlalchemy.orm import relationship

from app.database import Base

# ── Key generation constants ──────────────────────────────────────────────────
KEY_PREFIX  = "aegis_"
KEY_BYTES   = 32    # 32 random bytes → 64 hex chars → 70-char key total
DISPLAY_LEN = 12    # chars stored as prefix for UI display


def generate_raw_key() -> str:
    """Generate a fresh raw API key (must be shown to user only once)."""
    return KEY_PREFIX + secrets.token_hex(KEY_BYTES)


def hash_key(raw_key: str) -> str:
    """SHA-256 hash of a raw API key for secure storage."""
    return hashlib.sha256(raw_key.encode()).hexdigest()


def key_prefix_display(raw_key: str) -> str:
    """First DISPLAY_LEN characters of the raw key (safe for UI)."""
    return raw_key[:DISPLAY_LEN]


# ── Valid scopes ──────────────────────────────────────────────────────────────
VALID_SCOPES = {"read", "write", "admin"}


class ApiKey(Base):
    """
    Scoped API key for programmatic / BI / SOAR access.

    The full raw key is **never stored** — only a SHA-256 hash.
    The first 12 characters (``key_prefix``) are retained for display.
    """

    __tablename__ = "api_keys"

    id          = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    name        = Column(String(200), nullable=False)
    description = Column(Text, nullable=True)

    # Display only — never use for auth
    key_prefix  = Column(String(DISPLAY_LEN + 1), nullable=False)

    # Auth token — SHA-256 of the full raw key
    key_hash    = Column(String(64), nullable=False, unique=True)

    # Owner
    user_id     = Column(
        UUID(as_uuid=True),
        ForeignKey("users.id", ondelete="CASCADE"),
        nullable=False,
    )

    # Permissions
    scopes      = Column(JSONB, nullable=False, default=["read"])   # ["read","write","admin"]

    # Lifecycle
    last_used_at = Column(DateTime, nullable=True)
    expires_at   = Column(DateTime, nullable=True)
    is_active    = Column(Boolean, nullable=False, default=True)
    created_at   = Column(DateTime, default=datetime.utcnow)

    user = relationship("User", foreign_keys=[user_id])

    __table_args__ = (
        Index("ix_api_keys_user_id",  "user_id"),
        Index("ix_api_keys_key_hash", "key_hash"),
        Index("ix_api_keys_active",   "is_active"),
    )
