from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path

from fastapi import HTTPException, status
from sqlalchemy import select
from sqlalchemy.orm import Session

from app.models.contact import Contact
from app.models.customer import Customer
from app.models.device import Device
from app.models.equipment import Equipment
from app.models.report_template import (
    ChecklistTemplate,
    MeasurementImport,
    MeasurementImportValue,
    ReportSection,
    TextBlock,
)
from app.models.location import Location
from app.models.validation import Validation
from app.modules.orion.template_service import ReportTemplateService


@dataclass(frozen=True)
class ReportContext:
    validation: Validation
    customer: Customer
    location: Location | None
    contact: Contact | None
    device: Device | None
    equipment: list[Equipment]
    generated_dir: Path
    report_sections: list[ReportSection]
    text_blocks: dict[str, TextBlock]
    checklist_templates: list[ChecklistTemplate]
    confirmed_measurements: list[MeasurementImportValue]


class OrionContextBuilder:
    def __init__(self, session: Session, generated_dir: Path) -> None:
        self.session = session
        self.generated_dir = generated_dir

    def build(self, validation_id: str) -> ReportContext:
        validation = self.session.get(Validation, validation_id)
        if validation is None:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Validation not found")

        customer = self.session.get(Customer, validation.customer_id)
        if customer is None:
            raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="Validation has no customer")

        location = self.session.get(Location, validation.location_id) if validation.location_id else None
        contact = self.session.get(Contact, validation.contact_id) if validation.contact_id else None
        device = self.session.get(Device, validation.device_id) if validation.device_id else None
        equipment = []
        if validation.equipment_ids:
            equipment = list(
                self.session.scalars(
                    select(Equipment).where(Equipment.id.in_(validation.equipment_ids))
                )
            )
        template_bundle = ReportTemplateService(self.session).ensure_default_template()
        confirmed_measurements = list(
            self.session.scalars(
                select(MeasurementImportValue)
                .join_from(MeasurementImportValue, MeasurementImport)
                .where(
                    MeasurementImport.validation_id == validation.id,
                    MeasurementImportValue.confirmed.is_(True),
                )
            )
        )

        self.generated_dir.mkdir(parents=True, exist_ok=True)
        return ReportContext(
            validation=validation,
            customer=customer,
            location=location,
            contact=contact,
            device=device,
            equipment=equipment,
            generated_dir=self.generated_dir,
            report_sections=template_bundle.sections,
            text_blocks=template_bundle.text_blocks,
            checklist_templates=template_bundle.checklists,
            confirmed_measurements=confirmed_measurements,
        )
