#!/usr/bin/env python3
"""Select the smallest CARBON item-test files for detected product elements."""

from __future__ import annotations

import argparse
import json
import re
from collections import defaultdict

ALWAYS = ["core-oracles.md", "boundaries-and-payloads.md", "report-contract.md"]


def entries(start: int, names: str) -> list[tuple[int, str]]:
    return [(start + i, name) for i, name in enumerate(names.split("|"))]


ELEMENTS = [
    *entries(1, "company|person|contact|lead|deal|account|user|team|role|opportunity"),
    *entries(11, "product|service|project|task|subtask"),
    *entries(16, "doc|file|note|event|meeting"),
    *entries(21, "invoice|payment|subscription|plan|price"),
    *entries(26, "campaign|message|email|call|activity"),
    *entries(31, "workflow|template|tag|location|vendor"),
    *entries(36, "status|boolean|date|datetime|number"),
    *entries(41, "currency|percent|text|url|email"),
    *entries(46, "phone|address|json|enum|id"),
    *entries(51, "owner|created at|updated at|start date|due date"),
    *entries(56, "priority|score|count|duration|time"),
    *entries(61, "create|update|assign|delete|view"),
    *entries(66, "search|filter|sort|group|import"),
    *entries(71, "export|duplicate|notify|remind|message"),
    *entries(76, "approve|reject|archive|restore|escalate"),
    *entries(81, "trigger|schedule|run|stop|cancel"),
    *entries(86, "grid|list|kanban|calendar|gallery"),
    *entries(91, "map|timeline|table|board|chart"),
    *entries(96, "detail|card|feed|form|tree"),
    *entries(
        101, "ai search|summarize|extract|classify|generate|prompt|recommend|analyze"
    ),
    *entries(
        109, "permission|policy|rule trigger|rule schedule|condition|rule action|audit"
    ),
]


def refs(*paths: str) -> tuple[str, ...]:
    return tuple(f"items/{path}.md" for path in paths)


ITEM_BY_NUMBER = {
    1: refs("records/company-account-vendor"),
    2: refs("identity/person-contact-and-profile"),
    3: refs(
        "identity/person-contact-and-profile", "records/lead-contact-opportunity-deal"
    ),
    4: refs("records/lead-contact-opportunity-deal"),
    5: refs("records/lead-contact-opportunity-deal"),
    6: refs("records/company-account-vendor", "identity/account-and-user-lifecycle"),
    7: refs("identity/account-and-user-lifecycle"),
    8: refs("identity/team-membership-role-owner-assignment"),
    9: refs("identity/team-membership-role-owner-assignment", "automation/permission"),
    10: refs("records/lead-contact-opportunity-deal"),
    11: refs("records/product-service-plan-price"),
    12: refs("records/product-service-plan-price"),
    13: refs("records/project-task-subtask"),
    14: refs("records/project-task-subtask"),
    15: refs("records/project-task-subtask"),
    16: refs("content/document-note-template"),
    17: refs(
        "content/upload-and-file-input", "content/download-and-export-file-delivery"
    ),
    18: refs("content/document-note-template"),
    19: refs("data/calendar-event-meeting-recurrence"),
    20: refs("data/calendar-event-meeting-recurrence", "content/call-and-meeting-link"),
    21: refs("records/invoice"),
    22: refs("records/payment"),
    23: refs("records/subscription"),
    24: refs("records/product-service-plan-price", "records/subscription"),
    25: refs("records/product-service-plan-price", "data/currency-price-totals"),
    26: refs("records/activity-campaign"),
    27: refs("content/in-app-message-chat-feed-item"),
    28: refs("content/email-and-outbound-message", "controls/email-address"),
    29: refs("content/call-and-meeting-link"),
    30: refs("records/activity-campaign"),
    31: refs("automation/workflow-graph"),
    32: refs("automation/template", "content/document-note-template"),
    33: refs("organization/tag"),
    34: refs(
        "controls/address", "specialized-controls/geolocation-and-device-permissions"
    ),
    35: refs("records/company-account-vendor"),
    36: refs("organization/enum-and-status-value"),
    37: refs("controls/checkbox", "controls/toggle-switch"),
    38: refs("data/date"),
    39: refs("data/datetime"),
    40: refs("data/number"),
    41: refs("data/currency-price-totals"),
    42: refs("data/score-percent-probability-priority"),
    43: refs("controls/text-input"),
    44: refs("controls/url", "organization/url-and-deep-link-state"),
    45: refs("controls/email-address"),
    46: refs("controls/phone"),
    47: refs("controls/address"),
    48: refs("organization/json-and-structured-payload"),
    49: refs("organization/enum-and-status-value"),
    50: refs("organization/id"),
    51: refs("identity/team-membership-role-owner-assignment"),
    52: refs("data/record-timestamps"),
    53: refs("data/record-timestamps"),
    54: refs("data/record-timestamps"),
    55: refs("data/record-timestamps"),
    56: refs("data/score-percent-probability-priority"),
    57: refs("data/score-percent-probability-priority"),
    58: refs("data/count-and-quantity"),
    59: refs("data/time-of-day-and-duration"),
    60: refs("data/time-of-day-and-duration"),
    61: refs("actions/create"),
    62: refs("actions/update"),
    63: refs("actions/assign-and-ownership"),
    64: refs("actions/delete"),
    65: refs("actions/view-read"),
    66: refs("organization/search"),
    67: refs("organization/filter"),
    68: refs("organization/sort"),
    69: refs("organization/group-and-aggregate"),
    70: refs("content/import"),
    71: refs("content/export"),
    72: refs("actions/duplicate"),
    73: refs("content/notification-and-reminder"),
    74: refs("content/notification-and-reminder"),
    75: refs("content/in-app-message-chat-feed-item"),
    76: refs("actions/approve-reject"),
    77: refs("actions/approve-reject"),
    78: refs("actions/archive-restore"),
    79: refs("actions/archive-restore"),
    80: refs("actions/escalate"),
    81: refs("automation/trigger"),
    82: refs("automation/schedule"),
    83: refs("actions/run-start-stop-cancel"),
    84: refs("actions/run-start-stop-cancel"),
    85: refs("actions/run-start-stop-cancel"),
    86: refs("views/grid"),
    87: refs("views/list"),
    88: refs("views/kanban-and-board"),
    89: refs("views/calendar"),
    90: refs("views/gallery"),
    91: refs("views/map"),
    92: refs("views/timeline-and-feed"),
    93: refs("views/table"),
    94: refs("views/kanban-and-board"),
    95: refs("views/chart"),
    96: refs("views/detail"),
    97: refs("views/card"),
    98: refs("views/timeline-and-feed"),
    99: refs("views/form-view", "controls/form-composition"),
    100: refs("views/tree"),
    101: refs("ai/ai-search-and-retrieval"),
    102: refs("ai/summarize"),
    103: refs("ai/extract"),
    104: refs("ai/classify"),
    105: refs("ai/generate"),
    106: refs("ai/prompt-surface"),
    107: refs("ai/recommend"),
    108: refs("ai/analyze"),
    109: refs("automation/permission"),
    110: refs("automation/policy"),
    111: refs("automation/trigger"),
    112: refs("automation/schedule"),
    113: refs("automation/condition-and-rule-expression"),
    114: refs("automation/automated-action"),
    115: refs("automation/audit"),
}


ALIASES = {
    "textbox": refs("controls/text-input"),
    "text box": refs("controls/text-input"),
    "textarea": refs("controls/multiline-text"),
    "contenteditable": refs("controls/multiline-text"),
    "rich text": refs("controls/multiline-text"),
    "username": refs("controls/username"),
    "handle": refs("controls/username"),
    "password": refs("controls/password"),
    "passkey": refs("identity/login"),
    "mfa": refs("identity/mfa-and-one-time-codes"),
    "2fa": refs("identity/mfa-and-one-time-codes"),
    "otp": refs("identity/mfa-and-one-time-codes"),
    "login": refs("identity/login", "controls/username", "controls/password"),
    "log in": refs("identity/login", "controls/username", "controls/password"),
    "sign in": refs("identity/login", "controls/username", "controls/password"),
    "signup": refs(
        "identity/registration-and-invitation", "controls/username", "controls/password"
    ),
    "sign up": refs(
        "identity/registration-and-invitation", "controls/username", "controls/password"
    ),
    "logout": refs("identity/session-lifecycle"),
    "session": refs("identity/session-lifecycle"),
    "checkbox": refs("controls/checkbox"),
    "radio": refs("controls/radio-group"),
    "dropdown": refs("controls/select-combobox-autocomplete-multi-select"),
    "select": refs("controls/select-combobox-autocomplete-multi-select"),
    "combobox": refs("controls/select-combobox-autocomplete-multi-select"),
    "autocomplete": refs("controls/select-combobox-autocomplete-multi-select"),
    "multi-select": refs("controls/select-combobox-autocomplete-multi-select"),
    "toggle": refs("controls/toggle-switch"),
    "switch": refs("controls/toggle-switch"),
    "slider": refs("specialized-controls/slider-range-stepper"),
    "range": refs("specialized-controls/slider-range-stepper"),
    "stepper": refs("specialized-controls/slider-range-stepper"),
    "rating": refs("specialized-controls/rating"),
    "color picker": refs("specialized-controls/color-picker"),
    "progress": refs("specialized-controls/progress-meter-skeleton"),
    "meter": refs("specialized-controls/progress-meter-skeleton"),
    "audio": refs("specialized-controls/audio-and-video-player"),
    "video": refs("specialized-controls/audio-and-video-player"),
    "media player": refs("specialized-controls/audio-and-video-player"),
    "camera": refs("specialized-controls/camera-microphone-recording"),
    "microphone": refs("specialized-controls/camera-microphone-recording"),
    "image editor": refs(
        "specialized-controls/image-editor-cropper-annotation-signature-canvas"
    ),
    "cropper": refs(
        "specialized-controls/image-editor-cropper-annotation-signature-canvas"
    ),
    "signature": refs(
        "specialized-controls/image-editor-cropper-annotation-signature-canvas"
    ),
    "canvas": refs(
        "specialized-controls/image-editor-cropper-annotation-signature-canvas"
    ),
    "code editor": refs("specialized-controls/code-editor-and-structured-text-editor"),
    "command palette": refs(
        "specialized-controls/command-palette-toolbar-keyboard-shortcut"
    ),
    "keyboard shortcut": refs(
        "specialized-controls/command-palette-toolbar-keyboard-shortcut"
    ),
    "clipboard": refs("specialized-controls/clipboard-share-print"),
    "print": refs("specialized-controls/clipboard-share-print"),
    "share sheet": refs("specialized-controls/clipboard-share-print"),
    "geolocation": refs("specialized-controls/geolocation-and-device-permissions"),
    "captcha": refs("specialized-controls/captcha-and-abuse-challenge"),
    "iframe": refs("specialized-controls/iframe-embedded-widget-third-party-surface"),
    "embed": refs("specialized-controls/iframe-embedded-widget-third-party-surface"),
    "carousel": refs("specialized-controls/carousel"),
    "pwa": refs("specialized-controls/pwa-install-and-offline"),
    "offline app": refs("specialized-controls/pwa-install-and-offline"),
    "button": refs("controls/button-and-icon-button"),
    "link": refs("controls/link"),
    "menu": refs("controls/menu-and-split-button"),
    "dialog": refs("controls/dialog-alert-dialog-drawer"),
    "modal": refs("controls/dialog-alert-dialog-drawer"),
    "popover": refs("controls/tooltip-popover-toast-banner"),
    "tooltip": refs("controls/tooltip-popover-toast-banner"),
    "toast": refs("controls/tooltip-popover-toast-banner"),
    "tabs": refs("controls/tabs-and-accordion"),
    "accordion": refs("controls/tabs-and-accordion"),
    "pagination": refs("controls/pagination-and-infinite-scroll"),
    "infinite scroll": refs("controls/pagination-and-infinite-scroll"),
    "drag": refs("controls/drag-drop-reorder-resize"),
    "drop zone": refs("content/upload-and-file-input"),
    "upload": refs("content/upload-and-file-input"),
    "download": refs("content/download-and-export-file-delivery"),
    "billing": refs("records/invoice", "records/payment", "records/subscription"),
    "checkout": refs("records/payment", "data/currency-price-totals"),
    "rbac": refs(
        "identity/team-membership-role-owner-assignment", "automation/permission"
    ),
    "access control": refs("automation/permission"),
    "automation": refs("automation/workflow-graph"),
    "agent": refs("ai/common-ai-baseline", "automation/workflow-graph"),
    "rag": refs("ai/ai-search-and-retrieval"),
    "chatbot": refs("ai/common-ai-baseline", "controls/multiline-text"),
}


def normalize(value: str) -> str:
    return re.sub(r"\s+", " ", re.sub(r"[_-]+", " ", value.casefold())).strip()


def main() -> int:
    parser = argparse.ArgumentParser(
        description="Select item-level CARBON test references for named controls or product elements."
    )
    parser.add_argument(
        "terms",
        nargs="+",
        help="Element names, numbers, or free-form artifact description",
    )
    parser.add_argument(
        "--json", action="store_true", help="Emit machine-readable JSON"
    )
    args = parser.parse_args()

    text = normalize(" ".join(args.terms))
    number_tokens = {
        int(n)
        for n in re.findall(r"\b(?:[1-9]\d?|1[01]\d)\b", text)
        if 1 <= int(n) <= 115
    }
    selected = set(ALWAYS)
    matches: dict[str, set[str]] = defaultdict(set)

    for number, name in ELEMENTS:
        normalized_name = normalize(name)
        if number in number_tokens or re.search(
            rf"\b{re.escape(normalized_name)}\b", text
        ):
            label = f"{number}:{name}"
            for filename in ITEM_BY_NUMBER[number]:
                selected.add(filename)
                matches[label].add(filename)

    for alias, files in ALIASES.items():
        if re.search(rf"\b{re.escape(normalize(alias))}\b", text):
            label = f"control:{alias}"
            for filename in files:
                selected.add(filename)
                matches[label].add(filename)

    ordered = [name for name in ALWAYS if name in selected]
    ordered += sorted(selected.difference(ALWAYS))
    result = {
        "query": " ".join(args.terms),
        "matches": {key: sorted(value) for key, value in sorted(matches.items())},
        "references": ordered,
        "note": "No semantic match"
        if not matches
        else "Read only these item files, then adapt cases to artifact evidence.",
    }

    if args.json:
        print(json.dumps(result, indent=2))
    else:
        print(f"Query: {result['query']}")
        if matches:
            print("Matches:")
            for label, files in result["matches"].items():
                print(f"  - {label}: {', '.join(files)}")
        else:
            print(
                "Matches: none; inspect the artifact and use catalog.md or items/index.md"
            )
        print("Read:")
        for filename in ordered:
            print(f"  - references/{filename}")
    return 0


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