"""위저드 상수와 단계 id — 픽 토큰, task-type 집합, `S_*` 단계 id, 멀티탭 그룹."""
from __future__ import annotations

import re

from okstra_ctl.analysis_inputs import ANALYSIS_TASK_TYPES
from okstra_ctl.models import picker_options


# ---- Constants -----------------------------------------------------------

_ANALYSIS_TASK_TYPE_DESCRIPTIONS = (
    "Map project structure and bounded codebase scope (read-only)",
    "Analyse feature behavior and test coverage scope (read-only)",
    "Assess change impact and preserved behavior (read-only)",
)


TASK_TYPES: list[tuple[str, str]] = [
    ("requirements-discovery", "Classify request and route to next safe phase"),
    ("improvement-discovery", "Find improvement candidates within a codebase scope and lens whitelist"),
    *zip(ANALYSIS_TASK_TYPES, _ANALYSIS_TASK_TYPE_DESCRIPTIONS),
    ("error-analysis", "Evidence-based root-cause analysis (no code changes)"),
    ("technical-verification", "Test unresolved technical facts in isolated experiment copies"),
    ("implementation-option-selection", "Compare implementation options (read-only)"),
    ("implementation-planning", "Plan options + request user approval"),
    ("implementation", "Execute approved plan (requires approved final-report)"),
    ("final-verification", "Acceptance + residual-risk review"),
    ("release-handoff", "Drive commit/push/PR — reuse the implementation task-key (new keys fail the empty-commits gate)"),
]


TASK_TYPE_VALUES = [tt for tt, _ in TASK_TYPES]


EXECUTORS = ["claude", "codex", "antigravity"]


# 역할 한 줄 설명 — defaults_or_custom 안내에서 각 역할이 무슨 일을 하는지 보여준다.
ROLE_BLURBS = {
    "lead": "Okstra lead · 워커 dispatch·교차검증 수렴·최종 합성",
    "claude": "독립 분석 워커 (Claude)",
    "codex": "독립 분석 워커 (Codex)",
    "antigravity": "독립 분석 워커 (Antigravity)",
    "grok": "독립 분석 워커 (Grok)",
    "kimi": "독립 분석 워커 (Kimi)",
    "report-writer": "최종 리포트 작성 (분석은 하지 않음)",
}


# Task types that consume an approved plan and need a stage-scope pick:
# implementation executes a stage, final-verification verifies a stage
# (or the whole task via `auto`). Both gate the approved-plan + stage steps.
_STAGE_SCOPED_TASK_TYPES = ("implementation", "final-verification")


# brief 는 entry phase 의 입력물(비개발자/타 팀의 아이디어·에러 초안)이다.
# downstream phase 는 task manifest 의 taskBriefPath 를 자동 carry-in 하며
# 위저드에서 brief 를 묻지 않는다 (release-handoff 는 prepare 가 검증 보고서
# 인용 input 문서를 자동 생성하므로 brief 자체가 없다).
_BRIEF_ENTRY_TASK_TYPES = (
    "requirements-discovery",
    "improvement-discovery",
    *ANALYSIS_TASK_TYPES,
    "error-analysis",
)


CANONICAL_BASE_REFS = ["main", "dev", "staging", "preprod", "prod"]


BASE_REF_FREE_INPUT_TOKEN = "__free_input__"


CLAUDE_MODEL_OPTIONS = ["default", *picker_options("claude")]


CODEX_MODEL_OPTIONS = ["default", *picker_options("codex")]


ANTIGRAVITY_MODEL_OPTIONS = ["default", *picker_options("antigravity")]


GROK_MODEL_OPTIONS = ["default", *picker_options("grok")]


KIMI_MODEL_OPTIONS = ["default", *picker_options("kimi")]


# special pick value: start a brand-new task
TASK_PICK_NEW_TOKEN = "__new__"


# AskUserQuestion renders at most 4 options per question; the last slot is
# always reserved for the direct-input option, so recommendation lists from
# dynamic sources (catalog, manifest) are capped at 3.
_RECOMMENDATION_CAP = 3


# Pick-vs-free-text tokens shared by suggestion-aware prompts.
PICK_USE_SUGGESTED = "__use_suggested__"


PICK_TYPE_CUSTOM = "__free_input__"


# 취소지 탈출구가 아니다 — 자유 입력 뒤에 올 수 있는 유일한 값.
_ABORT_OPTION = "__abort__"


# workers_override 에서 "옵션 워커를 추가하지 않음" 을 뜻하는 sentinel.
_DEFAULT_ROSTER_TOKEN = "__default_roster__"


_RECENT_PREFIX = "__recent:"


_REPORT_PREFIX = "__report:"


_BRIEF_PREFIX = "__brief:"


# brief 본문 머리 인용구에 okstra-brief-gen 이 적어 넣는 진입 phase 줄.
# `templates/reports/brief.template.md` 의 "> - Recommended next phase: <...>" 이고,
# 값 규칙은 `docs/for-ai/skills/okstra-brief-gen.md` § "Recommended next phase".
# 목록 표시(`- `)는 머리 인용구의 필드를 한 줄씩 렌더링시키려고 붙은 것이라
# 선택적으로 받는다 — 그 표시가 없던 옛 brief 도 그대로 읽힌다.
_BRIEF_NEXT_PHASE_RE = re.compile(
    r"^\s*>?\s*(?:[-*]\s+)?Recommended next phase\s*:\s*`?([a-z][a-z-]*)`?",
    re.IGNORECASE,
)


_BRIEF_HEAD_LINES = 60


# ---- Step IDs ------------------------------------------------------------

S_REPORT_LANGUAGE = "report_language"
S_TASK_PICK = "task_pick"


S_TASK_GROUP = "task_group"


S_TASK_GROUP_TEXT = "task_group_text"


S_TASK_ID = "task_id"


S_TASK_ID_TEXT = "task_id_text"


S_TASK_TYPE = "task_type"


S_TASK_TYPE_TEXT = "task_type_text"


S_BRIEF_KEEP = "brief_keep"


S_BRIEF_PATH_PICK = "brief_path_pick"


S_BRIEF_PATH = "brief_path"


S_BRIEF_CARRY = "brief_carry"


S_FEATURE_EVIDENCE_PICK = "feature_evidence_pick"


S_FEATURE_EVIDENCE = "feature_evidence"


S_PROJECT_EVIDENCE_PICK = "project_evidence_pick"


S_PROJECT_EVIDENCE = "project_evidence"


S_ANALYSIS_TARGET_PICK = "analysis_target_pick"


S_ANALYSIS_TARGET = "analysis_target"


S_BASE_REF_PICK = "base_ref_pick"


S_BASE_REF_TEXT = "base_ref_text"


S_SELECTED_DIRECTION_PICK = "selected_direction_pick"


S_APPROVED_PLAN_PICK = "approved_plan_pick"


S_APPROVED_PLAN = "approved_plan"


S_APPROVE_PLAN_CONFIRM = "approve_plan_confirm"


S_DESIGN_PREP_DECISION = "design_prep_decision"


S_DESIGN_PREP_OVERRIDES = "design_prep_overrides"


S_DESIGN_PREP_CONFIRM = "design_prep_confirm"


S_STAGE_PICK = "stage_pick"


S_HANDOFF_STAGE_PICK = "handoff_stage_pick"


S_EXECUTOR = "executor"


S_CRITIC_PICK = "critic_pick"


S_CRITIC_TEXT = "critic_text"


S_REUSE_PREVIOUS = "reuse_previous"


S_DEFAULTS_OR_CUSTOM = "defaults_or_custom"


S_WORKERS_OVERRIDE = "workers_override"


S_WORKERS_CUSTOM = "workers_custom"


S_LEAD_MODEL = "lead_model"


S_EXECUTOR_MODEL = "executor_model"


S_CLAUDE_MODEL = "claude_model"


S_CODEX_MODEL = "codex_model"


S_ANTIGRAVITY_MODEL = "antigravity_model"


S_GROK_MODEL = "grok_model"


S_KIMI_MODEL = "kimi_model"


S_REPORT_WRITER_MODEL = "report_writer_model"


S_DIRECTIVE_PICK = "directive_pick"


S_DIRECTIVE = "directive"


S_RELATED_TASKS_PICK = "related_tasks_pick"


S_RELATED_TASKS = "related_tasks"


S_CLARIFICATION_PICK = "clarification_pick"


S_CLARIFICATION = "clarification"


S_REVERIFY_SCOPE_PICK = "reverify_scope_pick"


S_REVERIFY_SCOPE_STAGES = "reverify_scope_stages"


S_PR_TEMPLATE_PICK = "pr_template_pick"


S_PR_TEMPLATE = "pr_template"


S_PR_TEMPLATE_SCOPE = "pr_template_scope"


S_FIX_CYCLE_CONFIRM = "fix_cycle_confirm"


S_CONFIRM = "confirm"


S_EDIT_TARGET = "edit_target"


S_DONE = "done"


S_ABORTED = "aborted"


# ---- 멀티탭 배치 프롬프트 그룹 (방출 계층 전용) ----
# 그룹 id 는 S_* 가 아니므로 prompts JSON SOT / step-id 동기화 검사 대상이 아니다.
GROUP_MODELS = "models"


GROUP_OPTIONS = "options"


GROUP_MAX_TABS = 4  # AskUserQuestion 의 질문(탭) 수 한도


# 멤버는 모두 서로 의존이 없는 단일선택 픽 step 이어야 한다.
# *_TEXT 후속 / workers_override / pr_template_scope 는 의존성 때문에 개별 유지.
PROMPT_GROUPS: dict[str, tuple[str, ...]] = {
    GROUP_MODELS: (S_LEAD_MODEL, S_EXECUTOR_MODEL, S_CLAUDE_MODEL,
                   S_CODEX_MODEL, S_ANTIGRAVITY_MODEL, S_GROK_MODEL,
                   S_KIMI_MODEL, S_REPORT_WRITER_MODEL),
    GROUP_OPTIONS: (S_DIRECTIVE_PICK, S_RELATED_TASKS_PICK,
                    S_CLARIFICATION_PICK, S_PR_TEMPLATE_PICK),
}


GROUP_LABELS: dict[str, str] = {
    GROUP_MODELS: "모델 선택 (탭별로 선택)",
    GROUP_OPTIONS: "추가 옵션 (탭별로 선택)",
}


_STEP_TO_GROUP: dict[str, str] = {
    sid: gid for gid, ids in PROMPT_GROUPS.items() for sid in ids
}


# ---- Validation helpers --------------------------------------------------

_SLUG_OK = re.compile(r"[a-z0-9]")


BRIEF_CARRY_SWITCH_ENTRY = "__switch_entry__"


BRIEF_CARRY_ABORT = _ABORT_OPTION


PICK_USE_DEFAULT = "__use_default__"


PICK_OTHER = "__other__"


PICK_SKIP = "__skip__"


_REUSE_LAST_TOKEN = "__reuse_last__"


_SIBLINGS_TOKEN = "__siblings__"


_LATEST_REPORT_TOKEN = "__latest_report__"


_PROJECT_DEFAULT_TOKEN = "__project_default__"


ALL_STAGES = "__all_stages__"


SCOPE_SHAPE_LINKED = "linked"


SCOPE_SHAPE_UNLINKED = "unlinked"


SCOPE_SHAPE_NO_ANSWERS = "no-answers"


# resume 재사용을 제안하는 phase. okstra.sh --resume-clarification 과 동일하게
# §1 clarification 을 갖는 비-implementation phase 로 한정한다(implementation 은
# approved-plan/stage 가 매 run 고유라 재사용 대상이 아니다).
_RESUME_REUSE_PHASES = (
    "requirements-discovery", "error-analysis", "implementation-planning",
    *ANALYSIS_TASK_TYPES,
)


# YES 선택 시 prefill 로 충족되어 다시 묻지 않는 설정 단계들.
_REUSE_FILLED_STEPS = (
    S_FEATURE_EVIDENCE_PICK, S_FEATURE_EVIDENCE,
    S_PROJECT_EVIDENCE_PICK, S_PROJECT_EVIDENCE,
    S_ANALYSIS_TARGET_PICK, S_ANALYSIS_TARGET,
    S_DEFAULTS_OR_CUSTOM, S_WORKERS_OVERRIDE, S_LEAD_MODEL, S_EXECUTOR_MODEL,
    S_CLAUDE_MODEL, S_CODEX_MODEL, S_ANTIGRAVITY_MODEL, S_GROK_MODEL,
    S_KIMI_MODEL, S_REPORT_WRITER_MODEL,
    S_DIRECTIVE_PICK, S_DIRECTIVE, S_RELATED_TASKS_PICK, S_RELATED_TASKS,
    S_CLARIFICATION_PICK, S_CLARIFICATION)
