"""Settings API routes."""

import uuid
from pathlib import Path
from typing import List
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel

from ..models import SettingsRequest, SettingsResponse, ValidateKeyResponse
from ..config import (
    load_config, save_config,
    get_custom_prompts, add_custom_prompt, update_custom_prompt, delete_custom_prompt,
    get_webhook_config, set_webhook_config,
    get_provider_settings, set_provider_settings,
    get_models_config, update_model_config, reset_models_to_defaults,
    get_all_system_prompts, get_system_prompt, update_system_prompt,
    reset_system_prompt, reset_all_system_prompts
)


class CustomPromptRequest(BaseModel):
    name: str
    prompt: str


class CustomPromptResponse(BaseModel):
    id: str
    name: str
    prompt: str


class WebhookRequest(BaseModel):
    url: str = None
    enabled: bool = None


class ProviderSettingsRequest(BaseModel):
    transcription_provider: str = None  # openai, eden
    analysis_provider: str = None  # openai, anthropic, eden
    critique_provider: str = None  # anthropic, openai, eden
    resources_provider: str = None  # perplexity, eden


router = APIRouter()


@router.get("/settings", response_model=SettingsResponse)
async def get_settings():
    """Get current application settings."""
    config = load_config()
    return SettingsResponse(
        openai_api_key_set=bool(config.openai_api_key),
        perplexity_api_key_set=bool(config.perplexity_api_key),
        anthropic_api_key_set=bool(config.anthropic_api_key),
        eden_api_key_set=bool(config.eden_api_key),
        output_directory=config.output_directory,
        transcription_provider=config.transcription_provider,
        analysis_provider=config.analysis_provider,
        critique_provider=config.critique_provider,
        resources_provider=config.resources_provider
    )


@router.post("/settings", response_model=SettingsResponse)
async def update_settings(request: SettingsRequest):
    """Update application settings."""
    config = load_config()

    # API Keys
    if request.openai_api_key is not None:
        config.openai_api_key = request.openai_api_key

    if request.perplexity_api_key is not None:
        config.perplexity_api_key = request.perplexity_api_key

    if request.anthropic_api_key is not None:
        config.anthropic_api_key = request.anthropic_api_key

    if request.eden_api_key is not None:
        config.eden_api_key = request.eden_api_key

    # Provider selection
    if request.transcription_provider is not None:
        config.transcription_provider = request.transcription_provider

    if request.analysis_provider is not None:
        config.analysis_provider = request.analysis_provider

    if request.critique_provider is not None:
        config.critique_provider = request.critique_provider

    if request.resources_provider is not None:
        config.resources_provider = request.resources_provider

    # Output directory
    if request.output_directory is not None:
        # Validate directory path
        output_path = Path(request.output_directory)
        try:
            output_path.mkdir(parents=True, exist_ok=True)
            if not output_path.is_dir():
                raise HTTPException(status_code=400, detail="Invalid directory path")
        except PermissionError:
            raise HTTPException(status_code=400, detail="Permission denied for directory")
        except Exception as e:
            raise HTTPException(status_code=400, detail=f"Invalid path: {str(e)}")

        config.output_directory = str(output_path.absolute())

    save_config(config)

    return SettingsResponse(
        openai_api_key_set=bool(config.openai_api_key),
        perplexity_api_key_set=bool(config.perplexity_api_key),
        anthropic_api_key_set=bool(config.anthropic_api_key),
        eden_api_key_set=bool(config.eden_api_key),
        output_directory=config.output_directory,
        transcription_provider=config.transcription_provider,
        analysis_provider=config.analysis_provider,
        critique_provider=config.critique_provider,
        resources_provider=config.resources_provider
    )


@router.post("/settings/validate-key", response_model=ValidateKeyResponse)
async def validate_api_key(request: SettingsRequest):
    """Validate an OpenAI API key."""
    if not request.openai_api_key:
        raise HTTPException(status_code=400, detail="API key is required")

    try:
        from openai import OpenAI
        client = OpenAI(api_key=request.openai_api_key)
        # Try a simple API call to validate the key
        client.models.list()
        return ValidateKeyResponse(valid=True, message="API key is valid")
    except Exception as e:
        return ValidateKeyResponse(valid=False, message=str(e))


class TestEdenRequest(BaseModel):
    eden_api_key: str = None


@router.post("/settings/test-eden", response_model=ValidateKeyResponse)
async def test_eden_key(request: TestEdenRequest):
    """Test Eden.ai API key by making a simple API call."""
    import httpx

    # Use provided key or load from config
    api_key = request.eden_api_key
    if not api_key:
        config = load_config()
        api_key = config.eden_api_key

    if not api_key:
        return ValidateKeyResponse(valid=False, message="No Eden API key provided")

    try:
        # Test by making a minimal API call to validate the key
        async with httpx.AsyncClient(timeout=15.0) as client:
            # Use a simple text analysis call to validate the key
            response = await client.post(
                "https://api.edenai.run/v2/text/keyword_extraction",
                headers={
                    "Authorization": f"Bearer {api_key}",
                    "Content-Type": "application/json"
                },
                json={
                    "providers": "openai",
                    "text": "Test connection",
                    "language": "en"
                }
            )

            if response.status_code == 200:
                return ValidateKeyResponse(valid=True, message="Eden.ai connection successful!")
            elif response.status_code == 401 or response.status_code == 403:
                return ValidateKeyResponse(valid=False, message="Invalid or unauthorized API key")
            elif response.status_code == 400:
                # Bad request but key is valid
                return ValidateKeyResponse(valid=True, message="Eden.ai API key is valid")
            else:
                error_msg = response.text[:100] if response.text else f"Status {response.status_code}"
                return ValidateKeyResponse(valid=False, message=f"API error: {error_msg}")
    except httpx.TimeoutException:
        return ValidateKeyResponse(valid=False, message="Connection timed out")
    except Exception as e:
        return ValidateKeyResponse(valid=False, message=str(e))


# Custom Prompts CRUD
@router.get("/prompts", response_model=List[CustomPromptResponse])
async def list_prompts():
    """Get all custom prompts."""
    prompts = get_custom_prompts()
    return [CustomPromptResponse(**p) for p in prompts]


@router.post("/prompts", response_model=CustomPromptResponse)
async def create_prompt(request: CustomPromptRequest):
    """Create a new custom prompt."""
    prompt_id = str(uuid.uuid4())[:8]
    prompt = add_custom_prompt(prompt_id, request.name, request.prompt)
    return CustomPromptResponse(**prompt)


@router.put("/prompts/{prompt_id}", response_model=CustomPromptResponse)
async def update_prompt(prompt_id: str, request: CustomPromptRequest):
    """Update an existing custom prompt."""
    prompt = update_custom_prompt(prompt_id, request.name, request.prompt)
    if not prompt:
        raise HTTPException(status_code=404, detail="Prompt not found")
    return CustomPromptResponse(**prompt)


@router.delete("/prompts/{prompt_id}")
async def remove_prompt(prompt_id: str):
    """Delete a custom prompt."""
    if delete_custom_prompt(prompt_id):
        return {"success": True}
    raise HTTPException(status_code=404, detail="Prompt not found")


# Webhook Settings
@router.get("/webhook")
async def get_webhook():
    """Get webhook configuration."""
    url, enabled = get_webhook_config()
    return {"url": url, "enabled": enabled}


@router.post("/webhook")
async def update_webhook(request: WebhookRequest):
    """Update webhook configuration."""
    set_webhook_config(url=request.url, enabled=request.enabled)
    url, enabled = get_webhook_config()
    return {"url": url, "enabled": enabled}


# ============================================================================
# Model Configuration Endpoints
# ============================================================================

class ModelUpdateRequest(BaseModel):
    model: str = None
    cost: float = None


@router.get("/models")
async def get_models():
    """Get all model configurations (defaults merged with overrides)."""
    return get_models_config()


@router.put("/models/{model_type}/{provider}")
async def update_model(model_type: str, provider: str, request: ModelUpdateRequest):
    """
    Update model configuration for a provider.

    Args:
        model_type: 'transcription', 'analysis', or 'resources'
        provider: Provider name (e.g., 'openai', 'anthropic')
    """
    if model_type not in ["transcription", "analysis", "resources"]:
        raise HTTPException(status_code=400, detail="Invalid model type")

    result = update_model_config(model_type, provider, request.model, request.cost)
    if not result:
        raise HTTPException(status_code=400, detail="Failed to update model config")

    return result


@router.post("/models/reset")
async def reset_models(model_type: str = None):
    """
    Reset model configurations to defaults.

    Args:
        model_type: 'transcription', 'analysis', 'resources', or None for all
    """
    if model_type and model_type not in ["transcription", "analysis", "resources"]:
        raise HTTPException(status_code=400, detail="Invalid model type")

    reset_models_to_defaults(model_type)
    return {"success": True, "models": get_models_config()}


# ============================================================================
# System Prompt Endpoints
# ============================================================================

class SystemPromptUpdateRequest(BaseModel):
    prompt: str


@router.get("/system-prompts")
async def get_system_prompts():
    """Get all system prompts (defaults merged with overrides)."""
    return get_all_system_prompts()


@router.put("/system-prompts/{prompt_id}")
async def update_system_prompt_endpoint(prompt_id: str, request: SystemPromptUpdateRequest):
    """Update a system prompt (creates an override)."""
    if not update_system_prompt(prompt_id, request.prompt):
        raise HTTPException(status_code=404, detail="System prompt not found")

    # Return the updated prompt info
    prompts = get_all_system_prompts()
    return prompts.get(prompt_id)


@router.post("/system-prompts/{prompt_id}/reset")
async def reset_system_prompt_endpoint(prompt_id: str):
    """Reset a system prompt to its default."""
    reset_system_prompt(prompt_id)

    # Return the reset prompt info
    prompts = get_all_system_prompts()
    if prompt_id not in prompts:
        raise HTTPException(status_code=404, detail="System prompt not found")

    return prompts.get(prompt_id)


@router.post("/system-prompts/reset-all")
async def reset_all_prompts():
    """Reset all system prompts to defaults."""
    reset_all_system_prompts()
    return {"success": True, "prompts": get_all_system_prompts()}
