import logging
from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.orm import Session
from typing import List, Union

from core.database import get_core_db
from core.security import get_current_user, get_tenant_from_token
from api.v1.modules.core.tasks_tracking import track_and_dispatch
from .schemas import (
    ImportTemporaryFilter, 
    ImportDefinitiveFilter, 
    ImportRepairFilter,
    ExportFilter,
    ExportRepairFilter,
    AllMovementsFilter,
    MovementItem, 
    MovementItemDetailed
)
from .movement_service import movement_service

logger = logging.getLogger(__name__)

router = APIRouter(
    tags=["Reports - Movement Invoices"]
)


@router.post(
    "/temporary", 
    response_model=List[MovementItem],
    summary="Get Temporary Import Movements",
    description="""
    Retrieve temporary import movements from legacy database based on filter criteria.
    This endpoint corresponds to the 'LLENADOTEMPORAL' (Fill Temporary) logic from the legacy system.
    
    **Note**: Requires connection to legacy SQL Server database.
    """
)
def get_temporary_import_movements(
    filters: ImportTemporaryFilter,
    company_id: int = Query(..., description="ID de la empresa"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user)
):
    """
    Get temporary import movements based on filters.
    
    Args:
        filters: Filter criteria for querying movements
        db: Database session
        current_user: Authenticated user information
        
    Returns:
        List of movement items matching the criteria
        
    Raises:
        HTTPException: If database query fails or user is unauthorized
    """
    try:
        logger.info(
            f"User {current_user.get('preferred_username', 'unknown')} "
            f"requesting temporary import movements"
        )
        from core.security import validate_access_to_resource
        validate_access_to_resource(db, company_id, current_user, ["report.view"])

        movements = movement_service.get_temporary_import_movements(
            db=db, 
            filters=filters
        )
        logger.info(f"Successfully retrieved {len(movements)} movements")
        return movements
    except ValueError as e:
        logger.warning(f"Validation error fetching movements: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        logger.error(f"Error fetching movements: {str(e)}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error processing import temporary movements: {str(e)}"
        )


@router.post(
    "/temporary-detailed", 
    response_model=List[MovementItemDetailed],
    summary="Get Detailed Temporary Import Movements",
    description="""
    Retrieve detailed temporary import movements (line by line) from legacy database.
    This endpoint corresponds to the 'LLENADOTEMPORAL - DETALLADO' logic from the legacy system.
    
    Each line/partida is returned separately with complete information including:
    - Provider and buyer details (name, RFC, Tax ID)
    - Customs broker information
    - Item descriptions and specifications
    - Series information
    - All related metadata
    
    **Note**: Requires connection to legacy SQL Server database.
    """
)
def get_temporary_import_movements_detailed(
    filters: ImportTemporaryFilter,
    company_id: int = Query(..., description="ID de la empresa"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user)
):
    """
    Get detailed temporary import movements (line by line) based on filters.
    
    Args:
        filters: Filter criteria for querying movements
        db: Database session
        current_user: Authenticated user information
        
    Returns:
        List of detailed movement items matching the criteria
        
    Raises:
        HTTPException: If database query fails or user is unauthorized
    """
    try:
        logger.info(
            f"User {current_user.get('preferred_username', 'unknown')} "
            f"requesting DETAILED temporary import movements"
        )
        from core.security import validate_access_to_resource
        validate_access_to_resource(db, company_id, current_user, ["report.view"])
        
        movements = movement_service.get_temporary_import_movements_detailed(
            db=db, 
            filters=filters
        )
        logger.info(f"Successfully retrieved {len(movements)} detailed movements")
        return movements
    except ValueError as e:
        logger.warning(f"Validation error fetching detailed movements: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        logger.error(f"Error fetching detailed movements: {str(e)}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error processing detailed import temporary movements: {str(e)}"
        )


@router.post(
    "/definitive",
    response_model=List[MovementItem],
    summary="Get Definitive Import Movements",
    description="""
    Retrieve definitive import movements from legacy database based on filter criteria.
    This endpoint corresponds to the 'LLENADODEFINITIVO - NORMAL' logic from the legacy system.
    
    Definitive imports are aggregated by invoice number and can be filtered by:
    - Movement type (COMEX or IMPDF based on ProvImpoDefCR field)
    - Date range (invoice date or payment date)
    - Provider and buyer
    - Pedimento code
    - Status (active or including cancelled)
    
    **Special Features**:
    - Supports shelter company logic for exchange rate calculations
    - MetTrans# = 1 logic for specific pedimento types (1, 4, 98E)
    - Retrieves driver badge information
    - Handles rectification pedimento lookups
    
    **Note**: Requires connection to legacy SQL Server database.
    """
)
def get_definitive_import_movements(
    filters: ImportDefinitiveFilter,
    company_id: int = Query(..., description="ID de la empresa"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user)
):
    """
    Get definitive import movements based on filters.
    
    Args:
        filters: Filter criteria for querying movements
        db: Database session
        current_user: Authenticated user information
        
    Returns:
        List of movement items matching the criteria
        
    Raises:
        HTTPException: If database query fails or user is unauthorized
    """
    try:
        logger.info(
            f"User {current_user.get('preferred_username', 'unknown')} "
            f"requesting definitive import movements"
        )
        from core.security import validate_access_to_resource
        validate_access_to_resource(db, company_id, current_user, ["report.view"])
        
        movements = movement_service.get_definitive_import_movements(
            db=db,
            filters=filters
        )
        logger.info(f"Successfully retrieved {len(movements)} definitive movements")
        return movements
    except Exception as e:
        logger.error(f"Error fetching definitive movements: {str(e)}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error processing definitive import movements: {str(e)}"
        )


@router.post(
    "/definitive-detailed",
    response_model=List[MovementItemDetailed],
    summary="Get Detailed Definitive Import Movements",
    description="""
    Retrieve detailed definitive import movements (line by line) from legacy database.
    This endpoint corresponds to the 'LLENADODEFINITIVO - DETALLADO' logic from the legacy system.
    
    Each line/partida is returned separately with complete information including:
    - Provider and buyer details (name, RFC, Tax ID)
    - Customs broker information
    - Item descriptions and specifications
    - Series information from QSeriesDef table
    - All related metadata
    
    **Special Logic**:
    - Only Partidas (EsSubPartida = 'P') have values calculated
    - Subpartidas (EsSubPartida = 'S') return with zero values
    - Series formatted as: "1) SERIE123. Modelo: MOD1. Parte: PART1 | 2) SERIE456..."
    - Exchange rate calculation supports shelter and non-shelter logic
    - MetTrans# = 1 logic for pedimento types 1, 4, 98E
    
    **Note**: Requires connection to legacy SQL Server database.
    """
)
def get_definitive_import_movements_detailed(
    filters: ImportDefinitiveFilter,
    company_id: int = Query(..., description="ID de la empresa"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user)
):
    """
    Get detailed definitive import movements (line by line) based on filters.
    
    Args:
        filters: Filter criteria for querying movements
        db: Database session
        current_user: Authenticated user information
        
    Returns:
        List of detailed movement items matching the criteria
        
    Raises:
        HTTPException: If database query fails or user is unauthorized
    """
    try:
        logger.info(
            f"User {current_user.get('preferred_username', 'unknown')} "
            f"requesting DETAILED definitive import movements"
        )
        from core.security import validate_access_to_resource
        validate_access_to_resource(db, company_id, current_user, ["report.view"])
        
        movements = movement_service.get_definitive_import_movements_detailed(
            db=db,
            filters=filters
        )
        logger.info(f"Successfully retrieved {len(movements)} detailed definitive movements")
        return movements
    except Exception as e:
        logger.error(f"Error fetching detailed definitive movements: {str(e)}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error processing detailed definitive import movements: {str(e)}"
        )


@router.post(
    "/repair",
    response_model=List[MovementItem],
    summary="Get Repair Import Movements",
    description="""
    Retrieve repair import movements from legacy database based on filter criteria.
    This endpoint corresponds to the 'LLENADOIMP_REPARACION - NORMAL' logic from the legacy system.
    
    Repair imports are aggregated by invoice number and can be filtered by:
    - Discharge status (SiDes: discharged, NoDes: not discharged, ALL: no filter)
    - Date range (invoice date or payment date)
    - Provider and buyer
    - Pedimento code
    - Status (active or including cancelled)
    
    **Special Features**:
    - Excludes regime changes (EsCambioRegimen <> 'S')
    - Supports discharge filter (unique to repair imports)
    - Exchange rate calculation with shelter/non-shelter logic
    - MetTrans# = 1 logic for specific pedimento types (1, 4, 98E)
    - Retrieves driver badge information
    
    **Database Tables**:
    - QFacImpRep: Repair import invoices
    - QEqiMaqRep: Repair import items/partidas
    - QPedimentos: Pedimentos (customs declarations)
    
    **Note**: Requires connection to legacy SQL Server database.
    """
)
def get_repair_import_movements(
    filters: ImportRepairFilter,
    company_id: int = Query(..., description="ID de la empresa"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user)
):
    """
    Get repair import movements based on filters.
    
    Args:
        filters: Filter criteria for querying movements
        db: Database session
        current_user: Authenticated user information
        
    Returns:
        List of movement items matching the criteria
        
    Raises:
        HTTPException: If database query fails or user is unauthorized
    """
    try:
        logger.info(
            f"User {current_user.get('preferred_username', 'unknown')} "
            f"requesting repair import movements"
        )
        from core.security import validate_access_to_resource
        validate_access_to_resource(db, company_id, current_user, ["report.view"])
        
        movements = movement_service.get_repair_import_movements(
            db=db,
            filters=filters
        )
        logger.info(f"Successfully retrieved {len(movements)} repair movements")
        return movements
    except Exception as e:
        logger.error(f"Error fetching repair movements: {str(e)}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error processing repair import movements: {str(e)}"
        )


@router.post(
    "/repair-detailed",
    response_model=List[MovementItemDetailed],
    summary="Get detailed repair import movements",
    description="""
    Retrieve detailed repair import movements (IMPRE) with individual partida lines.
    
    **LLENADOIMP_REPARACION - DETALLADO**
    
    Returns individual partida (line item) records for repair imports with full detail including:
    - Complete invoice and customs clearance information
    - Series, model, and part numbers for each item
    - Client/supplier and sold-to information with tax IDs
    - Exchange rate calculations (MN/ME) based on filter options
    - Customs agent and customs section details
    - Driver badge unique number
    - All partida-level fields (part number, descriptions, quantities, weights, etc.)
    
    **Discharge Filter Options:**
    - `SiDes`: Only include discharged items (Descarga = 1)
    - `NoDes`: Only include non-discharged items (Descarga = 0)  
    - `ALL`: Include all items regardless of discharge status
    
    **Database Tables Used:**
    - QFacImpRep: Repair import invoices
    - QPedimentos: Customs declarations
    - QEqiMaqRep: Repair import partidas (line items)
    - QSeriesImpoRep: Series information
    - GClientesPro: Suppliers
    - GCliVendido: Sold-to clients
    - GAAduanal: Customs agents
    - GAduanaSec: Customs sections
    - GConductor: Drivers (for badge numbers)
    - GTipoCambio: Exchange rates
    """,
    tags=["Import Movements - Repair"]
)
async def get_import_repair_movements_detailed(
    filters: ImportRepairFilter,
    company_id: int = Query(..., description="ID de la empresa"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user)
):
    """
    Get detailed repair import movements based on filter criteria.
    Returns partida-level detail with series information and full client/customs data.
    """
    try:
        logger.info(f"User {current_user.get('sub')} requesting detailed repair movements")
        from core.security import validate_access_to_resource
        validate_access_to_resource(db, company_id, current_user, ["report.view"])
        
        movements = movement_service.get_repair_import_movements_detailed(
            db=db,
            filters=filters
        )
        logger.info(f"Successfully retrieved {len(movements)} detailed repair partidas")
        return movements
    except Exception as e:
        logger.error(f"Error fetching detailed repair movements: {str(e)}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error processing detailed repair import movements: {str(e)}"
        )


@router.post(
    "/export",
    response_model=List[MovementItem],
    summary="Get export movements",
    description="""
    Retrieve export movements (EXPO DEF) grouped by invoice.
    
    **LLENADOEXPORTACION - NORMAL**
    
    Returns aggregated data grouped by invoice number for export movements.
    
    **Movement Type Options:**
    - `AFIJO`: Fixed assets
    - `NODES`: No discharge
    - `SCRAP`: Scrap materials
    - `REEXP`: Re-exports
    - `DONAC`: Donations
    - `VEMEX`: Sales to Mexico
    - `ALL`: All movement types
    
    **Discharge Filter Options:**
    - `SiDes`: Only discharged items (Descarga = 1)
    - `NoDes`: Only non-discharged items (Descarga = 0)
    - `ALL`: All items regardless of discharge status
    
    **Database Tables Used:**
    - QFacExp: Export invoices
    - QEqeMaq: Export partidas (line items)
    - QPedimentos: Customs declarations
    - QClaAct: Part classifications
    - GAAduanal: Customs agents
    - GAduanaSec: Customs sections
    - GConductor: Drivers
    - GTipoCambio: Exchange rates
    
    Automatically excludes regime changes (EsCambioRegimen = 'N')
    """,
    tags=["Export Movements"]
)
async def get_export_movements(
    filters: ExportFilter,
    company_id: int = Query(..., description="ID de la empresa"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user)
):
    """
    Get export movements based on filter criteria.
    Returns aggregated data grouped by invoice.
    """
    try:
        logger.info(f"User {current_user.get('sub')} requesting export movements")
        from core.security import validate_access_to_resource
        validate_access_to_resource(db, company_id, current_user, ["report.view"])
        
        movements = movement_service.get_export_movements(
            db=db,
            filters=filters
        )
        logger.info(f"Successfully retrieved {len(movements)} export movements")
        return movements
    except Exception as e:
        logger.error(f"Error fetching export movements: {str(e)}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error processing export movements: {str(e)}"
        )


@router.post(
    "/export-detailed",
    response_model=List[MovementItemDetailed],
    summary="Get detailed export movements",
    description="""
    Retrieve detailed export movements with individual partida lines.
    
    **LLENADOEXPORTACION - DETALLADO**
    
    Returns individual partida (line item) records for exports with full detail including:
    - Complete invoice and customs clearance information
    - Series, model, and part numbers for each item
    - Client/supplier and buyer information with tax IDs
    - Exchange rate calculations (MN/ME) based on filter options
    - Customs agent and customs section details
    - Driver badge unique number
    - All partida-level fields
    
    **Movement Type Options:**
    - `AFIJO`: Fixed assets
    - `NODES`: No discharge
    - `SCRAP`: Scrap materials
    - `REEXP`: Re-exports
    - `DONAC`: Donations
    - `VEMEX`: Sales to Mexico
    - `ALL`: All movement types
    
    **Discharge Filter Options:**
    - `SiDes`: Only discharged items
    - `NoDes`: Only non-discharged items
    - `ALL`: All items
    
    **Database Tables Used:**
    - QFacExp: Export invoices
    - QEqeMaq: Export partidas
    - QSeriesExpo: Serial numbers
    - QPedimentos: Customs declarations
    - GClientesPro: Suppliers
    - GCliVendido: Buyers
    - GAAduanal: Customs agents
    - GAduanaSec: Customs sections
    - GConductor: Drivers
    - GTipoCambio: Exchange rates
    """,
    tags=["Export Movements"]
)
async def get_export_movements_detailed(
    filters: ExportFilter,
    company_id: int = Query(..., description="ID de la empresa"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user)
):
    """
    Get detailed export movements based on filter criteria.
    Returns partida-level detail with series information and full client/customs data.
    """
    try:
        logger.info(f"User {current_user.get('sub')} requesting detailed export movements")
        from core.security import validate_access_to_resource
        validate_access_to_resource(db, company_id, current_user, ["report.view"])
        
        movements = movement_service.get_export_movements_detailed(
            db=db,
            filters=filters
        )
        logger.info(f"Successfully retrieved {len(movements)} detailed export partidas")
        return movements
    except Exception as e:
        logger.error(f"Error fetching detailed export movements: {str(e)}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error processing detailed export movements: {str(e)}"
        )


@router.post("/export-repair", response_model=List[MovementItem])
def get_export_repair_movements(
    filters: ExportRepairFilter,
    company_id: int = Query(..., description="ID de la empresa"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user)
):
    """
    **LLENADOEXP_REPARACION - NORMAL**
    
    Get export repair movements (EXPO REP) based on filter criteria.
    Groups results by invoice (FacturaExpo).
    
    Clarion logic:
    - Query from QFacExpRep, QEqeMaqRep tables
    - Filters: date range (FF/FP), provider, buyer, pedimento code
    - Movement types: AFIJO, NODES
    - Discharge filter: SiDes, NoDes, or ALL
    - Calculates totals from partidas where EsSubpartida = 'P'
    - Exchange rate logic based on currency type and Scaii.ini MetTrans
    - Always filters by EsCambioRegimen = 'N'
    """
    try:
        logger.info(f"User {current_user.get('sub')} requesting export repair movements")
        from core.security import validate_access_to_resource
        validate_access_to_resource(db, company_id, current_user, ["report.view"])
        
        movements = movement_service.get_export_repair_movements(
            db=db,
            filters=filters
        )
        logger.info(f"Successfully retrieved {len(movements)} export repair invoices")
        return movements
    except Exception as e:
        logger.error(f"Error fetching export repair movements: {str(e)}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error processing export repair movements: {str(e)}"
        )


@router.post("/export-repair-detailed", response_model=List[MovementItemDetailed])
def get_export_repair_movements_detailed(
    filters: ExportRepairFilter,
    company_id: int = Query(..., description="ID de la empresa"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user)
):
    """
    Get detailed export repair movements based on filter criteria.
    Returns partida-level detail with series information and full client/customs data.
    """
    try:
        logger.info(f"User {current_user.get('sub')} requesting detailed export repair movements")
        from core.security import validate_access_to_resource
        validate_access_to_resource(db, company_id, current_user, ["report.view"])
        
        movements = movement_service.get_export_repair_movements_detailed(
            db=db,
            filters=filters
        )
        logger.info(f"Successfully retrieved {len(movements)} detailed export repair partidas")
        return movements
    except Exception as e:
        logger.error(f"Error fetching detailed export repair movements: {str(e)}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error processing detailed export repair movements: {str(e)}"
        )


@router.post(
    "/all", 
    response_model=Union[List[MovementItemDetailed], List[MovementItem]],
    summary="Get All Invoice Movements",
    description="""
    Retrieve all invoice movements (imports and exports of all types) from database.
    This endpoint combines temporary, definitive, and repair imports with all export types.
    
    Use this when "TODAS" checkbox is selected to get a comprehensive view of all movements
    regardless of their specific type.
    
    If send_email is True, the report will be sent to the authenticated user's email address.
    """
)
async def get_all_movements(
    filters: AllMovementsFilter,
    company_id: int = Query(..., description="ID de la empresa"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user)
):
    """
    Get all invoice movements (all types combined) based on filters.
    
    Args:
        filters: Filter criteria for querying movements
        db: Database session
        current_user: Authenticated user information
        
    Returns:
        List of all movement items matching the criteria
        
    Raises:
        HTTPException: If database query fails or user is unauthorized
    """
    try:
        logger.info(
            f"User {current_user.get('preferred_username', 'unknown')} "
            f"requesting all invoice movements (send_email={filters.send_email})"
        )
        from core.security import validate_access_to_resource
        validate_access_to_resource(db, company_id, current_user, ["report.view"])
        
        movements = movement_service.get_all_movements(
            db=db, 
            filters=filters
        )
        logger.info(f"Successfully retrieved {len(movements)} total movements")
        
        # Send email if requested
        if filters.send_email:
            user_email = current_user.get('email')
            if not user_email:
                logger.warning(f"User {current_user.get('sub')} has no email address - skipping email")
            else:
                try:
                    from core.email import EmailService
                    from .csv_utils import generate_csv_from_movements
                    from datetime import datetime
                    
                    # Generate CSV
                    csv_content = generate_csv_from_movements(
                        movements=movements,
                        filters=filters
                    )
                    
                    # Generate filename
                    filename = f"reporte_facturas_{filters.start_date}_{filters.end_date}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
                    
                    # Send email
                    email_sent = await EmailService.send_report_email(
                        recipient_email=user_email,
                        subject=f"Reporte de Facturas - {filters.start_date} al {filters.end_date}",
                        body_text=f"Se ha generado el reporte de facturas solicitado con {len(movements)} registros.",
                        csv_content=csv_content,
                        filename=filename
                    )
                    
                    if email_sent:
                        logger.info(f"Report emailed successfully to {user_email}")
                    else:
                        logger.warning(f"Failed to send email to {user_email} - SMTP may not be configured correctly")
                        
                except Exception as email_error:
                    logger.warning(f"Email sending failed: {str(email_error)} - continuing with report generation")
        
        return movements
        return movements
    except ValueError as e:
        logger.warning(f"Validation error fetching all movements: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error fetching all movements: {str(e)}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Error processing all movements: {str(e)}"
        )


@router.post(
    "/generate",
    summary="Generate Invoice Report (Async)",
    description="Trigger background generation of invoice report."
)
def generate_invoice_report_async(
    filters: AllMovementsFilter,
    company_id: int = Query(..., description="ID de la empresa"),
    db: Session = Depends(get_core_db),
    current_user: dict = Depends(get_current_user)
):
    """
    Trigger background generation of invoice report.
    Returns task_id to poll status.
    """
    from .tasks import generate_invoice_movements_async
    from core.security import validate_access_to_resource
    
    logger.info(f"User {current_user.get('preferred_username', 'unknown')} triggering async report generation")
    
    # validate_access_to_resource returns the integer tenant_id from DB
    tenant_id = validate_access_to_resource(db, company_id, current_user, ["report.process"])

    # Serialize filters to dict for Celery
    filter_data = filters.model_dump()
    user_email = current_user.get('email')
    
    # Trigger task
    tenant_id = get_tenant_from_token(current_user)
    if not tenant_id:
        tenant_id = current_user.get("tenant_id")
    if not tenant_id:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Tenant ID not found in token",
        )
    task = track_and_dispatch(
        db=db,
        task=generate_invoice_movements_async,
        tenant_id=int(tenant_id),
        company_id=company_id,
        requested_by_user=current_user.get("preferred_username") or current_user.get("email") or current_user.get("sub"),
        task_name="generate_invoice_movements_async",
        task_group="reports",
        task_origin="a76/reports/movements/invoices",
        args=[filter_data, user_email],
    )
    
    return {"task_id": task.id}


@router.get(
    "/task/{task_id}",
    summary="Get Async Task Status",
    description="Check status of background report generation task."
)
def get_task_status(task_id: str):
    """
    Get status of background task.
    """
    from celery.result import AsyncResult
    from core.celery_app import celery_app
    
    task_result = AsyncResult(task_id, app=celery_app)
    
    response = {
        "task_id": task_id,
        "status": task_result.status,
    }
    
    if task_result.state == 'PROCESSING':
         response["meta"] = task_result.info
    
    if task_result.ready():
        response["result"] = task_result.result
        
    return response
