"""Cloud storage API routes."""

from typing import Optional
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel

from ..services.cloud import GoogleDriveProvider, DropboxProvider, CloudFile
from ..services.history import get_history_item, get_transcription_text
from ..config import load_config, save_config

router = APIRouter()

# Provider instances (singleton pattern)
_providers = {
    'google_drive': GoogleDriveProvider(),
    'dropbox': DropboxProvider()
}


class CloudCredentials(BaseModel):
    provider: str
    access_token: Optional[str] = None
    refresh_token: Optional[str] = None
    client_id: Optional[str] = None
    client_secret: Optional[str] = None
    app_key: Optional[str] = None
    app_secret: Optional[str] = None
    service_account_json: Optional[str] = None


class CloudUploadRequest(BaseModel):
    item_id: str
    provider: str
    filename: Optional[str] = None
    format: str = "txt"  # txt, md, pdf


@router.get("/cloud/providers")
async def list_providers():
    """List available cloud storage providers and their status."""
    providers = []
    for name, provider in _providers.items():
        providers.append({
            "id": name,
            "name": provider.display_name,
            "authenticated": provider.is_authenticated()
        })
    return {"providers": providers}


@router.post("/cloud/connect")
async def connect_provider(credentials: CloudCredentials):
    """
    Connect to a cloud storage provider.

    Different providers require different credentials:
    - google_drive: access_token, refresh_token, client_id, client_secret
                   OR service_account_json
    - dropbox: access_token (and optionally refresh_token, app_key, app_secret)
    """
    if credentials.provider not in _providers:
        raise HTTPException(status_code=400, detail=f"Unknown provider: {credentials.provider}")

    provider = _providers[credentials.provider]

    creds_dict = {
        'access_token': credentials.access_token,
        'refresh_token': credentials.refresh_token,
        'client_id': credentials.client_id,
        'client_secret': credentials.client_secret,
        'app_key': credentials.app_key,
        'app_secret': credentials.app_secret,
        'service_account_json': credentials.service_account_json
    }
    # Remove None values
    creds_dict = {k: v for k, v in creds_dict.items() if v is not None}

    try:
        success = await provider.authenticate(creds_dict)
        if success:
            return {
                "success": True,
                "provider": credentials.provider,
                "message": f"Connected to {provider.display_name}"
            }
        else:
            raise HTTPException(status_code=401, detail="Authentication failed")
    except ImportError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Connection failed: {str(e)}")


@router.post("/cloud/disconnect/{provider}")
async def disconnect_provider(provider: str):
    """Disconnect from a cloud storage provider."""
    if provider not in _providers:
        raise HTTPException(status_code=400, detail=f"Unknown provider: {provider}")

    # Reset the provider instance
    if provider == 'google_drive':
        _providers['google_drive'] = GoogleDriveProvider()
    elif provider == 'dropbox':
        _providers['dropbox'] = DropboxProvider()

    return {"success": True, "message": f"Disconnected from {provider}"}


@router.post("/cloud/upload")
async def upload_to_cloud(request: CloudUploadRequest):
    """
    Upload a transcription to cloud storage.

    Args:
        item_id: History item ID
        provider: 'google_drive' or 'dropbox'
        filename: Optional custom filename
        format: Export format ('txt', 'md', 'pdf')
    """
    if request.provider not in _providers:
        raise HTTPException(status_code=400, detail=f"Unknown provider: {request.provider}")

    provider = _providers[request.provider]
    if not provider.is_authenticated():
        raise HTTPException(
            status_code=401,
            detail=f"Not connected to {provider.display_name}. Please connect first."
        )

    # Get the transcription
    item = get_history_item(request.item_id)
    if not item:
        raise HTTPException(status_code=404, detail="Item not found")

    text = get_transcription_text(item['file_path'])
    if not text:
        raise HTTPException(status_code=404, detail="Transcription file not found")

    title = item.get('title', 'transcription')
    safe_title = "".join(c for c in title if c.isalnum() or c in (' ', '-', '_')).strip()[:50]

    # Generate content based on format
    if request.format == 'txt':
        content = text.encode('utf-8')
        filename = request.filename or f"{safe_title}.txt"
        content_type = "text/plain"

    elif request.format == 'md':
        from ..services.markdown_exporter import create_markdown
        metadata = {
            'url': item.get('url'),
            'duration': item.get('duration'),
            'created_at': item.get('created_at')
        }
        md_content = create_markdown(title, text, metadata)
        content = md_content.encode('utf-8')
        filename = request.filename or f"{safe_title}.md"
        content_type = "text/markdown"

    elif request.format == 'pdf':
        from ..services.pdf_exporter import create_pdf
        metadata = {
            'url': item.get('url'),
            'duration': item.get('duration'),
            'created_at': item.get('created_at')
        }
        content = create_pdf(title, text, metadata)
        filename = request.filename or f"{safe_title}.pdf"
        content_type = "application/pdf"

    else:
        raise HTTPException(status_code=400, detail=f"Unsupported format: {request.format}")

    try:
        result = await provider.upload_content(
            content=content,
            filename=filename,
            content_type=content_type
        )

        return {
            "success": True,
            "provider": request.provider,
            "file": {
                "id": result.id,
                "name": result.name,
                "path": result.path,
                "size": result.size,
                "web_link": result.web_link
            }
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Upload failed: {str(e)}")


@router.get("/cloud/files/{provider}")
async def list_cloud_files(provider: str):
    """List files in cloud storage."""
    if provider not in _providers:
        raise HTTPException(status_code=400, detail=f"Unknown provider: {provider}")

    prov = _providers[provider]
    if not prov.is_authenticated():
        raise HTTPException(status_code=401, detail="Not connected")

    try:
        files = await prov.list_files()
        return {
            "provider": provider,
            "files": [
                {
                    "id": f.id,
                    "name": f.name,
                    "path": f.path,
                    "size": f.size,
                    "web_link": f.web_link
                }
                for f in files
            ]
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.delete("/cloud/files/{provider}/{file_id}")
async def delete_cloud_file(provider: str, file_id: str):
    """Delete a file from cloud storage."""
    if provider not in _providers:
        raise HTTPException(status_code=400, detail=f"Unknown provider: {provider}")

    prov = _providers[provider]
    if not prov.is_authenticated():
        raise HTTPException(status_code=401, detail="Not connected")

    try:
        success = await prov.delete_file(file_id)
        if success:
            return {"success": True}
        else:
            raise HTTPException(status_code=404, detail="File not found or delete failed")
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/cloud/share/{provider}/{file_id}")
async def get_share_link(provider: str, file_id: str):
    """Get a shareable link for a cloud file."""
    if provider not in _providers:
        raise HTTPException(status_code=400, detail=f"Unknown provider: {provider}")

    prov = _providers[provider]
    if not prov.is_authenticated():
        raise HTTPException(status_code=401, detail="Not connected")

    try:
        link = await prov.get_share_link(file_id)
        return {"link": link}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
