"""
Report routes for the sim-search API.

This module defines the routes for report generation and management.
"""

import os
from typing import Any, List, Optional
from fastapi import APIRouter, Depends, HTTPException, status, BackgroundTasks
from fastapi.responses import FileResponse
from sqlalchemy.orm import Session

from app.api.dependencies import get_current_active_user
from app.db.models import User, Report, Search
from app.db.session import get_db
from app.schemas.report import (
    ReportCreate, ReportUpdate, Report as ReportSchema,
    ReportList, ReportProgress, ReportDownload
)
from app.services.report_service import ReportService

router = APIRouter()
report_service = ReportService()

# Dictionary to store report generation progress
report_progress = {}


@router.post("/generate", response_model=ReportSchema)
async def generate_report(
    report_in: ReportCreate,
    background_tasks: BackgroundTasks,
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db),
) -> Any:
    """
    Generate a report from search results.
    
    Args:
        report_in: Report creation parameters
        background_tasks: FastAPI background tasks
        current_user: Current authenticated user
        db: Database session
        
    Returns:
        Generated report
    """
    try:
        # Check if search_id is provided and exists
        search = None
        if report_in.search_id:
            search = db.query(Search).filter(
                Search.id == report_in.search_id,
                Search.user_id == current_user.id
            ).first()
            
            if not search:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail="Search not found",
                )
        
        # Create report record
        title = report_in.title or f"Report: {report_in.query}"
        report = Report(
            user_id=current_user.id,
            search_id=report_in.search_id,
            title=title,
            content="Report generation in progress...",
            detail_level=report_in.detail_level or "standard",
            query_type=report_in.query_type,
            model_used=report_in.model,
        )
        
        db.add(report)
        db.commit()
        db.refresh(report)
        
        # Initialize progress tracking
        report_progress[report.id] = {
            "progress": 0.0,
            "status": "Initializing report generation...",
            "current_chunk": 0,
            "total_chunks": 0,
            "current_report": "Report generation in progress...",
        }
        
        # Generate report in background
        background_tasks.add_task(
            report_service.generate_report_background,
            report_id=report.id,
            report_in=report_in,
            search=search,
            db=db,
            progress_dict=report_progress,
        )
        
        return report
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error generating report: {str(e)}",
        )


@router.get("/list", response_model=ReportList)
async def list_reports(
    skip: int = 0,
    limit: int = 100,
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db),
) -> Any:
    """
    Get a list of user's reports.
    
    Args:
        skip: Number of records to skip
        limit: Maximum number of records to return
        current_user: Current authenticated user
        db: Database session
        
    Returns:
        List of reports
    """
    reports = db.query(Report).filter(Report.user_id == current_user.id).order_by(
        Report.created_at.desc()
    ).offset(skip).limit(limit).all()
    
    total = db.query(Report).filter(Report.user_id == current_user.id).count()
    
    return {"reports": reports, "total": total}


@router.get("/{report_id}", response_model=ReportSchema)
async def get_report(
    report_id: str,
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db),
) -> Any:
    """
    Get a specific report.
    
    Args:
        report_id: ID of the report
        current_user: Current authenticated user
        db: Database session
        
    Returns:
        Report
        
    Raises:
        HTTPException: If the report is not found or doesn't belong to the user
    """
    report = db.query(Report).filter(
        Report.id == report_id, Report.user_id == current_user.id
    ).first()
    
    if not report:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Report not found",
        )
    
    return report


@router.delete("/{report_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_report(
    report_id: str,
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db),
) -> None:
    """
    Delete a report.
    
    Args:
        report_id: ID of the report to delete
        current_user: Current authenticated user
        db: Database session
        
    Raises:
        HTTPException: If the report is not found or doesn't belong to the user
    """
    report = db.query(Report).filter(
        Report.id == report_id, Report.user_id == current_user.id
    ).first()
    
    if not report:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Report not found",
        )
    
    db.delete(report)
    db.commit()


@router.get("/{report_id}/progress", response_model=ReportProgress)
async def get_report_progress(
    report_id: str,
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db),
) -> Any:
    """
    Get the progress of a report generation.
    
    Args:
        report_id: ID of the report
        current_user: Current authenticated user
        db: Database session
        
    Returns:
        Report generation progress
        
    Raises:
        HTTPException: If the report is not found or doesn't belong to the user
    """
    # Check if report exists and belongs to user
    report = db.query(Report).filter(
        Report.id == report_id, Report.user_id == current_user.id
    ).first()
    
    if not report:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Report not found",
        )
    
    # Get progress from progress dictionary
    progress_data = report_progress.get(report_id, {
        "progress": 1.0,
        "status": "Report generation complete",
        "current_chunk": 0,
        "total_chunks": 0,
        "current_report": None,
    })
    
    return {
        "report_id": report_id,
        "progress": progress_data.get("progress", 1.0),
        "status": progress_data.get("status", "Report generation complete"),
        "current_chunk": progress_data.get("current_chunk", 0),
        "total_chunks": progress_data.get("total_chunks", 0),
        "current_report": progress_data.get("current_report", None),
    }


@router.get("/{report_id}/download")
async def download_report(
    report_id: str,
    format: str = "markdown",
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db),
) -> Any:
    """
    Download a report in the specified format.
    
    Args:
        report_id: ID of the report
        format: Format of the report (markdown, html, pdf)
        current_user: Current authenticated user
        db: Database session
        
    Returns:
        Report file
        
    Raises:
        HTTPException: If the report is not found or doesn't belong to the user
    """
    report = db.query(Report).filter(
        Report.id == report_id, Report.user_id == current_user.id
    ).first()
    
    if not report:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Report not found",
        )
    
    # Generate file in the requested format
    try:
        file_path = await report_service.generate_report_file(report, format)
        
        # Return file
        return FileResponse(
            path=file_path,
            filename=f"report_{report_id}.{format}",
            media_type="application/octet-stream",
        )
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error generating report file: {str(e)}",
        )
