"""
Easynews Router

Handles Easynews integration:
- Configuration management (credentials, proxy settings)
- Search term management
- Manual check triggers
- Results browsing and downloads
"""

import asyncio
from concurrent.futures import ThreadPoolExecutor
from datetime import datetime
from typing import Dict, List, Optional

from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Request
from pydantic import BaseModel
from slowapi import Limiter
from slowapi.util import get_remote_address

from ..core.dependencies import get_current_user, require_admin, get_app_state
from ..core.exceptions import handle_exceptions
from modules.universal_logger import get_logger

logger = get_logger('API')

router = APIRouter(prefix="/api/easynews", tags=["Easynews"])
limiter = Limiter(key_func=get_remote_address)

# Thread pool for blocking operations
_executor = ThreadPoolExecutor(max_workers=2)


# ============================================================================
# PYDANTIC MODELS
# ============================================================================

class EasynewsConfigUpdate(BaseModel):
    username: Optional[str] = None
    password: Optional[str] = None
    enabled: Optional[bool] = None
    check_interval_hours: Optional[int] = None
    auto_download: Optional[bool] = None
    min_quality: Optional[str] = None
    proxy_enabled: Optional[bool] = None
    proxy_type: Optional[str] = None
    proxy_host: Optional[str] = None
    proxy_port: Optional[int] = None
    proxy_username: Optional[str] = None
    proxy_password: Optional[str] = None
    notifications_enabled: Optional[bool] = None


# ============================================================================
# HELPER FUNCTIONS
# ============================================================================

def _get_monitor():
    """Get the Easynews monitor instance."""
    from modules.easynews_monitor import EasynewsMonitor
    app_state = get_app_state()
    db_path = str(app_state.db.db_path)  # Convert Path to string
    return EasynewsMonitor(db_path)


# ============================================================================
# CONFIGURATION ENDPOINTS
# ============================================================================

@router.get("/config")
@limiter.limit("30/minute")
@handle_exceptions
async def get_config(
    request: Request,
    current_user: Dict = Depends(get_current_user)
):
    """Get Easynews configuration (passwords masked)."""
    monitor = _get_monitor()
    config = monitor.get_config()

    # Mask password for security
    if config.get('password'):
        config['password'] = '********'
    if config.get('proxy_password'):
        config['proxy_password'] = '********'

    return {
        "success": True,
        "config": config
    }


@router.put("/config")
@limiter.limit("10/minute")
@handle_exceptions
async def update_config(
    request: Request,
    config: EasynewsConfigUpdate,
    current_user: Dict = Depends(require_admin)
):
    """Update Easynews configuration."""
    monitor = _get_monitor()

    # Build update kwargs
    kwargs = {}
    if config.username is not None:
        kwargs['username'] = config.username
    if config.password is not None and config.password != '********':
        kwargs['password'] = config.password
    if config.enabled is not None:
        kwargs['enabled'] = config.enabled
    if config.check_interval_hours is not None:
        kwargs['check_interval_hours'] = config.check_interval_hours
    if config.auto_download is not None:
        kwargs['auto_download'] = config.auto_download
    if config.min_quality is not None:
        kwargs['min_quality'] = config.min_quality
    if config.proxy_enabled is not None:
        kwargs['proxy_enabled'] = config.proxy_enabled
    if config.proxy_type is not None:
        kwargs['proxy_type'] = config.proxy_type
    if config.proxy_host is not None:
        kwargs['proxy_host'] = config.proxy_host
    if config.proxy_port is not None:
        kwargs['proxy_port'] = config.proxy_port
    if config.proxy_username is not None:
        kwargs['proxy_username'] = config.proxy_username
    if config.proxy_password is not None and config.proxy_password != '********':
        kwargs['proxy_password'] = config.proxy_password
    if config.notifications_enabled is not None:
        kwargs['notifications_enabled'] = config.notifications_enabled

    if not kwargs:
        return {"success": False, "message": "No updates provided"}

    success = monitor.update_config(**kwargs)

    return {
        "success": success,
        "message": "Configuration updated" if success else "Update failed"
    }


@router.post("/test")
@limiter.limit("5/minute")
@handle_exceptions
async def test_connection(
    request: Request,
    current_user: Dict = Depends(get_current_user)
):
    """Test Easynews connection with current credentials."""
    monitor = _get_monitor()

    loop = asyncio.get_event_loop()
    result = await loop.run_in_executor(_executor, monitor.test_connection)

    return result


# ============================================================================
# CELEBRITY ENDPOINTS (uses tracked celebrities from Appearances)
# ============================================================================

@router.get("/celebrities")
@limiter.limit("30/minute")
@handle_exceptions
async def get_celebrities(
    request: Request,
    current_user: Dict = Depends(get_current_user)
):
    """Get all tracked celebrities that will be searched on Easynews."""
    monitor = _get_monitor()
    celebrities = monitor.get_celebrities()

    return {
        "success": True,
        "celebrities": celebrities,
        "count": len(celebrities)
    }


# ============================================================================
# RESULTS ENDPOINTS
# ============================================================================

@router.get("/results")
@limiter.limit("30/minute")
@handle_exceptions
async def get_results(
    request: Request,
    status: Optional[str] = None,
    celebrity_id: Optional[int] = None,
    limit: int = 100,
    offset: int = 0,
    current_user: Dict = Depends(get_current_user)
):
    """Get discovered results with optional filters."""
    monitor = _get_monitor()
    results = monitor.get_results(
        status=status,
        celebrity_id=celebrity_id,
        limit=limit,
        offset=offset,
    )

    # Get total count
    total = monitor.get_result_count(status=status)

    return {
        "success": True,
        "results": results,
        "count": len(results),
        "total": total
    }


@router.post("/results/{result_id}/status")
@limiter.limit("30/minute")
@handle_exceptions
async def update_result_status(
    request: Request,
    result_id: int,
    status: str,
    current_user: Dict = Depends(get_current_user)
):
    """Update a result's status (e.g., mark as ignored)."""
    valid_statuses = ['new', 'downloaded', 'ignored', 'failed']
    if status not in valid_statuses:
        raise HTTPException(status_code=400, detail=f"Invalid status. Must be one of: {valid_statuses}")

    monitor = _get_monitor()
    success = monitor.update_result_status(result_id, status)

    return {
        "success": success,
        "message": f"Status updated to {status}" if success else "Update failed"
    }


@router.post("/results/{result_id}/download")
@limiter.limit("10/minute")
@handle_exceptions
async def download_result(
    request: Request,
    result_id: int,
    background_tasks: BackgroundTasks,
    current_user: Dict = Depends(get_current_user)
):
    """Start downloading a result."""
    monitor = _get_monitor()

    def do_download():
        return monitor.download_result(result_id)

    loop = asyncio.get_event_loop()
    result = await loop.run_in_executor(_executor, do_download)

    return result


# ============================================================================
# CHECK ENDPOINTS
# ============================================================================

@router.get("/status")
@limiter.limit("60/minute")
@handle_exceptions
async def get_status(
    request: Request,
    current_user: Dict = Depends(get_current_user)
):
    """Get current check status."""
    monitor = _get_monitor()
    status = monitor.get_status()
    config = monitor.get_config()
    celebrity_count = monitor.get_celebrity_count()

    return {
        "success": True,
        "status": status,
        "last_check": config.get('last_check'),
        "enabled": config.get('enabled', False),
        "has_credentials": config.get('has_credentials', False),
        "celebrity_count": celebrity_count,
    }


@router.post("/check")
@limiter.limit("5/minute")
@handle_exceptions
async def trigger_check(
    request: Request,
    background_tasks: BackgroundTasks,
    current_user: Dict = Depends(get_current_user)
):
    """Trigger a manual check for all tracked celebrities."""
    monitor = _get_monitor()
    status = monitor.get_status()

    if status.get('is_running'):
        return {
            "success": False,
            "message": "Check already in progress"
        }

    def do_check():
        return monitor.check_all_celebrities()

    loop = asyncio.get_event_loop()
    background_tasks.add_task(loop.run_in_executor, _executor, do_check)

    return {
        "success": True,
        "message": "Check started"
    }


@router.post("/check/{search_id}")
@limiter.limit("5/minute")
@handle_exceptions
async def trigger_single_check(
    request: Request,
    search_id: int,
    background_tasks: BackgroundTasks,
    current_user: Dict = Depends(get_current_user)
):
    """Trigger a manual check for a specific search term."""
    monitor = _get_monitor()
    status = monitor.get_status()

    if status.get('is_running'):
        return {
            "success": False,
            "message": "Check already in progress"
        }

    # Verify search exists
    search = monitor.get_search(search_id)
    if not search:
        raise HTTPException(status_code=404, detail="Search not found")

    def do_check():
        return monitor.check_single_search(search_id)

    loop = asyncio.get_event_loop()
    background_tasks.add_task(loop.run_in_executor, _executor, do_check)

    return {
        "success": True,
        "message": f"Check started for: {search['search_term']}"
    }


# ============================================================================
# SEARCH MANAGEMENT ENDPOINTS
# ============================================================================

class EasynewsSearchCreate(BaseModel):
    search_term: str
    media_type: Optional[str] = 'any'
    tmdb_id: Optional[int] = None
    tmdb_title: Optional[str] = None
    poster_url: Optional[str] = None


class EasynewsSearchUpdate(BaseModel):
    search_term: Optional[str] = None
    media_type: Optional[str] = None
    enabled: Optional[bool] = None
    tmdb_id: Optional[int] = None
    tmdb_title: Optional[str] = None
    poster_url: Optional[str] = None


@router.get("/searches")
@limiter.limit("30/minute")
@handle_exceptions
async def get_searches(
    request: Request,
    current_user: Dict = Depends(get_current_user)
):
    """Get all saved search terms."""
    monitor = _get_monitor()
    searches = monitor.get_all_searches()

    return {
        "success": True,
        "searches": searches,
        "count": len(searches)
    }


@router.post("/searches")
@limiter.limit("10/minute")
@handle_exceptions
async def add_search(
    request: Request,
    search: EasynewsSearchCreate,
    current_user: Dict = Depends(get_current_user)
):
    """Add a new search term."""
    monitor = _get_monitor()

    search_id = monitor.add_search(
        search_term=search.search_term,
        media_type=search.media_type,
        tmdb_id=search.tmdb_id,
        tmdb_title=search.tmdb_title,
        poster_url=search.poster_url
    )

    if search_id:
        return {
            "success": True,
            "id": search_id,
            "message": f"Search term '{search.search_term}' added"
        }
    else:
        return {
            "success": False,
            "message": "Failed to add search term"
        }


@router.put("/searches/{search_id}")
@limiter.limit("10/minute")
@handle_exceptions
async def update_search(
    request: Request,
    search_id: int,
    updates: EasynewsSearchUpdate,
    current_user: Dict = Depends(get_current_user)
):
    """Update an existing search term."""
    monitor = _get_monitor()

    # Build update kwargs
    kwargs = {}
    if updates.search_term is not None:
        kwargs['search_term'] = updates.search_term
    if updates.media_type is not None:
        kwargs['media_type'] = updates.media_type
    if updates.enabled is not None:
        kwargs['enabled'] = updates.enabled
    if updates.tmdb_id is not None:
        kwargs['tmdb_id'] = updates.tmdb_id
    if updates.tmdb_title is not None:
        kwargs['tmdb_title'] = updates.tmdb_title
    if updates.poster_url is not None:
        kwargs['poster_url'] = updates.poster_url

    if not kwargs:
        return {"success": False, "message": "No updates provided"}

    success = monitor.update_search(search_id, **kwargs)

    return {
        "success": success,
        "message": "Search updated" if success else "Update failed"
    }


@router.delete("/searches/{search_id}")
@limiter.limit("10/minute")
@handle_exceptions
async def delete_search(
    request: Request,
    search_id: int,
    current_user: Dict = Depends(get_current_user)
):
    """Delete a search term."""
    monitor = _get_monitor()
    success = monitor.delete_search(search_id)

    return {
        "success": success,
        "message": "Search deleted" if success else "Delete failed"
    }
