import logging

from celery import Task

from core.celery_app import celery_app
from core.database import scoped_core_db
from core.exceptions import ValidationException

from api.v1.modules.a76.invoices.models import InvoiceHeader, InvoiceStatus
from .main_process import main_process

logger = logging.getLogger(__name__)


def _progress(task: Task, current: int, status: str) -> None:
    task.update_state(state="PROGRESS", meta={"current": current, "status": status})


@celery_app.task(bind=True, name="process_invoice_task")
def process_invoice_task(self: Task, invoice_id: int, tenant_id: str, company_id: str, username: str = "SYSTEM") -> dict:
    """
    Procesa una factura de importación ejecutando todas las validaciones y
    actualizaciones del proceso principal (main_process) con reporte de progreso.
    """
    with scoped_core_db(tenant_id=int(tenant_id), company_id=int(company_id)) as db:
        try:
            _progress(self, 5, "Cargando factura...")
            invoice: InvoiceHeader | None = db.get(InvoiceHeader, invoice_id)

            if invoice is None:
                return {
                    "status": "error",
                    "message": f"Factura con id {invoice_id} no encontrada.",
                    "errors": [],
                }

            _progress(self, 10, "Verificando estatus de seguridad...")
            if invoice.status == InvoiceStatus.PROCESSED:
                return {
                    "status": "error",
                    "message": f"La factura {invoice.invoice_number} ya se encuentra procesada.",
                    "errors": [{"field": "status", "message": "Factura ya procesada."}],
                }

            _progress(self, 20, "Iniciando procesamiento de factura...")
            result = main_process(
                db=db,
                invoice=invoice,
                tenant_id=tenant_id,
                company_id=company_id,
                username=username,
            )

            _progress(self, 95, "Confirmando cambios...")
            db.commit()

            _progress(self, 100, "Proceso completado.")
            return result

        except ValidationException as exc:
            db.rollback()
            return {
                "status": "validation_error",
                "message": exc.message,
                "errors": exc.errors,
            }
        except Exception as exc:
            db.rollback()
            logger.error(f"Error en process_invoice_task: {str(exc)}", exc_info=True)
            raise exc
