#!/usr/bin/env python3
"""Download the entitled childcare feed and create a prefilled review worksheet."""

from __future__ import annotations

import argparse
import csv
import getpass
import json
import os
import sys
from pathlib import Path
from urllib.error import HTTPError, URLError
from urllib.parse import urlencode
from urllib.request import Request, urlopen

BASE_URL = "https://daleads.com.au/api/v1/das"
REVIEW_FIELDS = (
    "customer_match", "customer_source", "customer_record_id",
    "classification_review", "review_notes",
)
SOURCE_FIELDS = (
    "id", "council_reference", "address", "suburb", "postcode", "council",
    "state", "lodgement_date", "childcare_pipeline_stage",
    "childcare_works_type", "status", "decision_status", "description",
    "latitude", "longitude", "feed_match_reason", "feed_match_confidence",
    "observed_at", "info_url",
)


def _spreadsheet_safe(value: object) -> object:
    """Keep council-originated text from being evaluated as a spreadsheet formula."""
    if not isinstance(value, str):
        return value
    probe = value.lstrip(" \t\r\n")
    if probe.startswith(("=", "+", "-", "@")) or value.startswith(("\t", "\r", "\n")):
        return "'" + value
    return value


def _fetch_page(base_url: str, key: str, page: int, state: str | None) -> dict:
    query: dict[str, object] = {"page": page, "per_page": 100}
    if state:
        query["state"] = state.upper()
    request = Request(
        f"{base_url}?{urlencode(query)}",
        headers={
            "Authorization": f"Bearer {key}",
            "User-Agent": "DA-Leads-Trial-Reconciliation/1.0",
        },
    )
    with urlopen(request, timeout=60) as response:
        return json.load(response)


def build_worksheet(
    base_url: str, key: str, output: Path, state: str | None, *, force: bool = False
) -> int:
    if output.exists() and not force:
        raise FileExistsError(
            f"{output} already exists; choose another --output or use --force to replace it"
        )
    rows: list[dict] = []
    page = 1
    while True:
        payload = _fetch_page(base_url, key, page, state)
        rows.extend(payload.get("data") or [])
        pages = int((payload.get("meta") or {}).get("pages") or 1)
        if page >= pages:
            break
        page += 1
    output.parent.mkdir(parents=True, exist_ok=True)
    with output.open("w", newline="", encoding="utf-8-sig") as handle:
        writer = csv.DictWriter(
            handle, fieldnames=SOURCE_FIELDS + REVIEW_FIELDS, extrasaction="ignore"
        )
        writer.writeheader()
        for row in rows:
            safe_row = {
                field: _spreadsheet_safe(row.get(field, "")) for field in SOURCE_FIELDS
            }
            writer.writerow({**safe_row, **{field: "" for field in REVIEW_FIELDS}})
    return len(rows)


def main() -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument(
        "--output", type=Path, default=Path("childcare-trial-review.csv")
    )
    parser.add_argument(
        "--state", help="Optional state code; omit for the full entitled national feed"
    )
    parser.add_argument(
        "--force", action="store_true", help="Replace an existing output file"
    )
    parser.add_argument("--base-url", default=BASE_URL, help=argparse.SUPPRESS)
    args = parser.parse_args()
    key = os.getenv("DALEADS_API_KEY") or getpass.getpass("DA Leads API key: ")
    if not key:
        parser.error("set DALEADS_API_KEY or enter the assigned key at the prompt")
    try:
        count = build_worksheet(
            args.base_url, key, args.output, args.state, force=args.force
        )
    except FileExistsError as exc:
        print(str(exc), file=sys.stderr)
        return 2
    except HTTPError as exc:
        detail = exc.read().decode("utf-8", errors="replace")
        print(f"API request failed ({exc.code}): {detail}", file=sys.stderr)
        return 1
    except URLError as exc:
        print(f"Network request failed: {exc.reason}", file=sys.stderr)
        return 1
    print(f"Wrote {count} entitled rows to {args.output}")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
