"""
Storage provider routes for L2 server.

Manages user storage backends.
"""

import logging
from typing import Optional, Dict, Any

from fastapi import APIRouter, Request, Depends, HTTPException, Form
from fastapi.responses import HTMLResponse
from pydantic import BaseModel

from artdag_common import render
from artdag_common.middleware import wants_html, wants_json

from ..config import settings
from ..dependencies import get_templates, require_auth, get_user_from_cookie

router = APIRouter()
logger = logging.getLogger(__name__)


STORAGE_PROVIDERS_INFO = {
    "pinata": {"name": "Pinata", "desc": "1GB free, IPFS pinning", "color": "blue"},
    "web3storage": {"name": "web3.storage", "desc": "IPFS + Filecoin", "color": "green"},
    "nftstorage": {"name": "NFT.Storage", "desc": "Free for NFTs", "color": "pink"},
    "infura": {"name": "Infura IPFS", "desc": "5GB free", "color": "orange"},
    "filebase": {"name": "Filebase", "desc": "5GB free, S3+IPFS", "color": "cyan"},
    "storj": {"name": "Storj", "desc": "25GB free", "color": "indigo"},
    "local": {"name": "Local Storage", "desc": "Your own disk", "color": "purple"},
}


class AddStorageRequest(BaseModel):
    provider_type: str
    config: Dict[str, Any]
    capacity_gb: int = 5
    provider_name: Optional[str] = None


@router.get("")
async def list_storage(request: Request):
    """List user's storage providers."""
    import db

    username = get_user_from_cookie(request)
    if not username:
        if wants_json(request):
            raise HTTPException(401, "Authentication required")
        from fastapi.responses import RedirectResponse
        return RedirectResponse(url="/login", status_code=302)

    storages = await db.get_user_storage(username)

    if wants_json(request):
        return {"storages": storages}

    templates = get_templates(request)
    return render(templates, "storage/list.html", request,
        storages=storages,
        user={"username": username},
        providers_info=STORAGE_PROVIDERS_INFO,
        active_tab="storage",
    )


@router.post("")
async def add_storage(
    req: AddStorageRequest,
    user: dict = Depends(require_auth),
):
    """Add a storage provider."""
    import db
    import storage_providers

    if req.provider_type not in STORAGE_PROVIDERS_INFO:
        raise HTTPException(400, f"Invalid provider type: {req.provider_type}")

    # Test connection
    provider = storage_providers.create_provider(req.provider_type, {
        **req.config,
        "capacity_gb": req.capacity_gb,
    })
    if not provider:
        raise HTTPException(400, "Failed to create provider")

    success, message = await provider.test_connection()
    if not success:
        raise HTTPException(400, f"Connection failed: {message}")

    # Save
    storage_id = await db.add_user_storage(
        username=user["username"],
        provider_type=req.provider_type,
        provider_name=req.provider_name,
        config=req.config,
        capacity_gb=req.capacity_gb,
    )

    return {"id": storage_id, "message": "Storage provider added"}


@router.post("/add", response_class=HTMLResponse)
async def add_storage_form(
    request: Request,
    provider_type: str = Form(...),
    provider_name: Optional[str] = Form(None),
    capacity_gb: int = Form(5),
    api_key: Optional[str] = Form(None),
    secret_key: Optional[str] = Form(None),
    api_token: Optional[str] = Form(None),
    project_id: Optional[str] = Form(None),
    project_secret: Optional[str] = Form(None),
    access_key: Optional[str] = Form(None),
    bucket: Optional[str] = Form(None),
    path: Optional[str] = Form(None),
):
    """Add storage via HTML form."""
    import db
    import storage_providers

    username = get_user_from_cookie(request)
    if not username:
        return HTMLResponse('<div class="text-red-400">Not authenticated</div>', status_code=401)

    # Build config
    config = {}
    if provider_type == "pinata":
        if not api_key or not secret_key:
            return HTMLResponse('<div class="text-red-400">Pinata requires API Key and Secret Key</div>')
        config = {"api_key": api_key, "secret_key": secret_key}
    elif provider_type in ["web3storage", "nftstorage"]:
        if not api_token:
            return HTMLResponse(f'<div class="text-red-400">{provider_type} requires API Token</div>')
        config = {"api_token": api_token}
    elif provider_type == "infura":
        if not project_id or not project_secret:
            return HTMLResponse('<div class="text-red-400">Infura requires Project ID and Secret</div>')
        config = {"project_id": project_id, "project_secret": project_secret}
    elif provider_type in ["filebase", "storj"]:
        if not access_key or not secret_key or not bucket:
            return HTMLResponse('<div class="text-red-400">Requires Access Key, Secret Key, and Bucket</div>')
        config = {"access_key": access_key, "secret_key": secret_key, "bucket": bucket}
    elif provider_type == "local":
        if not path:
            return HTMLResponse('<div class="text-red-400">Local storage requires a path</div>')
        config = {"path": path}
    else:
        return HTMLResponse(f'<div class="text-red-400">Unknown provider: {provider_type}</div>')

    # Test
    provider = storage_providers.create_provider(provider_type, {**config, "capacity_gb": capacity_gb})
    if provider:
        success, message = await provider.test_connection()
        if not success:
            return HTMLResponse(f'<div class="text-red-400">Connection failed: {message}</div>')

    # Save
    storage_id = await db.add_user_storage(
        username=username,
        provider_type=provider_type,
        provider_name=provider_name,
        config=config,
        capacity_gb=capacity_gb,
    )

    return HTMLResponse(f'''
        <div class="text-green-400 mb-2">Storage provider added!</div>
        <script>setTimeout(() => window.location.href = '/storage', 1500);</script>
    ''')


@router.get("/{storage_id}")
async def get_storage(
    storage_id: int,
    user: dict = Depends(require_auth),
):
    """Get storage details."""
    import db

    storage = await db.get_storage_by_id(storage_id)
    if not storage:
        raise HTTPException(404, "Storage not found")

    if storage.get("username") != user["username"]:
        raise HTTPException(403, "Not authorized")

    return storage


@router.delete("/{storage_id}")
async def delete_storage(
    storage_id: int,
    request: Request,
    user: dict = Depends(require_auth),
):
    """Delete a storage provider."""
    import db

    storage = await db.get_storage_by_id(storage_id)
    if not storage:
        raise HTTPException(404, "Storage not found")

    if storage.get("username") != user["username"]:
        raise HTTPException(403, "Not authorized")

    success = await db.remove_user_storage(storage_id)

    if wants_html(request):
        return HTMLResponse("")

    return {"deleted": True}


@router.post("/{storage_id}/test")
async def test_storage(
    storage_id: int,
    request: Request,
    user: dict = Depends(require_auth),
):
    """Test storage connectivity."""
    import db
    import storage_providers
    import json

    storage = await db.get_storage_by_id(storage_id)
    if not storage:
        raise HTTPException(404, "Storage not found")

    if storage.get("username") != user["username"]:
        raise HTTPException(403, "Not authorized")

    config = storage["config"]
    if isinstance(config, str):
        config = json.loads(config)

    provider = storage_providers.create_provider(storage["provider_type"], {
        **config,
        "capacity_gb": storage.get("capacity_gb", 5),
    })

    if not provider:
        if wants_html(request):
            return HTMLResponse('<span class="text-red-400">Failed to create provider</span>')
        return {"success": False, "message": "Failed to create provider"}

    success, message = await provider.test_connection()

    if wants_html(request):
        color = "green" if success else "red"
        return HTMLResponse(f'<span class="text-{color}-400">{message}</span>')

    return {"success": success, "message": message}
