from __future__ import annotations

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

from src.errors import UserError
from src.organize.organizer import organize_files
from src.organize.path_builder import build_folder_path
from src.logging_setup import log_event

logger = logging.getLogger(__name__)

OUTPUT_ROOT_ENV_VAR = "OUTPUT_ROOT"


def register(sub: argparse._SubParsersAction) -> None:
    org = sub.add_parser(
        "organize", help="Organize outputs into Regio/Plaats/Venue/YYYY/MM/ folders."
    )
    org_sub = org.add_subparsers(dest="organize_cmd", required=True)

    preview = org_sub.add_parser("preview", help="Preview the folder path.")
    _add_common_args(preview, include_root=False)
    preview.set_defaults(_handler=_run_preview)

    run = org_sub.add_parser("run", help="Create folder and optionally copy/move files into it.")
    _add_common_args(run, include_root=True)
    run.add_argument(
        "--strategy",
        choices=["copy", "move"],
        default="copy",
        help="File strategy (default: copy).",
    )
    run.add_argument(
        "--paths", nargs="*", default=[], help="Source file paths to copy/move into the folder."
    )
    run.add_argument(
        "--dry-run", action="store_true", help="Do not create folders or copy/move files."
    )
    run.set_defaults(_handler=_run)


def _add_common_args(parser: argparse.ArgumentParser, *, include_root: bool) -> None:
    if include_root:
        parser.add_argument(
            "--root", help=f"Root directory to organize into (or env {OUTPUT_ROOT_ENV_VAR})."
        )
    parser.add_argument("--region", required=True, help="Region name.")
    parser.add_argument("--place", required=True, help="Place name.")
    parser.add_argument("--venue", required=True, help="Venue name.")
    parser.add_argument("--date", dest="event_date", required=True, help="Event date (YYYY-MM-DD).")


def _run_preview(args: argparse.Namespace) -> int:
    log_event(logger, "command.start", command="organize.preview")
    folder = build_folder_path(
        region=args.region,
        place=args.place,
        venue=args.venue,
        event_date=_parse_date(args.event_date),
    )
    print(folder.relpath())
    log_event(logger, "command.complete", command="organize.preview")
    return 0


def _run(args: argparse.Namespace) -> int:
    log_event(logger, "command.start", command="organize.run")
    root = _load_root_dir(args.root)
    folder = build_folder_path(
        region=args.region,
        place=args.place,
        venue=args.venue,
        event_date=_parse_date(args.event_date),
    )
    sources = [Path(p) for p in (args.paths or [])]
    result = organize_files(
        root_dir=root,
        folder_path=folder,
        source_files=sources,
        strategy=str(args.strategy),
        dry_run=bool(args.dry_run),
    )
    print(result.to_human_summary())
    log_event(logger, "command.complete", command="organize.run")
    return 0


def _parse_date(raw: str) -> date:
    try:
        return date.fromisoformat(str(raw))
    except ValueError as exc:
        raise UserError("Date must be in YYYY-MM-DD format.") from exc


def _load_root_dir(root_arg: str | None) -> Path:
    raw = (root_arg or "").strip() or os.environ.get(OUTPUT_ROOT_ENV_VAR, "").strip()
    if not raw:
        raise UserError(f"Missing root directory. Pass --root or set {OUTPUT_ROOT_ENV_VAR}.")
    return Path(raw)
