"""
FastAPI application for Google Alerts Reporter Web UI
"""
import logging
from pathlib import Path
from datetime import datetime
from typing import Optional, List, Dict
import json

from fastapi import FastAPI, Depends, HTTPException, Request
from fastapi.responses import HTMLResponse, FileResponse, JSONResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from fastapi.middleware.cors import CORSMiddleware
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address
from slowapi.errors import RateLimitExceeded

from .config import settings
from .auth import get_current_user
from .gmail_client import GmailClient
from .grok_analyzer import GrokAnalyzer
from .report_generator import ReportGenerator
from .notifications import NotificationManager
from .historical import HistoricalData

# Configure logging
logging.basicConfig(
    level=getattr(logging, settings.log_level),
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler(settings.log_file),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

# Initialize FastAPI app
app = FastAPI(
    title=settings.app_name,
    version=settings.app_version,
    description="Automated crisis analysis from Google Alerts",
    docs_url="/api/docs" if settings.debug else None,
    redoc_url="/api/redoc" if settings.debug else None
)

# Rate limiter
limiter = Limiter(key_func=get_remote_address)
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)

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

# Static files and templates
app.mount("/static", StaticFiles(directory="static"), name="static")
templates = Jinja2Templates(directory="templates")

# Initialize services
gmail_client = GmailClient()
grok_analyzer = GrokAnalyzer()
report_generator = ReportGenerator()
notification_manager = NotificationManager()
historical_data = HistoricalData() if settings.enable_historical else None

# In-memory cache for latest analysis (simple caching)
latest_analysis_cache = {
    "timestamp": None,
    "data": None
}


@app.on_event("startup")
async def startup_event():
    """Run on application startup."""
    logger.info(f"Starting {settings.app_name} v{settings.app_version}")
    logger.info(f"Debug mode: {settings.debug}")
    logger.info(f"Search query: {settings.search_query}")

    # Authenticate Gmail on startup
    if gmail_client.authenticate():
        logger.info("Gmail authentication successful on startup")
    else:
        logger.warning("Gmail authentication failed on startup - will retry on first request")


@app.on_event("shutdown")
async def shutdown_event():
    """Run on application shutdown."""
    logger.info("Shutting down application")


@app.get("/", response_class=HTMLResponse)
async def dashboard(
    request: Request,
    username: str = Depends(get_current_user)
):
    """
    Main dashboard page.

    Args:
        request: FastAPI request object
        username: Authenticated username

    Returns:
        HTML dashboard page
    """
    logger.info(f"User {username} accessed dashboard")

    # Get latest analysis from cache if available
    cached_data = latest_analysis_cache.get("data")

    return templates.TemplateResponse(
        "dashboard.html",
        {
            "request": request,
            "settings": settings,
            "username": username,
            "cached_data": cached_data,
            "cache_timestamp": latest_analysis_cache.get("timestamp")
        }
    )


@app.post("/api/refresh")
@limiter.limit(f"{settings.rate_limit_per_minute}/minute")
async def refresh_analysis(
    request: Request,
    username: str = Depends(get_current_user)
):
    """
    Fetch new alerts and perform analysis.

    Args:
        request: FastAPI request object
        username: Authenticated username

    Returns:
        JSON with analysis results
    """
    logger.info(f"User {username} requested analysis refresh")

    try:
        # Step 1: Authenticate Gmail (if not already)
        if not gmail_client.service:
            logger.info("Authenticating with Gmail API")
            if not gmail_client.authenticate():
                raise HTTPException(
                    status_code=500,
                    detail="Failed to authenticate with Gmail API"
                )

        # Step 2: Fetch alerts
        logger.info("Fetching Google Alerts emails")
        alerts_data = gmail_client.fetch_alerts()

        if not alerts_data:
            return JSONResponse(
                status_code=200,
                content={
                    "success": True,
                    "message": "No alerts found",
                    "data": {
                        "total_items": 0,
                        "sentiments": {"neg": 0, "pos": 0, "neu": 0},
                        "negative_items": []
                    }
                }
            )

        # Step 3: Extract all items
        all_items = [item for alert in alerts_data for item in alert['items']]
        logger.info(f"Extracted {len(all_items)} total alerts")

        # Step 4: Analyze sentiment
        logger.info("Analyzing sentiment")
        sentiments, analyzed_items = grok_analyzer.analyze_batch(all_items)

        # Step 5: Get top negatives
        negative_items = grok_analyzer.get_negative_items(analyzed_items, limit=10)

        # Step 6: Prepare response
        response_data = {
            "total_items": len(all_items),
            "sentiments": sentiments,
            "negative_items": negative_items,
            "alerts_data": alerts_data,
            "analyzed_items": analyzed_items
        }

        # Update cache
        latest_analysis_cache["data"] = response_data
        latest_analysis_cache["timestamp"] = datetime.now().isoformat()

        # Step 7: Save to historical data
        if historical_data:
            try:
                historical_data.save_analysis(
                    sentiments=sentiments,
                    total_items=len(all_items)
                )
                logger.info("Historical data saved successfully")
            except Exception as e:
                logger.error(f"Failed to save historical data: {e}")

        # Step 8: Send notifications if thresholds are met
        notification_results = {}
        try:
            notification_results = notification_manager.send_crisis_alert(
                sentiments=sentiments,
                total_items=len(all_items),
                negative_items=negative_items
            )
            if notification_results:
                logger.info(f"Notifications sent: {notification_results}")
        except Exception as e:
            logger.error(f"Failed to send notifications: {e}")

        logger.info("Analysis refresh completed successfully")

        return JSONResponse(
            status_code=200,
            content={
                "success": True,
                "message": "Analysis completed",
                "data": response_data,
                "timestamp": latest_analysis_cache["timestamp"],
                "notifications_sent": notification_results
            }
        )

    except Exception as e:
        logger.error(f"Error during analysis refresh: {e}", exc_info=True)
        raise HTTPException(
            status_code=500,
            detail=f"Analysis failed: {str(e)}"
        )


@app.post("/api/report/html")
async def generate_html_report(
    request: Request,
    username: str = Depends(get_current_user)
):
    """
    Generate and download HTML report.

    Args:
        request: FastAPI request object
        username: Authenticated username

    Returns:
        HTML report file
    """
    logger.info(f"User {username} requested HTML report")

    cached_data = latest_analysis_cache.get("data")
    if not cached_data:
        raise HTTPException(
            status_code=400,
            detail="No analysis data available. Please refresh analysis first."
        )

    try:
        filepath = report_generator.save_html_report(
            sentiments=cached_data["sentiments"],
            total_items=cached_data["total_items"],
            negative_items=cached_data["negative_items"]
        )

        return FileResponse(
            path=filepath,
            filename=filepath.name,
            media_type="text/html"
        )

    except Exception as e:
        logger.error(f"Error generating HTML report: {e}", exc_info=True)
        raise HTTPException(
            status_code=500,
            detail=f"Failed to generate HTML report: {str(e)}"
        )


@app.post("/api/report/pdf")
async def generate_pdf_report(
    request: Request,
    username: str = Depends(get_current_user)
):
    """
    Generate and download PDF report.

    Args:
        request: FastAPI request object
        username: Authenticated username

    Returns:
        PDF report file
    """
    logger.info(f"User {username} requested PDF report")

    cached_data = latest_analysis_cache.get("data")
    if not cached_data:
        raise HTTPException(
            status_code=400,
            detail="No analysis data available. Please refresh analysis first."
        )

    try:
        filepath = report_generator.generate_pdf_report(
            sentiments=cached_data["sentiments"],
            total_items=cached_data["total_items"],
            negative_items=cached_data["negative_items"]
        )

        return FileResponse(
            path=filepath,
            filename=filepath.name,
            media_type="application/pdf"
        )

    except Exception as e:
        logger.error(f"Error generating PDF report: {e}", exc_info=True)
        raise HTTPException(
            status_code=500,
            detail=f"Failed to generate PDF report: {str(e)}"
        )


@app.get("/api/deindex")
async def get_deindex_urls(
    username: str = Depends(get_current_user)
):
    """
    Get list of Reclame Aqui URLs for deindexing.

    Args:
        username: Authenticated username

    Returns:
        JSON with list of URLs
    """
    logger.info(f"User {username} requested deindex URLs")

    cached_data = latest_analysis_cache.get("data")
    if not cached_data:
        return JSONResponse(
            status_code=200,
            content={
                "success": True,
                "urls": [],
                "message": "No analysis data available"
            }
        )

    try:
        reclameaqui_urls = gmail_client.get_reclameaqui_urls(
            cached_data.get("alerts_data", [])
        )

        return JSONResponse(
            status_code=200,
            content={
                "success": True,
                "urls": reclameaqui_urls,
                "count": len(reclameaqui_urls),
                "search_console_url": f"https://search.google.com/search-console/removals"
            }
        )

    except Exception as e:
        logger.error(f"Error getting deindex URLs: {e}", exc_info=True)
        raise HTTPException(
            status_code=500,
            detail=f"Failed to get URLs: {str(e)}"
        )


@app.get("/api/status")
async def get_status(
    username: str = Depends(get_current_user)
):
    """
    Get application status.

    Args:
        username: Authenticated username

    Returns:
        JSON with status information
    """
    return JSONResponse(
        status_code=200,
        content={
            "app_name": settings.app_name,
            "version": settings.app_version,
            "status": "running",
            "gmail_authenticated": gmail_client.service is not None,
            "grok_api_enabled": not grok_analyzer.use_mock,
            "cache_available": latest_analysis_cache.get("data") is not None,
            "cache_timestamp": latest_analysis_cache.get("timestamp"),
            "search_query": settings.search_query,
            "auto_refresh_interval": settings.auto_refresh_interval
        }
    )


@app.get("/health")
async def health_check():
    """Health check endpoint (no auth required)."""
    return {"status": "healthy", "version": settings.app_version}


@app.get("/api/historical")
async def get_historical_data(
    days: Optional[int] = None,
    username: str = Depends(get_current_user)
):
    """
    Get historical analysis data.

    Args:
        days: Number of days to retrieve (defaults to settings)
        username: Authenticated username

    Returns:
        JSON with historical data
    """
    logger.info(f"User {username} requested historical data (days={days})")

    if not historical_data:
        raise HTTPException(
            status_code=400,
            detail="Historical data tracking is disabled"
        )

    try:
        history = historical_data.get_history(days)
        summary = historical_data.get_summary(days)

        return JSONResponse(
            status_code=200,
            content={
                "success": True,
                "history": history,
                "summary": summary
            }
        )

    except Exception as e:
        logger.error(f"Error retrieving historical data: {e}", exc_info=True)
        raise HTTPException(
            status_code=500,
            detail=f"Failed to retrieve historical data: {str(e)}"
        )


@app.get("/api/historical/chart")
async def get_historical_chart_data(
    days: Optional[int] = None,
    username: str = Depends(get_current_user)
):
    """
    Get historical data formatted for Chart.js.

    Args:
        days: Number of days to retrieve
        username: Authenticated username

    Returns:
        JSON with Chart.js compatible data
    """
    logger.info(f"User {username} requested historical chart data (days={days})")

    if not historical_data:
        raise HTTPException(
            status_code=400,
            detail="Historical data tracking is disabled"
        )

    try:
        chart_data = historical_data.get_chart_data(days)

        return JSONResponse(
            status_code=200,
            content={
                "success": True,
                "chart_data": chart_data
            }
        )

    except Exception as e:
        logger.error(f"Error retrieving chart data: {e}", exc_info=True)
        raise HTTPException(
            status_code=500,
            detail=f"Failed to retrieve chart data: {str(e)}"
        )


@app.post("/api/send-daily-report")
async def send_daily_report(
    request: Request,
    username: str = Depends(get_current_user)
):
    """
    Generate and send daily report via email.

    Args:
        request: FastAPI request object
        username: Authenticated username

    Returns:
        JSON with send status
    """
    logger.info(f"User {username} triggered daily report send")

    if not settings.email_enabled:
        raise HTTPException(
            status_code=400,
            detail="Email notifications are disabled"
        )

    cached_data = latest_analysis_cache.get("data")
    if not cached_data:
        raise HTTPException(
            status_code=400,
            detail="No analysis data available. Please refresh analysis first."
        )

    try:
        # Generate PDF report
        pdf_path = report_generator.generate_pdf_report(
            sentiments=cached_data["sentiments"],
            total_items=cached_data["total_items"],
            negative_items=cached_data["negative_items"]
        )

        # Send via email
        result = notification_manager.send_daily_report(
            sentiments=cached_data["sentiments"],
            total_items=cached_data["total_items"],
            negative_items=cached_data["negative_items"],
            pdf_path=pdf_path
        )

        if result:
            logger.info("Daily report sent successfully")
            return JSONResponse(
                status_code=200,
                content={
                    "success": True,
                    "message": "Daily report sent successfully"
                }
            )
        else:
            raise HTTPException(
                status_code=500,
                detail="Failed to send daily report"
            )

    except Exception as e:
        logger.error(f"Error sending daily report: {e}", exc_info=True)
        raise HTTPException(
            status_code=500,
            detail=f"Failed to send daily report: {str(e)}"
        )


@app.post("/api/notifications/test")
async def test_notifications(
    request: Request,
    username: str = Depends(get_current_user)
):
    """
    Test notification delivery for all enabled channels.

    Args:
        request: FastAPI request object
        username: Authenticated username

    Returns:
        JSON with test results for each channel
    """
    logger.info(f"User {username} requested notification test")

    try:
        # Test data
        test_sentiments = {"neg": 15, "pos": 5, "neu": 5}
        test_total = 25
        test_negative_items = [
            {
                "title": "Test Alert 1",
                "url": "https://example.com/1",
                "source": "Test Source",
                "sentiment": "neg",
                "confidence": 0.95
            },
            {
                "title": "Test Alert 2",
                "url": "https://example.com/2",
                "source": "Test Source",
                "sentiment": "neg",
                "confidence": 0.88
            }
        ]

        # Send test notifications
        results = notification_manager.send_crisis_alert(
            sentiments=test_sentiments,
            total_items=test_total,
            negative_items=test_negative_items
        )

        logger.info(f"Notification test results: {results}")

        return JSONResponse(
            status_code=200,
            content={
                "success": True,
                "message": "Notification test completed",
                "results": results,
                "channels_tested": {
                    "email": settings.email_enabled,
                    "whatsapp": settings.whatsapp_enabled,
                    "slack": settings.slack_enabled
                }
            }
        )

    except Exception as e:
        logger.error(f"Error testing notifications: {e}", exc_info=True)
        raise HTTPException(
            status_code=500,
            detail=f"Notification test failed: {str(e)}"
        )


# Error handlers
@app.exception_handler(404)
async def not_found_handler(request: Request, exc):
    """Handle 404 errors."""
    return JSONResponse(
        status_code=404,
        content={"detail": "Not found"}
    )


@app.exception_handler(500)
async def internal_error_handler(request: Request, exc):
    """Handle 500 errors."""
    logger.error(f"Internal server error: {exc}", exc_info=True)
    return JSONResponse(
        status_code=500,
        content={"detail": "Internal server error"}
    )


if __name__ == "__main__":
    import uvicorn

    uvicorn.run(
        "app.main:app",
        host=settings.host,
        port=settings.port,
        reload=settings.debug,
        log_level=settings.log_level.lower()
    )
