from __future__ import annotations

import argparse
import logging
from datetime import date
from pathlib import Path

from src.commands.date_range import parse_date_range
from src.config.matching_config import load_matching_config
from src.config.pipedrive_config import load_pipedrive_config
from src.exif.exif import read_exif
from src.matching.io import iter_image_files, validate_inbox_dir
from src.matching.matching import match_photo
from src.pipedrive.client import PipedriveClient
from src.pipedrive.mapping import (
    NormalizedDeal,
    load_mapping_file,
    normalize_deals_in_range,
    resolve_mapping,
)
from src.logging_setup import log_event

logger = logging.getLogger(__name__)


def register(sub: argparse._SubParsersAction) -> None:
    match = sub.add_parser("match", help="Match photos to deals (date window + distance).")
    match.add_argument("--inbox", required=True, help="Inbox folder path.")
    match.add_argument("--from", dest="from_date", required=True, help="Start date (YYYY-MM-DD).")
    match.add_argument("--to", dest="to_date", required=True, help="End date (YYYY-MM-DD).")
    match.add_argument(
        "--mapping", help="Path to mapping JSON file (else env PIPEDRIVE_FIELD_MAPPING_PATH)."
    )
    match.add_argument(
        "--dry-run", action="store_true", help="Do not write outputs (match is read-only)."
    )
    match.set_defaults(_handler=_run)


def _run(args: argparse.Namespace) -> int:
    log_event(logger, "command.start", command="match")
    inbox = Path(args.inbox)
    validate_inbox_dir(inbox)
    from_d, to_d = parse_date_range(args.from_date, args.to_date)

    cfg = load_pipedrive_config(mapping_path_override=Path(args.mapping) if args.mapping else None)
    match_cfg = load_matching_config()
    deals = _load_deals(cfg.api_token, cfg.base_url, cfg.mapping_path, from_d, to_d)

    for path in iter_image_files(inbox):
        photo = read_exif(path)
        result = match_photo(photo, deals, match_cfg)
        print(result.to_json())
    log_event(logger, "command.complete", command="match")
    return 0


def _load_deals(
    api_token: str,
    base_url: str,
    mapping_path: Path,
    from_d: date,
    to_d: date,
) -> list[NormalizedDeal]:
    client = PipedriveClient(api_token=api_token, base_url=base_url)
    deal_fields = client.list_deal_fields()
    mapping_data = load_mapping_file(mapping_path)
    mapping = resolve_mapping(mapping_data, deal_fields)
    return normalize_deals_in_range(client.iter_deals(), mapping, from_date=from_d, to_date=to_d)
