"""Public facade for XML export generation and download responses."""

from __future__ import annotations

import logging
from datetime import date

from django.http import HttpResponse

from istat.xml_export.exceptions import XmlPayloadValidationError
from istat.xml_export.http.responses import (
    build_xml_download_response,
    build_zip_download_response,
)
from istat.xml_export.services.xml_export_service import (
    generate_c59_xml_export,
    generate_c59_zip_export,
    generate_guest_xml_export,
)
from istat.xml_export.validation.xsd_validator import (
    load_default_c59_xsd_path,
    validate_c59_xml_against_xsd,
)
from structures.models import Structure


logger = logging.getLogger(__name__)


def _count_guest_payloads(xml_content: str) -> int:
    return xml_content.count("<guest>")


def _count_c59_rows(xml_content: str) -> int:
    return xml_content.count("<rim:rigac59")


def generate_guest_xml_download(
    *,
    structure_id: int,
    start_date: date,
    end_date: date,
) -> HttpResponse:
    """Generate a guest XML export and wrap it in a download response."""

    structure = Structure.objects.filter(id=structure_id).only("id", "istat_code").first()
    structure_istat_code = (
        str(getattr(structure, "istat_code", "") or "").strip() or None
    )
    log_context = {
        "structure_id": structure_id,
        "structure_istat_code": structure_istat_code,
        "export_type": "guest_xml",
        "start_date": start_date.isoformat() if isinstance(start_date, date) else start_date,
        "end_date": end_date.isoformat() if isinstance(end_date, date) else end_date,
        "xsd_validation_enabled": False,
        "xsd_path": None,
    }

    try:
        export_result = generate_guest_xml_export(
            structure_id=structure_id,
            start_date=start_date,
            end_date=end_date,
        )
        response = build_xml_download_response(export_result)
    except XmlPayloadValidationError:
        logger.warning(
            "Guest XML download generation failed",
            extra={**log_context, "status": "failure"},
        )
        raise

    logger.info(
        "Guest XML download generated",
        extra={
            **log_context,
            "filename": export_result.filename,
            "payload_count": _count_guest_payloads(export_result.content),
            "status": "success",
        },
    )
    return response


def generate_c59_xml_download(
    *,
    structure_id: int,
    report_date: date,
    validate_xsd: bool = False,
    xsd_path: str | None = None,
) -> HttpResponse:
    """Generate a C59 XML export, optionally validate it, and return a download response."""

    structure = Structure.objects.filter(id=structure_id).only("id", "istat_code").first()
    structure_istat_code = (
        str(getattr(structure, "istat_code", "") or "").strip() or None
    )
    resolved_xsd_path = xsd_path or (load_default_c59_xsd_path() if validate_xsd else None)
    log_context = {
        "structure_id": structure_id,
        "structure_istat_code": structure_istat_code,
        "export_type": "c59_xml",
        "report_date": report_date.isoformat() if isinstance(report_date, date) else report_date,
        "xsd_validation_enabled": validate_xsd,
        "xsd_path": resolved_xsd_path,
    }

    try:
        export_result = generate_c59_xml_export(
            structure_id=structure_id,
            report_date=report_date,
        )
        if validate_xsd:
            validate_c59_xml_against_xsd(export_result.content, resolved_xsd_path)
        response = build_xml_download_response(export_result)
    except XmlPayloadValidationError:
        logger.warning(
            "C59 XML download generation failed",
            extra={**log_context, "status": "failure"},
        )
        raise

    logger.info(
        "C59 XML download generated",
        extra={
            **log_context,
            "filename": export_result.filename,
            "row_count": _count_c59_rows(export_result.content),
            "status": "success",
        },
    )
    return response


def generate_c59_zip_download(
    *,
    structure_id: int,
    start_date: date,
    end_date: date,
) -> HttpResponse:
    """Generate a multi-day C59 ZIP export and return a download response.

    One C59 XML file is generated per calendar day in [start_date, end_date].
    All files are packed into a single in-memory ZIP archive.
    """
    structure = Structure.objects.filter(id=structure_id).only("id", "istat_code").first()
    structure_istat_code = (
        str(getattr(structure, "istat_code", "") or "").strip() or None
    )
    log_context = {
        "structure_id": structure_id,
        "structure_istat_code": structure_istat_code,
        "export_type": "c59_zip",
        "start_date": start_date.isoformat() if isinstance(start_date, date) else start_date,
        "end_date": end_date.isoformat() if isinstance(end_date, date) else end_date,
    }

    try:
        export_result = generate_c59_zip_export(
            structure_id=structure_id,
            start_date=start_date,
            end_date=end_date,
        )
        response = build_zip_download_response(export_result)
    except XmlPayloadValidationError:
        logger.warning(
            "C59 ZIP download generation failed",
            extra={**log_context, "status": "failure"},
        )
        raise

    logger.info(
        "C59 ZIP download generated",
        extra={
            **log_context,
            "zip_filename": export_result.filename,
            "file_count": export_result.file_count,
            "zip_byte_size": export_result.byte_size,
            "status": "success",
        },
    )
    return response
