#!/usr/bin/env python3
"""Resolve a WeChat brand profile and content track without reading credentials."""

from __future__ import annotations

import argparse
import json
import re
import sys
from pathlib import Path
from typing import Any


PROFILE_PATH = Path(__file__).resolve().parents[1] / "profiles" / "brand_profiles.json"
ACCOUNT_ID_RE = re.compile(r"^[a-z0-9][a-z0-9-]{0,47}$")


def load_profiles() -> dict[str, Any]:
    return json.loads(PROFILE_PATH.read_text(encoding="utf-8"))


def normalize(value: str) -> str:
    return re.sub(r"\s+", "", value).lower()


def score_keywords(text: str, keywords: list[str]) -> tuple[int, list[str]]:
    normalized = normalize(text)
    matched = [keyword for keyword in keywords if normalize(keyword) in normalized]
    return len(matched), matched


def resolve_track(profile: dict[str, Any], text: str) -> dict[str, Any]:
    candidates = []
    for track_id, track in profile.get("tracks", {}).items():
        score, matched = score_keywords(text, track.get("keywords", []))
        candidates.append(
            {
                "id": track_id,
                "label": track.get("label", track_id),
                "score": score,
                "matched_keywords": matched,
            }
        )
    candidates.sort(key=lambda item: (-item["score"], item["id"]))
    best = candidates[0] if candidates else None
    if not best or best["score"] == 0:
        track_id = profile.get("default_track")
        best = next((item for item in candidates if item["id"] == track_id), best)
    return {"recommended": best, "candidates": candidates}


def resolve(text: str, forced_profile: str | None = None) -> dict[str, Any]:
    data = load_profiles()
    profiles = data.get("profiles", [])
    by_id = {profile["id"]: profile for profile in profiles}

    if forced_profile:
        if not ACCOUNT_ID_RE.fullmatch(forced_profile) or forced_profile not in by_id:
            raise ValueError(f"Unknown brand profile: {forced_profile}")
        selected = by_id[forced_profile]
        profile_result = {
            "id": selected["id"],
            "display_name": selected["display_name"],
            "score": None,
            "matched_keywords": [],
            "forced": True,
        }
    else:
        scored = []
        for profile in profiles:
            score, matched = score_keywords(text, profile.get("routing_keywords", []))
            scored.append(
                {
                    "id": profile["id"],
                    "display_name": profile["display_name"],
                    "score": score,
                    "matched_keywords": matched,
                    "forced": False,
                }
            )
        scored.sort(key=lambda item: (-item["score"], item["id"]))
        profile_result = scored[0] if scored else None
        selected = by_id[profile_result["id"]] if profile_result else None

    if not selected or not profile_result:
        raise ValueError("No brand profiles are configured.")

    track_result = resolve_track(selected, text)
    score = profile_result["score"]
    candidates = [] if forced_profile else [
        {
            "id": profile["id"],
            "display_name": profile["display_name"],
        }
        for profile in profiles
    ]
    return {
        "profile": profile_result,
        "track": track_result,
        "profile_candidates": candidates,
        "needs_user_confirmation": not bool(forced_profile),
        "confidence": "explicit" if forced_profile else ("high" if score and score >= 2 else "low"),
        "security_note": "This resolver never reads credentials or account secret files.",
    }


def main() -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    source = parser.add_mutually_exclusive_group()
    source.add_argument("--text", help="Article brief or user input to classify")
    source.add_argument("--file", type=Path, help="UTF-8 text/Markdown input to classify")
    parser.add_argument("--profile", help="Explicit profile id; bypass inference but still require confirmation upstream")
    parser.add_argument("--list", action="store_true", help="List available profiles")
    args = parser.parse_args()

    try:
        if args.list:
            print(json.dumps(load_profiles().get("profiles", []), ensure_ascii=False, indent=2))
            return 0
        if args.file:
            text = args.file.read_text(encoding="utf-8")
        else:
            text = args.text or ""
        if not text and not args.profile:
            parser.error("one of --text, --file, or --profile is required")
        print(json.dumps(resolve(text, args.profile), ensure_ascii=False, indent=2))
        return 0
    except (OSError, UnicodeError, ValueError, json.JSONDecodeError) as exc:
        print(f"Error: {exc}", file=sys.stderr)
        return 1


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