"""Discover PDFs in the configured inbox, optional CLI paths, or an interactive path prompt."""

from __future__ import annotations

import sys
from pathlib import Path
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from folio_notion.pipeline_context import PipelineContext


def _gather_pdfs_from_path(p: Path) -> list[Path]:
    p = p.expanduser()
    if not p.exists():
        return []
    if p.is_file():
        return [p.resolve()] if p.suffix.lower() == ".pdf" else []
    if p.is_dir():
        return sorted(p.glob("*.pdf")) + sorted(p.glob("*.PDF"))
    return []


def _parse_path_line(raw: str) -> list[Path]:
    parts = [s.strip().strip('"').strip("'") for s in raw.split(",")]
    out: list[Path] = []
    for s in parts:
        if not s:
            continue
        out.append(Path(s).expanduser())
    return out


def collect_pdf_paths(inbox: Path, extras: list[Path]) -> list[Path]:
    """Inbox PDFs plus files/dirs from ``extras``; stable order, no duplicates."""
    inbox.mkdir(parents=True, exist_ok=True)
    seen: set[Path] = set()
    out: list[Path] = []

    def add(path: Path) -> None:
        r = path.resolve()
        if r not in seen:
            seen.add(r)
            out.append(r)

    for p in sorted(inbox.glob("*.pdf")) + sorted(inbox.glob("*.PDF")):
        add(p)
    for e in extras:
        for q in _gather_pdfs_from_path(e):
            add(q)
    return out


def run(ctx: PipelineContext) -> None:
    inbox = Path(ctx.config["input_dir"])
    extras = [Path(p) for p in ctx.cli_pdf_paths]
    ctx.pdf_paths = collect_pdf_paths(inbox, extras)
    if ctx.pdf_paths:
        return

    if not sys.stdin.isatty():
        raise RuntimeError(
            f"No PDFs in {inbox}. Add files, use: fn run --pdf PATH [PATH ...], "
            "or set input_dir in config."
        )

    from folio_notion.prompts import prompt_line

    hint = (
        f"No PDFs in {inbox}.\n"
        "Enter path(s) to .pdf file(s) or folder(s) (comma-separated), or Enter to quit: "
    )
    line = prompt_line(hint)
    if not line.strip():
        raise RuntimeError(
            f"No PDFs to process. Drop .pdf files in {inbox}, or run: fn run --pdf /path/to/file.pdf"
        )

    more: list[Path] = []
    for part in _parse_path_line(line):
        if not part.exists():
            raise RuntimeError(f"Not found: {part}")
        more.append(part)

    ctx.pdf_paths = collect_pdf_paths(inbox, extras + more)
    if not ctx.pdf_paths:
        raise RuntimeError(
            "No PDF files found at those paths (need .pdf files or folders containing them)."
        )
