from datetime import datetime
from typing import Optional

import typer

from cli.commands.api_keys.create.presenter import present_api_key_create_success
from cli.infrastructure.command import async_command, authenticated_client
from alloy_runtime_types.dtos.api_keys import CreateApiKeyRequest
from alloy_runtime_types.enums.api_key_scope import ApiKeyScope


def api_keys_create_command(
    scope: list[str] = typer.Option(
        ...,
        "--scope",
        help="API key scope. Repeat for multiple values: read, update, delete, use",
    ),
    description: Optional[str] = typer.Option(
        None,
        "-d",
        "--description",
        help="API key description",
    ),
    expires_at: Optional[str] = typer.Option(
        None,
        "--expires-at",
        help="Optional expiration datetime (ISO 8601)",
    ),
) -> None:
    _execute_create_from_flags(
        scope=scope,
        description=description,
        expires_at=expires_at,
    )


@async_command
async def _execute_create(request: CreateApiKeyRequest) -> None:
    async with authenticated_client() as (_config, client):
        response = await client.create_api_key(request)

    present_api_key_create_success(response)


def _execute_create_from_flags(
    scope: list[str],
    description: Optional[str],
    expires_at: Optional[str],
) -> None:
    expires_datetime: datetime | None = None
    if expires_at:
        try:
            expires_datetime = datetime.fromisoformat(expires_at.replace("Z", "+00:00"))
        except ValueError:
            raise typer.BadParameter(
                f"Invalid datetime format: '{expires_at}'. Must be ISO 8601 format (e.g., '2025-12-31T23:59:59Z')"
            )

    request = CreateApiKeyRequest(
        scopes=[_validate_api_key_scope(value) for value in scope],
        description=description,
        expires_at=expires_datetime,
    )

    _execute_create(request)


def _validate_api_key_scope(value: str) -> ApiKeyScope:
    try:
        return ApiKeyScope(value.lower())
    except ValueError:
        valid = ", ".join(scope.value for scope in ApiKeyScope)
        raise typer.BadParameter(f"Invalid API key scope '{value}'. Valid: {valid}")
