"""
API Keys Management Endpoints
"""
from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func
from pydantic import BaseModel
from typing import Optional, List
from datetime import datetime, timedelta
import secrets
import hashlib

from app.database import get_db
from app.auth.dependencies import get_current_user
from app.models.user import User
from app.models.api_key import ApiKey

router = APIRouter()


# Request/Response Models
class ApiKeyCreate(BaseModel):
    name: str
    permissions: Optional[List[str]] = ["*"]
    allowed_services: Optional[List[str]] = []
    expires_in_days: Optional[int] = None
    is_test_key: Optional[bool] = False


class ApiKeyResponse(BaseModel):
    id: int
    name: str
    key_prefix: str
    permissions: list
    allowed_services: list
    is_active: bool
    is_test_key: bool
    expires_at: Optional[datetime]
    last_used_at: Optional[datetime]
    total_requests: int
    created_at: datetime

    class Config:
        from_attributes = True


class ApiKeyCreatedResponse(ApiKeyResponse):
    api_key: str  # Only returned on creation


class ApiKeyListResponse(BaseModel):
    api_keys: List[ApiKeyResponse]
    total: int


@router.get("", response_model=ApiKeyListResponse)
async def list_api_keys(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    List all API keys for the current user/client
    """
    query = select(ApiKey).where(ApiKey.user_id == current_user.id)

    result = await db.execute(query)
    api_keys = result.scalars().all()

    return ApiKeyListResponse(
        api_keys=[ApiKeyResponse(
            id=key.id,
            name=key.name,
            key_prefix=key.key_prefix,
            permissions=key.permissions or [],
            allowed_services=key.allowed_services or [],
            is_active=key.is_active,
            is_test_key=key.is_test_key,
            expires_at=key.expires_at,
            last_used_at=key.last_used_at,
            total_requests=key.total_requests,
            created_at=key.created_at
        ) for key in api_keys],
        total=len(api_keys)
    )


@router.post("", response_model=ApiKeyCreatedResponse, status_code=status.HTTP_201_CREATED)
async def create_api_key(
    data: ApiKeyCreate,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    Create a new API key
    """
    # Generate API key
    if data.is_test_key:
        api_key = f"test_{''.join(secrets.token_hex(24))}"
    else:
        api_key = f"live_{''.join(secrets.token_hex(24))}"

    key_prefix = api_key[:8]
    key_hash = hashlib.sha256(api_key.encode()).hexdigest()

    # Calculate expiry
    expires_at = None
    if data.expires_in_days:
        expires_at = datetime.utcnow() + timedelta(days=data.expires_in_days)

    api_key_obj = ApiKey(
        user_id=current_user.id,
        client_id=current_user.client_id,
        name=data.name,
        key_prefix=key_prefix,
        key_hash=key_hash,
        permissions=data.permissions,
        allowed_services=data.allowed_services,
        is_test_key=data.is_test_key,
        expires_at=expires_at,
        is_active=True
    )
    db.add(api_key_obj)
    await db.commit()
    await db.refresh(api_key_obj)

    return ApiKeyCreatedResponse(
        id=api_key_obj.id,
        name=api_key_obj.name,
        key_prefix=api_key_obj.key_prefix,
        permissions=api_key_obj.permissions or [],
        allowed_services=api_key_obj.allowed_services or [],
        is_active=api_key_obj.is_active,
        is_test_key=api_key_obj.is_test_key,
        expires_at=api_key_obj.expires_at,
        last_used_at=api_key_obj.last_used_at,
        total_requests=api_key_obj.total_requests,
        created_at=api_key_obj.created_at,
        api_key=api_key  # Only returned once!
    )


@router.get("/{key_id}", response_model=ApiKeyResponse)
async def get_api_key(
    key_id: int,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    Get API key details
    """
    result = await db.execute(
        select(ApiKey)
        .where(ApiKey.id == key_id)
        .where(ApiKey.user_id == current_user.id)
    )
    api_key = result.scalar_one_or_none()

    if not api_key:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="API key not found"
        )

    return ApiKeyResponse(
        id=api_key.id,
        name=api_key.name,
        key_prefix=api_key.key_prefix,
        permissions=api_key.permissions or [],
        allowed_services=api_key.allowed_services or [],
        is_active=api_key.is_active,
        is_test_key=api_key.is_test_key,
        expires_at=api_key.expires_at,
        last_used_at=api_key.last_used_at,
        total_requests=api_key.total_requests,
        created_at=api_key.created_at
    )


@router.put("/{key_id}", response_model=ApiKeyResponse)
async def update_api_key(
    key_id: int,
    data: dict,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    Update API key (name, permissions, etc.)
    """
    result = await db.execute(
        select(ApiKey)
        .where(ApiKey.id == key_id)
        .where(ApiKey.user_id == current_user.id)
    )
    api_key = result.scalar_one_or_none()

    if not api_key:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="API key not found"
        )

    # Update allowed fields
    if "name" in data:
        api_key.name = data["name"]
    if "permissions" in data:
        api_key.permissions = data["permissions"]
    if "allowed_services" in data:
        api_key.allowed_services = data["allowed_services"]
    if "is_active" in data:
        api_key.is_active = data["is_active"]

    await db.commit()
    await db.refresh(api_key)

    return ApiKeyResponse(
        id=api_key.id,
        name=api_key.name,
        key_prefix=api_key.key_prefix,
        permissions=api_key.permissions or [],
        allowed_services=api_key.allowed_services or [],
        is_active=api_key.is_active,
        is_test_key=api_key.is_test_key,
        expires_at=api_key.expires_at,
        last_used_at=api_key.last_used_at,
        total_requests=api_key.total_requests,
        created_at=api_key.created_at
    )


@router.delete("/{key_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_api_key(
    key_id: int,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    Delete/revoke an API key
    """
    result = await db.execute(
        select(ApiKey)
        .where(ApiKey.id == key_id)
        .where(ApiKey.user_id == current_user.id)
    )
    api_key = result.scalar_one_or_none()

    if not api_key:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="API key not found"
        )

    await db.delete(api_key)
    await db.commit()


@router.post("/{key_id}/regenerate", response_model=ApiKeyCreatedResponse)
async def regenerate_api_key(
    key_id: int,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    Regenerate an API key (creates new key, invalidates old one)
    """
    result = await db.execute(
        select(ApiKey)
        .where(ApiKey.id == key_id)
        .where(ApiKey.user_id == current_user.id)
    )
    api_key = result.scalar_one_or_none()

    if not api_key:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="API key not found"
        )

    # Generate new key
    if api_key.is_test_key:
        new_api_key = f"test_{''.join(secrets.token_hex(24))}"
    else:
        new_api_key = f"live_{''.join(secrets.token_hex(24))}"

    api_key.key_prefix = new_api_key[:8]
    api_key.key_hash = hashlib.sha256(new_api_key.encode()).hexdigest()
    api_key.total_requests = 0
    api_key.last_used_at = None

    await db.commit()
    await db.refresh(api_key)

    return ApiKeyCreatedResponse(
        id=api_key.id,
        name=api_key.name,
        key_prefix=api_key.key_prefix,
        permissions=api_key.permissions or [],
        allowed_services=api_key.allowed_services or [],
        is_active=api_key.is_active,
        is_test_key=api_key.is_test_key,
        expires_at=api_key.expires_at,
        last_used_at=api_key.last_used_at,
        total_requests=api_key.total_requests,
        created_at=api_key.created_at,
        api_key=new_api_key
    )
