#!/usr/bin/env python3
"""Fast path theme catalog presence & schema sanity validator.

Checks:
1. theme_list.json exists.
2. Loads JSON and ensures top-level keys present: themes (list), metadata_info (dict).
3. Basic field contract for each theme: id, theme, synergies (list), description.
4. Enforces presence of catalog_hash inside metadata_info for drift detection.
5. Optionally validates against Pydantic models if available (best effort).
Exit codes:
 0 success
 1 structural failure / missing file
 2 partial validation warnings elevated via --strict
"""
from __future__ import annotations
import sys
import json
import argparse
import pathlib
import typing as t

THEME_LIST_PATH = pathlib.Path('config/themes/theme_list.json')

class Problem:
    def __init__(self, level: str, message: str):
        self.level = level
        self.message = message
    def __repr__(self):
        return f"{self.level.upper()}: {self.message}"

def load_json(path: pathlib.Path) -> t.Any:
    try:
        return json.loads(path.read_text(encoding='utf-8') or '{}')
    except FileNotFoundError:
        raise
    except Exception as e:  # pragma: no cover
        raise RuntimeError(f"parse_error: {e}")

def validate(data: t.Any) -> list[Problem]:
    probs: list[Problem] = []
    if not isinstance(data, dict):
        probs.append(Problem('error','top-level not an object'))
        return probs
    themes = data.get('themes')
    if not isinstance(themes, list) or not themes:
        probs.append(Problem('error','themes list missing or empty'))
    meta = data.get('metadata_info')
    if not isinstance(meta, dict):
        probs.append(Problem('error','metadata_info missing or not object'))
    else:
        if not meta.get('catalog_hash'):
            probs.append(Problem('error','metadata_info.catalog_hash missing'))
        if not meta.get('generated_at'):
            probs.append(Problem('warn','metadata_info.generated_at missing'))
    # Per theme spot check (limit to first 50 to keep CI snappy)
    for i, th in enumerate(themes[:50] if isinstance(themes, list) else []):
        if not isinstance(th, dict):
            probs.append(Problem('error', f'theme[{i}] not object'))
            continue
        if not th.get('id'):
            probs.append(Problem('error', f'theme[{i}] id missing'))
        if not th.get('theme'):
            probs.append(Problem('error', f'theme[{i}] theme missing'))
        syns = th.get('synergies')
        if syns is None:
            probs.append(Problem('warn', f'theme[{i}] synergies missing'))
        elif not isinstance(syns, list):
            probs.append(Problem('warn', f'theme[{i}] synergies not a list'))
        else:
            bad_types = [type(item).__name__ for item in syns if not isinstance(item, str)]
            if bad_types:
                probs.append(Problem('warn', f'theme[{i}] synergies contain non-string entries: {set(bad_types)}'))
        if 'description' not in th:
            probs.append(Problem('warn', f'theme[{i}] description missing'))
    return probs

def main(argv: list[str]) -> int:
    ap = argparse.ArgumentParser(description='Validate fast path theme catalog build presence & schema.')
    ap.add_argument('--strict-warn', action='store_true', help='Promote warnings to errors (fail CI).')
    args = ap.parse_args(argv)
    if not THEME_LIST_PATH.exists():
        print('ERROR: theme_list.json missing at expected path.', file=sys.stderr)
        return 1
    try:
        data = load_json(THEME_LIST_PATH)
    except FileNotFoundError:
        print('ERROR: theme_list.json missing.', file=sys.stderr)
        return 1
    except Exception as e:
        print(f'ERROR: failed parsing theme_list.json: {e}', file=sys.stderr)
        return 1
    problems = validate(data)
    errors = [p for p in problems if p.level=='error']
    warns = [p for p in problems if p.level=='warn']
    for p in problems:
        stream = sys.stderr if p.level!='info' else sys.stdout
        print(repr(p), file=stream)
    if errors:
        return 1
    if args.strict_warn and warns:
        return 2
    print(f"Fast path validation ok: {len(errors)} errors, {len(warns)} warnings. Checked {min(len(data.get('themes', [])),50)} themes.")
    return 0

if __name__ == '__main__':
    raise SystemExit(main(sys.argv[1:]))
