import os
from pathlib import Path
from typing import Optional

from typing_extensions import Literal

from ...models.nassco.macp.inspection import MACPInspection
from ...translations.base import Language
from ...translations.nassco.defect_codes import NasscoDefectTranslations
from ...translations.nassco.enum_translations import NasscoEnumTranslations
from ...utils.pdf_reports import generate_pdf


def generate_macp_pdf(
    inspection: MACPInspection,
    annotated_frames_dir: str,
    pdf_output_path: str,
    video_name: str,
    uom: Literal["metric", "imperial"],
    logo_path: Optional[str] = None,
    language: Language = Language.ENGLISH,
    address: Optional[str] = None,
    pdf_title: Optional[str] = None,
):
    """
    Generate a PDF report for the MACP.

    Args:
        inspection: The MACP inspection to generate a PDF report for.
        annotated_frames_dir: The path of the directory to the annotated frames.
        pdf_output_path: The path to the output PDF file.
        video_name: The name of the video.
        uom: The unit of measurement.
        logo_path: The path to the logo image.
        language: The language for the report (default: English).
        address: The address for the report.
        pdf_title: The title for the PDF report.
    Returns:
        The path to the generated PDF file.
    """

    inspection_dict = inspection.__dict__.copy()
    inspection_dict["observations"].sort(key=lambda x: x.distance)

    # Translate enum values to Spanish if needed
    if language == Language.SPANISH:
        # Convert nested objects to dictionaries for easier manipulation
        if "header" in inspection_dict and hasattr(inspection_dict["header"], "__dict__"):
            inspection_dict["header"] = inspection_dict["header"].__dict__.copy()

        if "survey" in inspection_dict["header"] and hasattr(inspection_dict["header"]["survey"], "__dict__"):
            inspection_dict["header"]["survey"] = inspection_dict["header"]["survey"].__dict__.copy()

        # Translate weather
        if hasattr(inspection.header.survey, "weather") and inspection.header.survey.weather:
            inspection_dict["header"]["survey"]["weather"] = NasscoEnumTranslations.translate_enum_object(inspection.header.survey.weather, language)

        # Translate inspection technology
        if hasattr(inspection.header.survey, "inspection_technology") and inspection.header.survey.inspection_technology:
            inspection_dict["header"]["survey"]["inspection_technology"] = NasscoEnumTranslations.translate_enum_object(inspection.header.survey.inspection_technology, language)

    # Enrich inspection with annotated frame URIs and translate observations
    for index, observation in enumerate(inspection.observations):
        observation_dict = observation.__dict__.copy()
        annotated_frame_path = os.path.join(annotated_frames_dir, observation.image_reference)
        if not os.path.exists(annotated_frame_path):
            raise FileNotFoundError(f"Annotated frame file not found: {annotated_frame_path}")

        observation_dict["annotated_frame"] = Path(annotated_frame_path).absolute().as_uri()

        # Translate observation data for Spanish
        if language == Language.SPANISH:
            # MACP observations don't have pdf_observation_string, so we'll create a simple description
            if observation.code:
                observation_dict["pdf_observation_string"] = f"{observation.code.abbreviation} - {observation.code.label}"
                # Translate the observation string
                observation_dict["pdf_observation_string"] = NasscoDefectTranslations.translate_observation_string(observation_dict["pdf_observation_string"], language)
            else:
                observation_dict["pdf_observation_string"] = ""

            # Translate defect code label if it exists
            if "code" in observation_dict and observation_dict["code"] and hasattr(observation_dict["code"], "label"):
                # Translate the label using the defect translations
                translated_label = NasscoDefectTranslations.translate_observation_string(observation_dict["code"].label, language)

                # Create a simple object that mimics the enum structure
                class TranslatedCode:
                    def __init__(self, label, abbreviation):
                        self.label = label
                        self.abbreviation = abbreviation
                        self._abbreviation = abbreviation

                    def __str__(self):
                        return self.abbreviation

                    def __repr__(self):
                        return f"TranslatedCode({self.label} - {self.abbreviation})"

                observation_dict["code"] = TranslatedCode(translated_label, observation_dict["code"].abbreviation)

        inspection_dict["observations"][index] = observation_dict

    # Get language-specific measurement units
    if language == Language.SPANISH:
        measurement_units = "m" if uom == "metric" else "pies"
    else:
        measurement_units = "m" if uom == "metric" else "ft"

    image_prefix = ""
    if video_name:
        image_prefix = f"{video_name}_"

    data = {
        "title": pdf_title or "MACP Report" if language == Language.ENGLISH else "Reporte MACP",
        "inspection": inspection_dict,
        "logo_path": logo_path,
        "video_name": video_name,
        "measurement_units": measurement_units,
        "address": address,
        "image_prefix": image_prefix,
    }

    pdf_path = generate_pdf("nassco/macp/report.html", data, pdf_output_path, language)
    return pdf_path
