"""PDF에서 해안조사 사진을 추출하여 scat-photos 폴더에 저장.

Type A (해안사전평가정보집): 1페이지 = 1구간 → 가장 큰 RGB 사진
Type B (방제정보집): 1페이지 = 2구간 → RGB 사진 2장, 순서대로 매칭

저장 네이밍: {sect_cd}-1.png (ScatPopup에서 참조하는 형식)
"""

from __future__ import annotations

import re
from pathlib import Path
from typing import List, Tuple

import fitz  # PyMuPDF

from pdf_parser import is_data_page, _CODE_RE
from pdf_parser_b import is_data_page_b

import config


def _get_page_photos(
    doc: fitz.Document, page: fitz.Page,
) -> List[fitz.Pixmap]:
    """페이지에서 RGB 사진만 추출 (배경 제외). 크기 내림차순."""
    photos: List[Tuple[fitz.Pixmap, int]] = []
    for img_info in page.get_images(full=True):
        xref = img_info[0]
        pix = fitz.Pixmap(doc, xref)
        # CMYK → RGB
        if pix.n > 4:
            pix = fitz.Pixmap(fitz.csRGB, pix)
        elif pix.n == 4:
            pix = fitz.Pixmap(fitz.csRGB, pix)
        # 흑백(n=1) 또는 배경(2000px 이상) 스킵
        if pix.n < 3 or pix.width >= 2000:
            continue
        photos.append((pix, pix.width * pix.height))
    photos.sort(key=lambda x: x[1], reverse=True)
    return photos


def _extract_codes_type_a(page: fitz.Page) -> List[str]:
    """Type A 페이지에서 sect_cd 추출."""
    text = page.get_text('text')
    return _CODE_RE.findall(text)


def _extract_codes_type_b(page: fitz.Page) -> List[str]:
    """Type B 페이지에서 sect_cd 추출 (순서 유지)."""
    text = page.get_text('text')
    codes = re.findall(r'([A-Z]{4,}-\d+(?:-[A-Z]){3,})', text)
    seen = set()
    unique = []
    for c in codes:
        if c not in seen:
            seen.add(c)
            unique.append(c)
    return unique


def _save_pixmap(pix: fitz.Pixmap, output_path: Path):
    """Pixmap을 PNG로 저장."""
    if pix.alpha:
        pix = fitz.Pixmap(fitz.csRGB, pix)
    pix.save(str(output_path))


def extract_images_from_pdf(
    pdf_path: str | Path,
    output_dir: str | Path | None = None,
    pdf_type: str = 'A',
) -> int:
    """PDF에서 데이터 페이지별 대표 사진을 추출.

    Args:
        pdf_path: PDF 파일 경로
        output_dir: 이미지 저장 경로 (기본: config.SCAT_PHOTOS_DIR)
        pdf_type: 'A' 또는 'B'

    Returns:
        추출된 이미지 수
    """
    pdf_path = Path(pdf_path)
    out_dir = Path(output_dir) if output_dir else config.SCAT_PHOTOS_DIR
    out_dir.mkdir(parents=True, exist_ok=True)

    doc = fitz.open(str(pdf_path))
    saved = 0

    for i in range(doc.page_count):
        page = doc[i]

        if pdf_type == 'A':
            if not is_data_page(page):
                continue
            codes = _extract_codes_type_a(page)
            photos = _get_page_photos(doc, page)
            if not codes or not photos:
                continue
            # 가장 작은 RGB 이미지 = 실제 현장 사진
            pix = photos[-1][0]
            out_path = out_dir / f'{codes[0]}-1.png'
            _save_pixmap(pix, out_path)
            saved += 1

        elif pdf_type == 'B':
            if not is_data_page_b(page):
                continue
            codes = _extract_codes_type_b(page)
            photos = _get_page_photos(doc, page)
            if not codes or not photos:
                continue
            # Type B: 사진 크기 동일, 순서대로 매칭
            for idx, code in enumerate(codes):
                if idx < len(photos):
                    pix = photos[idx][0]
                    out_path = out_dir / f'{code}-1.png'
                    _save_pixmap(pix, out_path)
                    saved += 1

    doc.close()
    return saved
