"""User-friendly API with Kafka integration and enhanced task management."""

import logging
import time
from datetime import datetime
from typing import List, Optional, Dict, Any
from fastapi import FastAPI, HTTPException, Query, Path, BackgroundTasks
from fastapi.responses import JSONResponse
from fastapi.middleware.cors import CORSMiddleware
from contextlib import asynccontextmanager

from src.models.task import (
    ScrapeTaskRequest, BulkScrapeTaskRequest, TaskResponse, TaskResult,
    TaskStats, TaskStatus, TaskPriority, TaskListResponse, QueueStats
)
from src.services.task_manager import task_manager
from src.services.kafka_service import kafka_service
from src.services.database import db_service
from src.services.cache_service import cache_service
from src.config.settings import LOG_LEVEL, LOG_FORMAT

# Configure logging
logging.basicConfig(level=getattr(logging, LOG_LEVEL), format=LOG_FORMAT)
logger = logging.getLogger(__name__)

@asynccontextmanager
async def lifespan(app: FastAPI):
    """Application lifespan manager."""
    logger.info("🚀 Starting User-Friendly Scraper API...")
    
    # Initialize services
    try:
        await db_service.connect()
        logger.info("✅ Database connected")
    except Exception as e:
        logger.warning(f"⚠️ Database connection failed: {e}")
    
    try:
        cache_service.connect()
        logger.info("✅ Cache connected")
    except Exception as e:
        logger.warning(f"⚠️ Cache connection failed: {e}")
    
    logger.info("🎉 User-Friendly Scraper API started successfully!")
    
    yield
    
    logger.info("🔄 Shutting down...")
    task_manager.close()
    try:
        await db_service.disconnect()
        cache_service.disconnect()
    except:
        pass
    logger.info("✅ Shutdown complete")

app = FastAPI(
    title="🔍 User-Friendly Web Scraper API",
    description="Easy-to-use web scraping API with Kafka task management and real-time statistics",
    version="4.0.0",
    lifespan=lifespan
)

# Add CORS middleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# ================================
# 📊 DASHBOARD & STATUS ENDPOINTS
# ================================

@app.get("/")
async def dashboard():
    """📊 Main dashboard with system overview."""
    queue_stats = task_manager.get_queue_stats()
    
    return {
        "🌟 welcome": "User-Friendly Web Scraper API",
        "🔥 version": "4.0.0",
        "📈 status": "operational",
        "🎯 features": [
            "🚀 Kafka-powered task queue",
            "📊 Real-time task tracking",
            "🔄 Bulk scraping support",
            "📱 User-friendly interface",
            "⚡ Multi-engine parallel scraping",
            "💾 Advanced caching",
            "📈 Comprehensive statistics"
        ],
        "📊 current_stats": {
            "📝 total_tasks": queue_stats.total_tasks,
            "⏳ pending_tasks": queue_stats.pending_tasks,
            "🔄 processing_tasks": queue_stats.processing_tasks,
            "✅ completed_tasks": queue_stats.completed_tasks,
            "❌ failed_tasks": queue_stats.failed_tasks,
            "👥 active_workers": queue_stats.active_workers,
            "⚡ throughput_per_minute": queue_stats.throughput_per_minute
        },
        "🔧 available_engines": ["google", "bing", "duckduckgo", "yandex", "baidu"],
        "🌐 endpoints": {
            "🔍 quick_search": "/search/quick",
            "📝 submit_task": "/tasks/submit",
            "📊 task_status": "/tasks/{task_id}/status",
            "📈 queue_stats": "/queue/stats",
            "👤 user_dashboard": "/users/{user_id}/dashboard"
        }
    }

@app.get("/health")
async def health_check():
    """🏥 Enhanced health check."""
    services = {
        "task_manager": True,
        "kafka_producer": kafka_service.healthy if kafka_service else False,
        "database": db_service.client is not None,
        "cache": cache_service.connected if cache_service else False,
    }
    
    status = "🟢 healthy" if all(services.values()) else "🟡 degraded"
    
    return {
        "status": status,
        "services": services,
        "timestamp": datetime.utcnow().isoformat(),
        "uptime": "Running smoothly! 🚀"
    }

# ================================
# 🔍 QUICK SEARCH ENDPOINTS
# ================================

@app.get("/search/quick")
async def quick_search(
    query: str = Query(..., description="🔍 What do you want to search for?"),
    engines: List[str] = Query(["bing"], description="🔧 Which engines to use?"),
    max_results: int = Query(5, ge=1, le=50, description="📊 How many results per engine?"),
    user_id: Optional[str] = Query(None, description="👤 Your user ID (optional)")
):
    """🚀 Quick search - Get results fast without task management."""
    try:
        from src.models.schemas import ScrapeRequest
        from src.scrapers.multi_engine_manager import multi_engine_manager
        
        start_time = time.time()
        
        # Create request
        request = ScrapeRequest(
            query=query,
            engines=engines,
            max_results=max_results
        )
        
        # Execute search
        results = await multi_engine_manager.scrape_multiple_engines_parallel(request)
        execution_time = time.time() - start_time
        
        # Format results
        formatted_results = []
        for result in results:
            formatted_results.append({
                "title": result.title,
                "url": result.url,
                "description": result.description,
                "engine": result.engine,
                "position": result.position,
                "timestamp": result.timestamp.isoformat()
            })
        
        return {
            "🔍 query": query,
            "🔧 engines_used": engines,
            "📊 total_results": len(formatted_results),
            "⏱️ execution_time": f"{execution_time:.2f}s",
            "📈 results": formatted_results,
            "✨ message": f"Found {len(formatted_results)} results in {execution_time:.2f} seconds!"
        }
        
    except Exception as e:
        logger.error(f"Quick search error: {e}")
        raise HTTPException(status_code=500, detail=f"Search failed: {str(e)}")

# ================================
# 📝 TASK MANAGEMENT ENDPOINTS
# ================================

@app.post("/tasks/submit")
async def submit_task(
    request: ScrapeTaskRequest,
    user_id: Optional[str] = Query(None, description="👤 Your user ID")
) -> TaskResponse:
    """📝 Submit a new scraping task to the queue."""
    try:
        response = await task_manager.submit_scrape_task(request, user_id)
        
        return {
            "🎯 task_id": response.task_id,
            "📊 status": response.status,
            "💬 message": response.message,
            "⏰ created_at": response.created_at.isoformat(),
            "📍 queue_position": response.queue_position,
            "⏳ estimated_completion": "2-5 minutes",
            "🔗 status_url": f"/tasks/{response.task_id}/status",
            "✨ tip": "Use the status URL to track your task progress!"
        }
        
    except Exception as e:
        logger.error(f"Task submission error: {e}")
        raise HTTPException(status_code=500, detail=f"Failed to submit task: {str(e)}")

@app.post("/tasks/bulk")
async def submit_bulk_task(
    request: BulkScrapeTaskRequest,
    user_id: Optional[str] = Query(None, description="👤 Your user ID")
) -> TaskResponse:
    """📝 Submit a bulk scraping task for multiple queries."""
    try:
        response = await task_manager.submit_bulk_scrape_task(request, user_id)
        
        return {
            "🎯 task_id": response.task_id,
            "📊 status": response.status,
            "💬 message": response.message,
            "📝 queries_count": len(request.queries),
            "⏰ created_at": response.created_at.isoformat(),
            "📍 queue_position": response.queue_position,
            "⏳ estimated_completion": f"{len(request.queries) * 2}-{len(request.queries) * 5} minutes",
            "🔗 status_url": f"/tasks/{response.task_id}/status",
            "✨ tip": "Bulk tasks process multiple queries efficiently!"
        }
        
    except Exception as e:
        logger.error(f"Bulk task submission error: {e}")
        raise HTTPException(status_code=500, detail=f"Failed to submit bulk task: {str(e)}")

@app.get("/tasks/{task_id}/status")
async def get_task_status(
    task_id: str = Path(..., description="🎯 Task ID to check")
):
    """📊 Get detailed task status and progress."""
    task_stats = task_manager.get_task_status(task_id)
    
    if not task_stats:
        raise HTTPException(status_code=404, detail="Task not found")
    
    # Calculate progress indicators
    status_emoji = {
        TaskStatus.PENDING: "⏳",
        TaskStatus.QUEUED: "📋",
        TaskStatus.PROCESSING: "🔄",
        TaskStatus.COMPLETED: "✅",
        TaskStatus.FAILED: "❌",
        TaskStatus.CANCELLED: "🚫"
    }
    
    response = {
        "🎯 task_id": task_id,
        "📊 status": f"{status_emoji.get(task_stats.status, '❓')} {task_stats.status}",
        "📈 progress": f"{task_stats.progress_percentage:.1f}%",
        "⏰ created_at": task_stats.created_at.isoformat(),
        "🔢 total_results": task_stats.total_results,
        "✅ successful_engines": task_stats.successful_engines,
        "❌ failed_engines": task_stats.failed_engines,
        "🔄 retry_count": task_stats.retry_count,
        "📊 engine_stats": task_stats.engine_stats
    }
    
    if task_stats.started_at:
        response["🏁 started_at"] = task_stats.started_at.isoformat()
    
    if task_stats.completed_at:
        response["🎉 completed_at"] = task_stats.completed_at.isoformat()
    
    if task_stats.execution_time:
        response["⏱️ execution_time"] = f"{task_stats.execution_time:.2f}s"
    
    if task_stats.last_error:
        response["⚠️ last_error"] = task_stats.last_error
    
    # Add helpful messages
    if task_stats.status == TaskStatus.COMPLETED:
        response["💬 message"] = "Task completed successfully! 🎉"
        response["🔗 results_url"] = f"/tasks/{task_id}/results"
    elif task_stats.status == TaskStatus.PROCESSING:
        response["💬 message"] = "Task is being processed... 🔄"
    elif task_stats.status == TaskStatus.QUEUED:
        response["💬 message"] = "Task is queued and waiting to be processed 📋"
    elif task_stats.status == TaskStatus.FAILED:
        response["💬 message"] = "Task failed ❌ Check the error details"
    
    return response

@app.get("/tasks/{task_id}/results")
async def get_task_results(
    task_id: str = Path(..., description="🎯 Task ID to get results for")
):
    """📊 Get task results with formatted output."""
    task_result = task_manager.get_task_result(task_id)
    
    if not task_result:
        raise HTTPException(status_code=404, detail="Task results not found")
    
    if task_result.status != TaskStatus.COMPLETED:
        raise HTTPException(status_code=400, detail="Task is not completed yet")
    
    return {
        "🎯 task_id": task_id,
        "🔍 query": task_result.query,
        "📊 status": "✅ Completed",
        "🔧 engines_used": task_result.engines_used,
        "📈 total_results": task_result.total_results,
        "⏱️ execution_time": f"{task_result.execution_time:.2f}s",
        "⏰ completed_at": task_result.completed_at.isoformat(),
        "📊 results": task_result.results,
        "📈 statistics": {
            "📝 total_results": task_result.total_results,
            "🔧 engines_used": len(task_result.engines_used),
            "⏱️ execution_time": f"{task_result.execution_time:.2f}s",
            "✅ successful_engines": task_result.stats.successful_engines,
            "❌ failed_engines": task_result.stats.failed_engines
        },
        "💡 tip": "Results are sorted by engine and position!"
    }

@app.post("/tasks/{task_id}/cancel")
async def cancel_task(
    task_id: str = Path(..., description="🎯 Task ID to cancel")
):
    """🚫 Cancel a pending or queued task."""
    success = task_manager.cancel_task(task_id)
    
    if success:
        return {
            "🎯 task_id": task_id,
            "📊 status": "🚫 Cancelled",
            "💬 message": "Task cancelled successfully",
            "⏰ cancelled_at": datetime.utcnow().isoformat()
        }
    else:
        raise HTTPException(status_code=400, detail="Task cannot be cancelled (not found or already processed)")

# ================================
# 📊 QUEUE & STATISTICS ENDPOINTS
# ================================

@app.get("/queue/stats")
async def get_queue_stats():
    """📊 Get comprehensive queue statistics."""
    stats = task_manager.get_queue_stats()
    
    return {
        "📊 queue_overview": {
            "📝 total_tasks": stats.total_tasks,
            "⏳ pending_tasks": stats.pending_tasks,
            "🔄 processing_tasks": stats.processing_tasks,
            "✅ completed_tasks": stats.completed_tasks,
            "❌ failed_tasks": stats.failed_tasks,
            "📏 current_queue_size": stats.queue_size,
            "👥 active_workers": stats.active_workers
        },
        "📈 performance_metrics": {
            "⏱️ average_processing_time": f"{stats.average_processing_time:.2f}s",
            "🚀 throughput_per_minute": f"{stats.throughput_per_minute:.1f}",
            "📊 success_rate": f"{(stats.completed_tasks / max(stats.total_tasks, 1)) * 100:.1f}%",
            "⚡ efficiency": "High" if stats.throughput_per_minute > 10 else "Medium"
        },
        "🎯 system_health": {
            "🟢 status": "Healthy" if stats.failed_tasks < stats.completed_tasks else "Degraded",
            "📱 kafka_connected": kafka_service.healthy if kafka_service else False,
            "💾 cache_available": cache_service.connected if cache_service else False
        }
    }

@app.get("/queue/live")
async def get_live_queue():
    """🔴 Get live queue status (real-time data)."""
    # This would typically connect to a real-time stream
    stats = task_manager.get_queue_stats()
    
    return {
        "🔴 live_status": "Active",
        "⏰ timestamp": datetime.utcnow().isoformat(),
        "📊 current_queue": {
            "⏳ pending": stats.pending_tasks,
            "🔄 processing": stats.processing_tasks,
            "👥 workers": stats.active_workers
        },
        "📈 real_time_metrics": {
            "🚀 tasks_per_minute": stats.throughput_per_minute,
            "⏱️ avg_processing_time": f"{stats.average_processing_time:.2f}s",
            "📊 queue_health": "🟢 Healthy" if stats.pending_tasks < 100 else "🟡 Busy"
        }
    }

# ================================
# 👤 USER DASHBOARD ENDPOINTS
# ================================

@app.get("/users/{user_id}/dashboard")
async def get_user_dashboard(
    user_id: str = Path(..., description="👤 User ID"),
    page: int = Query(1, ge=1, description="📄 Page number"),
    page_size: int = Query(10, ge=1, le=50, description="📊 Items per page")
):
    """👤 Get user dashboard with task history and statistics."""
    try:
        # Get user tasks
        user_tasks = task_manager.get_user_tasks(user_id, page, page_size)
        
        # Calculate user statistics
        total_tasks = len(user_tasks)
        completed_tasks = sum(1 for task in user_tasks if task.status == TaskStatus.COMPLETED)
        failed_tasks = sum(1 for task in user_tasks if task.status == TaskStatus.FAILED)
        total_results = sum(task.total_results for task in user_tasks)
        
        # Recent activity
        recent_tasks = sorted(user_tasks, key=lambda x: x.created_at, reverse=True)[:5]
        
        return {
            "👤 user_id": user_id,
            "📊 overview": {
                "📝 total_tasks": total_tasks,
                "✅ completed_tasks": completed_tasks,
                "❌ failed_tasks": failed_tasks,
                "🎯 success_rate": f"{(completed_tasks / max(total_tasks, 1)) * 100:.1f}%",
                "📈 total_results": total_results,
                "⏰ last_activity": recent_tasks[0].created_at.isoformat() if recent_tasks else None
            },
            "🔥 recent_tasks": [
                {
                    "🎯 task_id": task.task_id,
                    "📊 status": task.status,
                    "📈 results": task.total_results,
                    "⏰ created": task.created_at.isoformat(),
                    "⏱️ execution_time": f"{task.execution_time:.2f}s" if task.execution_time else "N/A"
                }
                for task in recent_tasks
            ],
            "📄 pagination": {
                "📍 current_page": page,
                "📊 page_size": page_size,
                "📝 total_tasks": total_tasks,
                "📄 total_pages": (total_tasks + page_size - 1) // page_size
            }
        }
        
    except Exception as e:
        logger.error(f"User dashboard error: {e}")
        raise HTTPException(status_code=500, detail=f"Failed to get user dashboard: {str(e)}")

# ================================
# 🔧 ADMIN & MAINTENANCE ENDPOINTS
# ================================

@app.post("/admin/cleanup")
async def cleanup_old_tasks(
    days: int = Query(7, ge=1, le=30, description="🗓️ Days to keep tasks"),
    background_tasks: BackgroundTasks = None
):
    """🧹 Clean up old tasks (admin only)."""
    def cleanup():
        task_manager.cleanup_old_tasks(days)
    
    if background_tasks:
        background_tasks.add_task(cleanup)
    else:
        cleanup()
    
    return {
        "💬 message": f"Cleanup initiated for tasks older than {days} days",
        "⏰ timestamp": datetime.utcnow().isoformat(),
        "🧹 status": "In progress"
    }

@app.get("/admin/system-info")
async def get_system_info():
    """🔧 Get detailed system information (admin only)."""
    queue_stats = task_manager.get_queue_stats()
    
    return {
        "🖥️ system_info": {
            "🚀 api_version": "4.0.0",
            "⏰ uptime": "Running smoothly",
            "📊 queue_stats": queue_stats,
            "🔧 kafka_info": kafka_service.get_topic_info() if kafka_service else None,
            "💾 cache_info": cache_service.get_cache_stats() if cache_service else None
        },
        "📈 performance": {
            "🚀 throughput": f"{queue_stats.throughput_per_minute:.1f} tasks/min",
            "⏱️ avg_processing": f"{queue_stats.average_processing_time:.2f}s",
            "📊 success_rate": f"{(queue_stats.completed_tasks / max(queue_stats.total_tasks, 1)) * 100:.1f}%"
        }
    }

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)
