from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path

from src.errors import UserError
from src.images.cwebp import Cwebp, require_cwebp
from src.images.paths import website_dest_path
from src.matching.io import iter_image_files, validate_inbox_dir


@dataclass(frozen=True)
class WebsiteExportSummary:
    inbox_dir: Path
    out_dir: Path
    dry_run: bool
    files_found: int
    files_exported: int

    def to_human_summary(self) -> str:
        mode = "DRY-RUN" if self.dry_run else "RUN"
        return (
            f"{mode} website export summary\n"
            f"- inbox: {self.inbox_dir}\n"
            f"- out: {self.out_dir}\n"
            f"- files_found: {self.files_found}\n"
            f"- files_exported: {self.files_exported}"
        )


def export_website_webp(
    *, inbox_dir: Path, out_dir: Path, target_kb: int, dry_run: bool
) -> WebsiteExportSummary:
    validate_inbox_dir(inbox_dir)
    target_bytes = int(target_kb) * 1024
    if target_bytes <= 0:
        raise UserError("Invalid target_kb.")

    tool = require_cwebp() if not dry_run else None

    files = iter_image_files(inbox_dir)
    exported = 0
    for src in files:
        dest = website_dest_path(out_dir=out_dir, inbox_dir=inbox_dir, src=src)
        if dry_run:
            continue
        _export_single_webp(tool=tool, src=src, dest=dest, target_bytes=target_bytes)
        exported += 1

    return WebsiteExportSummary(
        inbox_dir=inbox_dir,
        out_dir=out_dir,
        dry_run=dry_run,
        files_found=len(files),
        files_exported=exported,
    )


def _export_single_webp(*, tool: Cwebp | None, src: Path, dest: Path, target_bytes: int) -> None:
    if tool is None:
        raise UserError("Internal error: cwebp tool missing in run mode.")
    dest.parent.mkdir(parents=True, exist_ok=True)

    qualities = [80, 70, 60, 50, 40, 30, 20]
    tmp = dest.with_suffix(dest.suffix + ".tmp")
    last_size = None
    for q in qualities:
        if tmp.exists():
            tmp.unlink()
        tool.run(input_path=src, output_path=tmp, quality=q)
        last_size = tmp.stat().st_size
        if last_size <= target_bytes:
            tmp.replace(dest)
            return
    if tmp.exists():
        tmp.unlink()
    raise UserError(f"Failed to reach target <= {target_bytes} bytes (last={last_size}).")
