"""Dashboard API endpoints for user self-service."""

from __future__ import annotations

from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from typing import Optional
import logging
import secrets
import hashlib
from datetime import datetime, timedelta

from hieromem_api.auth import require_api_key
from hieromem_api.tenants import Tenant, get_tenant_registry
from hieromem_api.tiers import TIER_LIMITS, get_tier_limit
from hieromem_api.usage_tracker import get_usage_tracker
from hieromem_api.deps import get_memory_engine


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


class UsageResponse(BaseModel):
    """Current usage statistics."""
    tier: str
    usage: dict
    limits: dict
    percentage_used: dict


class APIKeyInfo(BaseModel):
    """API key information."""
    id: Optional[int]
    key_preview: str  # First 8 chars only
    created_at: datetime
    status: str
    expires_at: Optional[datetime] = None


class APIKeysResponse(BaseModel):
    """List of API keys."""
    keys: list[APIKeyInfo]


class CreateAPIKeyRequest(BaseModel):
    """Request to create new API key."""
    name: str
    expires_days: Optional[int] = None


class CreateAPIKeyResponse(BaseModel):
    """Response with new API key."""
    api_key: str
    key_id: int
    message: str


class NamespaceInfo(BaseModel):
    """Namespace information."""
    name: str
    episode_count: int


class NamespacesResponse(BaseModel):
    """List of namespaces."""
    namespaces: list[NamespaceInfo]
    total: int


class BillingInfo(BaseModel):
    """Billing information."""
    tier: str
    stripe_customer_id: Optional[str]
    subscription_status: Optional[str]
    next_billing_date: Optional[str]
    amount: float


@router.get("/usage", response_model=UsageResponse)
async def get_usage_stats(tenant: Tenant = Depends(require_api_key)):
    """
    Get current usage statistics for the authenticated tenant.

    Returns usage counts, limits, and percentage used.
    """
    tracker = get_usage_tracker()
    usage = tracker.get_usage(tenant.tenant_id)
    limits = TIER_LIMITS[tenant.tier]

    # Calculate percentage used
    memories_limit = limits["memories_per_month"]
    recalls_limit = limits["recalls_per_day"]

    percentage_used = {
        "memories": (usage.memories_this_month / memories_limit * 100) if memories_limit else 0,
        "recalls": (usage.recalls_today / recalls_limit * 100) if recalls_limit else 0,
    }

    return UsageResponse(
        tier=tenant.tier,
        usage={
            "memories_this_month": usage.memories_this_month,
            "recalls_today": usage.recalls_today,
            "recalls_this_month": usage.recalls_this_month,
        },
        limits={
            "memories_per_month": memories_limit,
            "recalls_per_day": recalls_limit,
            "namespaces": limits["namespaces"],
        },
        percentage_used=percentage_used
    )


@router.get("/api-keys", response_model=APIKeysResponse)
async def list_api_keys(tenant: Tenant = Depends(require_api_key)):
    """
    List all API keys for the authenticated tenant.

    Returns key previews (not full keys) for security.
    """
    registry = get_tenant_registry()
    keys = registry.list_by_tenant(tenant.tenant_id)

    key_infos = [
        APIKeyInfo(
            id=k.id,
            key_preview=k.api_key[:8] + "..." if len(k.api_key) > 8 else k.api_key,
            created_at=k.created_at,
            status=k.status,
            expires_at=k.expires_at
        )
        for k in keys
    ]

    return APIKeysResponse(keys=key_infos)


@router.post("/api-keys", response_model=CreateAPIKeyResponse)
async def create_api_key(
    req: CreateAPIKeyRequest,
    tenant: Tenant = Depends(require_api_key)
):
    """
    Create a new API key for the authenticated tenant.

    Returns the full API key (only shown once).
    """
    # Check namespace limit for tier
    registry = get_tenant_registry()
    existing_keys = registry.list_by_tenant(tenant.tenant_id)

    namespace_limit = get_tier_limit(tenant.tier, "namespaces")
    if namespace_limit and len(existing_keys) >= namespace_limit:
        raise HTTPException(
            status_code=403,
            detail=f"API key limit reached for {tenant.tier} tier ({namespace_limit} keys)"
        )

    # Generate new API key
    new_key = f"hm_{secrets.token_urlsafe(32)}"
    key_hash = hashlib.sha256(new_key.encode("utf-8")).hexdigest()

    # Calculate expiration
    expires_at = None
    if req.expires_days:
        expires_at = datetime.utcnow() + timedelta(days=req.expires_days)

    # Create new tenant entry
    new_tenant = Tenant(
        tenant_id=tenant.tenant_id,
        api_key=new_key,
        api_key_hash=key_hash,
        tier=tenant.tier,
        status="active",
        role=tenant.role,
        expires_at=expires_at,
        stripe_customer_id=tenant.stripe_customer_id,
        stripe_subscription_id=tenant.stripe_subscription_id,
    )

    registry.upsert(new_tenant)

    return CreateAPIKeyResponse(
        api_key=new_key,
        key_id=new_tenant.id or 0,
        message="API key created successfully. Save it now - you won't see it again!"
    )


@router.delete("/api-keys/{key_id}")
async def revoke_api_key(
    key_id: int,
    tenant: Tenant = Depends(require_api_key)
):
    """
    Revoke an API key.

    The key will no longer be valid for authentication.
    """
    registry = get_tenant_registry()
    keys = registry.list_by_tenant(tenant.tenant_id)

    # Find the key
    key_to_revoke = None
    for k in keys:
        if k.id == key_id:
            key_to_revoke = k
            break

    if not key_to_revoke:
        raise HTTPException(status_code=404, detail="API key not found")

    # Revoke it
    registry.revoke_key(key_to_revoke.api_key_hash)

    return {"status": "success", "message": "API key revoked"}


@router.get("/namespaces", response_model=NamespacesResponse)
async def list_namespaces(tenant: Tenant = Depends(require_api_key)):
    """
    List all namespaces for the authenticated tenant.

    Returns namespace names and episode counts.
    """
    memory = get_memory_engine()

    # Get all namespaces for this tenant
    if hasattr(memory, "_episodes_by_namespace"):
        # Multi-tenant mode
        prefix = f"{tenant.tenant_id}::"
        namespaces = [
            ns for ns in memory._episodes_by_namespace.keys()
            if ns.startswith(prefix)
        ]

        namespace_infos = [
            NamespaceInfo(
                name=ns.replace(prefix, ""),
                episode_count=len(memory._episodes_by_namespace.get(ns, []))
            )
            for ns in namespaces
        ]
    else:
        # Single tenant mode
        namespace_infos = [
            NamespaceInfo(
                name="default",
                episode_count=len(memory.episodes)
            )
        ]

    return NamespacesResponse(
        namespaces=namespace_infos,
        total=len(namespace_infos)
    )


@router.get("/billing", response_model=BillingInfo)
async def get_billing_info(tenant: Tenant = Depends(require_api_key)):
    """
    Get billing information for the authenticated tenant.

    Returns subscription status, next billing date, and amount.
    """
    # Get tier pricing
    tier_config = TIER_LIMITS[tenant.tier]
    amount = tier_config.get("price_monthly", 0)

    # TODO: Fetch actual subscription status from Stripe
    subscription_status = None
    next_billing_date = None

    if tenant.stripe_subscription_id:
        try:
            from hieromem_api.billing import get_billing_service
            billing = get_billing_service()
            subscription = billing.get_subscription(tenant.stripe_subscription_id)
            subscription_status = subscription.get("status")

            # Get next billing date
            current_period_end = subscription.get("current_period_end")
            if current_period_end:
                next_billing_date = datetime.fromtimestamp(current_period_end).isoformat()
        except ImportError:
            logging.warning("Billing service not available (hieromem_api.billing missing)")
        except Exception as e:
            logging.error("Failed to retrieve Stripe subscription for tenant %s: %s", tenant.tenant_id, str(e))

    return BillingInfo(
        tier=tenant.tier,
        stripe_customer_id=tenant.stripe_customer_id,
        subscription_status=subscription_status or ("active" if tenant.tier != "free" else None),
        next_billing_date=next_billing_date,
        amount=amount
    )


__all__ = ["router"]
