"""CAD & PDF Rendering and Vector Export Engine for Drawing Takeoff.
Handles PyMuPDF rasterization, CAD font transcoding, multi-page chunking,
and high-resolution A3 Landscape / Portrait blueprint export.
"""

from __future__ import annotations

import logging
import shutil
from pathlib import Path

import fitz  # PyMuPDF

from app.modules.takeoff.application.cad_converter_service import get_cad_converter_service
from app.modules.takeoff.application.vietnamese_cad_font_transcoder import (
    get_vietnamese_cad_font_transcoder,
)

logger = logging.getLogger("dscons.takeoff.cad_converter")


class CadBlueprintConverter:
    """Converter for AutoCAD DWG/DXF and multi-page technical PDFs."""

    def __init__(self):
        self._font_transcoder = get_vietnamese_cad_font_transcoder()
        self._cad_converter = get_cad_converter_service()

    def render_pdf_to_images(
        self,
        pdf_path: Path | str,
        output_dir: Path | str,
        dpi: int = 200,
        max_pages: int = 15,
    ) -> list[str]:
        """Render all pages of engineering PDF blueprint to high-res PNG images for Multimodal AI Vision."""
        pdf_p = Path(pdf_path)
        out_d = Path(output_dir)
        out_d.mkdir(parents=True, exist_ok=True)

        if not pdf_p.exists():
            logger.warning("[TAKEOFF] File PDF không tồn tại: %s", pdf_p)
            return []

        image_paths = []
        try:
            doc = fitz.open(str(pdf_p))
            zoom = dpi / 72.0
            mat = fitz.Matrix(zoom, zoom)

            num_pages = min(len(doc), max_pages)
            for page_num in range(num_pages):
                page = doc.load_page(page_num)
                pix = page.get_pixmap(matrix=mat, alpha=False)
                img_name = f"{pdf_p.stem}_page_{page_num + 1}.png"
                img_dest = out_d / img_name
                pix.save(str(img_dest))
                image_paths.append(str(img_dest))

            doc.close()
            logger.info(
                "[TAKEOFF] Đã render %d trang ảnh từ %s (DPI=%d)",
                len(image_paths),
                pdf_p.name,
                dpi,
            )
        except Exception as e:
            logger.error("[TAKEOFF] Lỗi render PDF sang ảnh: %s", e)

        return image_paths

    def export_cad_drawing_to_a3_pdf(
        self,
        source_path: str | Path,
        target_pdf_path: str | Path | None = None,
        orientation: str = "landscape",
        color_scheme: str = "blueprint",
    ) -> Path:
        """Standardize CAD Drawing (.dwg, .dxf) or PDF to crisp, print-ready A3 PDF (1:100 / 1:200 scale)."""
        src = Path(source_path)
        if not src.exists():
            raise FileNotFoundError(f"Không tìm thấy file nguồn bản vẽ: {src}")

        ext = src.suffix.lower()
        if not target_pdf_path:
            out_dir = Path("app/static/drawings/a3_exports")
            out_dir.mkdir(parents=True, exist_ok=True)
            target_pdf_path = out_dir / f"{src.stem}_A3_{orientation}.pdf"
        target = Path(target_pdf_path)
        target.parent.mkdir(parents=True, exist_ok=True)

        if ext == ".pdf":
            try:
                src_doc = fitz.open(str(src))
                a3_doc = fitz.open()

                if orientation.lower() == "portrait":
                    a3_width, a3_height = 842.0, 1191.0
                else:
                    a3_width, a3_height = 1191.0, 842.0

                for page_idx in range(len(src_doc)):
                    src_page = src_doc[page_idx]
                    src_rect = src_page.rect

                    a3_page = a3_doc.new_page(width=a3_width, height=a3_height)

                    if color_scheme == "blueprint":
                        a3_page.draw_rect(
                            fitz.Rect(0, 0, a3_width, a3_height),
                            color=(0.04, 0.06, 0.12),
                            fill=(0.04, 0.06, 0.12),
                        )
                    elif color_scheme == "sepia":
                        a3_page.draw_rect(
                            fitz.Rect(0, 0, a3_width, a3_height),
                            color=(0.98, 0.95, 0.90),
                            fill=(0.98, 0.95, 0.90),
                        )

                    margin = 25.0
                    target_w = a3_width - (2 * margin)
                    target_h = a3_height - (2 * margin)

                    scale = min(target_w / src_rect.width, target_h / src_rect.height)
                    scaled_w = src_rect.width * scale
                    scaled_h = src_rect.height * scale

                    offset_x = margin + (target_w - scaled_w) / 2.0
                    offset_y = margin + (target_h - scaled_h) / 2.0
                    fit_rect = fitz.Rect(
                        offset_x, offset_y, offset_x + scaled_w, offset_y + scaled_h
                    )

                    a3_page.show_pdf_page(fit_rect, src_doc, page_idx)

                    # Draw outer border & standard CAD Title Block
                    border_color = (
                        (0.0, 0.5, 1.0)
                        if color_scheme == "blueprint"
                        else (0.1, 0.1, 0.1)
                    )
                    a3_page.draw_rect(fit_rect, color=border_color, width=1.5)

                    title_box = fitz.Rect(
                        fit_rect.x1 - 280, fit_rect.y1 - 65, fit_rect.x1, fit_rect.y1
                    )
                    a3_page.draw_rect(
                        title_box,
                        color=border_color,
                        fill=(0.06, 0.09, 0.18)
                        if color_scheme == "blueprint"
                        else (1, 1, 1),
                        width=1.0,
                    )
                    a3_page.insert_text(
                        fitz.Point(title_box.x0 + 10, title_box.y0 + 18),
                        "CÔNG TY TNHH XÂY DỰNG ĐỊNH SƠN (MST: 0202111150)",
                        fontsize=8,
                        color=border_color,
                    )
                    a3_page.insert_text(
                        fitz.Point(title_box.x0 + 10, title_box.y0 + 34),
                        f"HỒ SƠ THIẾT KẾ: {src.stem[:40]}",
                        fontsize=9,
                        color=(1, 1, 1) if color_scheme == "blueprint" else (0, 0, 0),
                    )
                    a3_page.insert_text(
                        fitz.Point(title_box.x0 + 10, title_box.y0 + 48),
                        f"QUY CHUẨN: KHỔ A3 (300 DPI) | TỶ LỆ: 1:100 | TRANG {page_idx + 1}/{len(src_doc)}",
                        fontsize=7.5,
                        color=(0.7, 0.7, 0.7),
                    )

                a3_doc.save(str(target))
                a3_doc.close()
                src_doc.close()
                logger.info(
                    "[TAKEOFF] Đã xuất A3 PDF thành công: %s (Khổ %s, %s)",
                    target.name,
                    orientation,
                    color_scheme,
                )
                return target
            except Exception as e:
                logger.error(
                    "[TAKEOFF] Lỗi đóng gói A3 PDF: %s. Fallback sao chép nguyên bản.",
                    e,
                )
                shutil.copyfile(src, target)
                return target

        # If DWG/DXF
        success = self._cad_converter.export_a3_vector_pdf(str(src), str(target))
        if success and target.exists():
            return target

        # Fallback
        shutil.copyfile(src, target)
        return target
