"""
Pheser — Comparator
Diff EXIF metadata between two images side-by-side.
Useful for verifying clean / redact operations.
"""

from __future__ import annotations
import os
from typing import Any

from PIL import Image
import piexif

from .utils import decode_value, gps_to_deg


def _load_flat(path: str) -> dict[str, Any]:
    """Return a flat tag_name → value dict for an image."""
    flat: dict[str, Any] = {}
    try:
        img = Image.open(path)
    except Exception:
        return flat
    if "exif" not in img.info:
        return flat
    exif_dict = piexif.load(img.info["exif"])
    for ifd in exif_dict:
        if ifd == "thumbnail":
            continue
        for tag in exif_dict[ifd]:
            try:
                name = piexif.TAGS[ifd][tag]["name"]
            except KeyError:
                name = f"{ifd}/Tag_{tag}"
            flat[name] = decode_value(exif_dict[ifd][tag])
    return flat


def compare(file_a: str, file_b: str, *, verbose: bool = True) -> dict:
    """
    Compare EXIF metadata between two image files.

    Returns
    -------
    {
        "only_in_a": {...},   # tags present in A but not B
        "only_in_b": {...},   # tags present in B but not A
        "changed":   {...},   # tags present in both but with different values
        "unchanged": [...],   # tag names that are identical
    }
    """
    for f in (file_a, file_b):
        if not os.path.isfile(f):
            print(f"[pheser]  File not found: {f}")
            return {}

    meta_a = _load_flat(file_a)
    meta_b = _load_flat(file_b)

    keys_a = set(meta_a)
    keys_b = set(meta_b)

    result = {
        "only_in_a": {k: meta_a[k] for k in keys_a - keys_b},
        "only_in_b": {k: meta_b[k] for k in keys_b - keys_a},
        "changed":   {k: {"a": meta_a[k], "b": meta_b[k]}
                      for k in keys_a & keys_b if meta_a[k] != meta_b[k]},
        "unchanged": sorted(k for k in keys_a & keys_b if meta_a[k] == meta_b[k]),
    }

    if verbose:
        _print_diff(file_a, file_b, result)

    return result


def _print_diff(a: str, b: str, diff: dict):
    W = 52
    print("═" * W)
    print("  Pheser — EXIF DIFF")
    print("═" * W)
    print(f"  A : {a}")
    print(f"  B : {b}")
    print("─" * W)

    if diff["only_in_a"]:
        print(f"\n   Only in A ({len(diff['only_in_a'])} tag(s)):")
        for k, v in diff["only_in_a"].items():
            print(f"    - {k}: {v}")

    if diff["only_in_b"]:
        print(f"\n   Only in B ({len(diff['only_in_b'])} tag(s)):")
        for k, v in diff["only_in_b"].items():
            print(f"    + {k}: {v}")

    if diff["changed"]:
        print(f"\n   Changed ({len(diff['changed'])} tag(s)):")
        for k, vals in diff["changed"].items():
            print(f"    ~ {k}")
            print(f"        A: {vals['a']}")
            print(f"        B: {vals['b']}")

    if diff["unchanged"]:
        print(f"\n   Unchanged : {len(diff['unchanged'])} tag(s)")

    print("\n" + "═" * W)