#!/usr/bin/env python3
"""Resolve user language to independently pageable CARBON flow files."""

from __future__ import annotations

import argparse
import json
import re
from pathlib import Path

SKILL_ROOT = Path(__file__).resolve().parents[1]
FLOW_ROOT = SKILL_ROOT / "references" / "flows"
MANDATORY = ["core-oracles.md", "boundaries-and-payloads.md", "report-contract.md"]

ALIASES = {
    "signup": "identity/signup-registration.md",
    "sign up": "identity/signup-registration.md",
    "registration": "identity/signup-registration.md",
    "register": "identity/signup-registration.md",
    "login": "identity/sign-in.md",
    "log in": "identity/sign-in.md",
    "sign in": "identity/sign-in.md",
    "logout": "identity/sign-out-session-end.md",
    "log out": "identity/sign-out-session-end.md",
    "sign out": "identity/sign-out-session-end.md",
    "email verification": "identity/email-verification.md",
    "verify email": "identity/email-verification.md",
    "password reset": "identity/password-reset.md",
    "forgot password": "identity/password-reset.md",
    "mfa": "identity/mfa-enrollment-and-challenge.md",
    "2fa": "identity/mfa-enrollment-and-challenge.md",
    "sso": "identity/sso-social-login.md",
    "social login": "identity/sso-social-login.md",
    "invite": "identity/invitation-acceptance.md",
    "invitation": "identity/invitation-acceptance.md",
    "profile update": "identity/profile-and-account-update.md",
    "account settings": "identity/profile-and-account-update.md",
    "delete account": "identity/account-deletion.md",
    "account deletion": "identity/account-deletion.md",
    "product discovery": "commerce/product-discovery.md",
    "browse products": "commerce/product-discovery.md",
    "product search": "commerce/product-discovery.md",
    "product detail": "commerce/product-detail-and-configuration.md",
    "product configuration": "commerce/product-detail-and-configuration.md",
    "cart": "commerce/cart-management.md",
    "shopping cart": "commerce/cart-management.md",
    "checkout": "commerce/checkout.md",
    "coupon": "commerce/promotion-and-gift-card.md",
    "promo": "commerce/promotion-and-gift-card.md",
    "gift card": "commerce/promotion-and-gift-card.md",
    "payment": "commerce/payment-and-3ds.md",
    "3ds": "commerce/payment-and-3ds.md",
    "order confirmation": "commerce/order-confirmation.md",
    "order history": "commerce/order-history-and-tracking.md",
    "order tracking": "commerce/order-history-and-tracking.md",
    "cancel order": "commerce/order-cancellation.md",
    "order cancellation": "commerce/order-cancellation.md",
    "return": "commerce/return-refund-exchange.md",
    "refund": "commerce/return-refund-exchange.md",
    "exchange": "commerce/return-refund-exchange.md",
    "start subscription": "commerce/subscription-start-and-renew.md",
    "renew subscription": "commerce/subscription-start-and-renew.md",
    "subscription renewal": "commerce/subscription-start-and-renew.md",
    "cancel subscription": "commerce/subscription-change-cancel-resume.md",
    "change subscription": "commerce/subscription-change-cancel-resume.md",
    "upgrade plan": "commerce/subscription-change-cancel-resume.md",
    "downgrade plan": "commerce/subscription-change-cancel-resume.md",
    "onboarding": "productivity/onboarding-and-first-value.md",
    "first value": "productivity/onboarding-and-first-value.md",
    "crud": "productivity/create-edit-delete-record.md",
    "create record": "productivity/create-edit-delete-record.md",
    "edit record": "productivity/create-edit-delete-record.md",
    "delete record": "productivity/create-edit-delete-record.md",
    "search filter sort": "productivity/search-filter-sort.md",
    "upload": "productivity/upload-process-download.md",
    "download": "productivity/upload-process-download.md",
    "import": "productivity/import-data.md",
    "export": "productivity/export-data.md",
    "share": "productivity/share-and-permissions.md",
    "permissions": "productivity/share-and-permissions.md",
    "comment": "productivity/comments-mentions-notifications.md",
    "mention": "productivity/comments-mentions-notifications.md",
    "approval": "productivity/approval-and-review.md",
    "review workflow": "productivity/approval-and-review.md",
    "booking": "productivity/schedule-and-book.md",
    "scheduling": "productivity/schedule-and-book.md",
    "message": "engagement/messaging.md",
    "chat": "engagement/messaging.md",
    "settings": "engagement/settings-preferences.md",
    "preferences": "engagement/settings-preferences.md",
    "support": "engagement/support-ticket.md",
    "support ticket": "engagement/support-ticket.md",
    "consent": "engagement/consent-and-privacy-controls.md",
    "privacy controls": "engagement/consent-and-privacy-controls.md",
    "offline": "resilience/offline-edit-and-sync.md",
    "sync": "resilience/offline-edit-and-sync.md",
    "data export request": "resilience/data-export-and-erasure.md",
    "data export and erasure": "resilience/data-export-and-erasure.md",
    "data erasure": "resilience/data-export-and-erasure.md",
    "right to delete": "resilience/data-export-and-erasure.md",
    "ai generate": "ai/ai-generate-review-accept.md",
    "ai review": "ai/ai-generate-review-accept.md",
    "rag": "ai/ai-retrieval-and-citations.md",
    "citations": "ai/ai-retrieval-and-citations.md",
    "ai agent": "ai/ai-agent-action-confirmation.md",
    "agent action": "ai/ai-agent-action-confirmation.md",
    "automation": "ai/automation-create-run-monitor.md",
    "workflow automation": "ai/automation-create-run-monitor.md",
}


def normalize(value: str) -> str:
    return re.sub(r"[^a-z0-9]+", " ", value.lower()).strip()


def select(query: str) -> list[str]:
    normalized = normalize(query)
    matched: list[str] = []
    for alias, relative in sorted(
        ALIASES.items(), key=lambda item: len(item[0]), reverse=True
    ):
        normalized_alias = normalize(alias)
        matches_alias = normalized == normalized_alias or re.search(
            rf"(?:^|\s){re.escape(normalized_alias)}(?:$|\s)", normalized
        )
        if matches_alias and relative not in matched:
            matched.append(relative)

    # Alias matches are precise, but one match must not suppress a second flow
    # expressed with product-specific nouns. For example, "create, edit, delete
    # task, and settings" should select both record lifecycle and settings.
    tokens = {token for token in normalized.split() if len(token) >= 3}
    scored: list[tuple[int, str]] = []
    for path in FLOW_ROOT.glob("*/*.md"):
        if path.name == "index.md":
            continue
        haystack = normalize(
            f"{path.stem} {path.read_text(encoding='utf-8').splitlines()[0]}"
        )
        score = sum(token in haystack.split() for token in tokens)
        if score:
            scored.append((score, str(path.relative_to(FLOW_ROOT))))

    minimum_score = 2 if matched else 1
    for score, relative in sorted(scored, reverse=True):
        if score < minimum_score:
            continue
        if relative not in matched:
            matched.append(relative)
        if len(matched) >= 5:
            break
    return matched


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "query", nargs="+", help="Flow name or natural-language description"
    )
    parser.add_argument("--json", action="store_true")
    args = parser.parse_args()
    query = " ".join(args.query)
    matches = select(query)
    payload = {
        "query": query,
        "matches": [
            {
                "flow": Path(relative).stem,
                "reference": f"flows/{relative}",
            }
            for relative in matches
        ],
        "references": MANDATORY + [f"flows/{relative}" for relative in matches],
        "note": "Load only the matched flow files, then add the item files evidenced by the artifact.",
    }
    if args.json:
        print(json.dumps(payload, indent=2))
    else:
        for reference in payload["references"]:
            print(reference)
    return 0 if matches else 1


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