// admin-data.jsx — IT 관리 페이지 데이터
// Razor 가 window.__ADMIN_DATA__ 로 실 데이터 주입. 미주입 시 mock fallback.
// 사장 모드(결재함/결재일보) 와는 별도. 운영자 시점.

const DATA = (typeof window !== 'undefined' && window.__ADMIN_DATA__) || {};
// 이전 변수명 호환 (Editor 내부 lookups). DATA 와 __INJECT__ 동일.
const __INJECT__ = DATA;

const ADMIN_NAV = [
  { id: 'overview', label: 'OVERVIEW',      icon: '◐', cmd: 'sys status' },
  { id: 'site',     label: 'SITE',          icon: '⌂', cmd: 'site title' },
  { id: 'llm',      label: 'LLM ROUTING',   icon: '✦', cmd: 'llm routing' },
  { id: 'cost',     label: 'COST GUARD',    icon: '¥', cmd: 'llm cost' },
  { id: 'jobs',     label: 'HANGFIRE',      icon: '⏱', cmd: 'jobs ls' },
  { id: 'db',       label: 'POSTGRES',      icon: '◧', cmd: 'db status' },
  { id: 'keys',     label: 'API KEYS',      icon: '⚷', cmd: 'keys ls' },
  { id: 'audit',    label: 'AUDIT LOG',     icon: '≡', cmd: 'log audit' },
  { id: 'metrics',  label: 'TELEMETRY',     icon: '∿', cmd: 'metrics' },
  { id: 'docs',     label: 'DOC STORAGE',   icon: '📁', cmd: 'paperless' },
  { id: 'manifest', label: 'TOOL MANIFEST', icon: '⛬', cmd: 'manifest ls' },
  { id: 'sandbox',  label: 'POLICY SANDBOX',icon: '◇', cmd: 'policy test' },
  { id: 'flags',    label: 'KILL SWITCH',   icon: '⏻', cmd: 'flags' },
  { id: 'tasks',    label: 'TASKS',         icon: '▶', cmd: 'tasks ls' },
  { id: 'prompts',  label: 'CHAT PROMPTS',  icon: '✎', cmd: 'prompt edit' },
  { id: 'departments', label: 'DEPARTMENTS', icon: '👥', cmd: 'dept ls' },
];

// ─── Overview KPIs (top strip) ────────────────────────────
const SYS_STATUS = DATA.overview ?? {
  uptime: '—',
  build: '—',
  region: '—',
  health: 'amber', // green | amber | red
  cluster: { nodes: 0, ready: 0, pods: 0, restarts24h: 0 },
  budget: { spentUsd: 0, budgetUsd: 0, periodLabel: '—' },
  inflight: 0,
  queue: 0,
  errors24h: 0,
};

// ─── LLM Routing (Tag → Provider/Model rules) ─────────────
const LLM_PROVIDERS = DATA.llmProviders ?? [];

// Provider별 모델 카탈로그 (GET /v1/models 응답). 정적 카탈로그 — 데이터 아닌 메타.
const PROVIDER_MODELS = DATA.providerModels ?? {
  anthropic: [
    { id: 'claude-opus-4.5',           ctx: 200000, inputPer1k: 0.015,  outputPer1k: 0.075,  family: 'opus' },
    { id: 'claude-sonnet-4.5',         ctx: 200000, inputPer1k: 0.003,  outputPer1k: 0.015,  family: 'sonnet' },
    { id: 'claude-haiku-4.5',          ctx: 200000, inputPer1k: 0.0008, outputPer1k: 0.004,  family: 'haiku' },
    { id: 'claude-3-7-sonnet-20250219',ctx: 200000, inputPer1k: 0.003,  outputPer1k: 0.015,  family: 'sonnet', deprecated: true },
    { id: 'claude-3-5-haiku-20241022', ctx: 200000, inputPer1k: 0.0008, outputPer1k: 0.004,  family: 'haiku',  deprecated: true },
    { id: 'claude-3-opus-20240229',    ctx: 200000, inputPer1k: 0.015,  outputPer1k: 0.075,  family: 'opus',   deprecated: true },
  ],
  gemini: [
    { id: 'gemini-2.5-pro',     ctx: 2000000, inputPer1k: 0.00125, outputPer1k: 0.005,  family: 'pro' },
    { id: 'gemini-2.5-flash',   ctx: 1000000, inputPer1k: 0.00010, outputPer1k: 0.0004, family: 'flash' },
    { id: 'gemini-2.5-flash-lite', ctx: 1000000, inputPer1k: 0.00003, outputPer1k: 0.00012, family: 'flash' },
    { id: 'gemini-2.0-flash',   ctx: 1000000, inputPer1k: 0.00010, outputPer1k: 0.0004, family: 'flash', deprecated: true },
  ],
  openai: [
    { id: 'gpt-5',         ctx: 400000, inputPer1k: 0.0025, outputPer1k: 0.020, family: 'gpt-5' },
    { id: 'gpt-5-mini',    ctx: 400000, inputPer1k: 0.0003, outputPer1k: 0.0024,family: 'gpt-5' },
    { id: 'gpt-4o',        ctx: 128000, inputPer1k: 0.0025, outputPer1k: 0.010, family: 'gpt-4o' },
    { id: 'gpt-4o-mini',   ctx: 128000, inputPer1k: 0.00015,outputPer1k: 0.0006,family: 'gpt-4o' },
    { id: 'o1-mini',       ctx: 128000, inputPer1k: 0.0011, outputPer1k: 0.0044,family: 'o-series' },
  ],
  perplexity: [
    { id: 'sonar-pro',     ctx: 200000, inputPer1k: 0.003, outputPer1k: 0.015, family: 'sonar' },
    { id: 'sonar',         ctx: 200000, inputPer1k: 0.001, outputPer1k: 0.001, family: 'sonar' },
  ],
  llamaswap: [
    { id: 'qwen2.5-7b-instruct',     ctx:  32768, inputPer1k: 0, outputPer1k: 0, family: 'qwen', local: true },
    { id: 'qwen2.5-14b-instruct',    ctx:  32768, inputPer1k: 0, outputPer1k: 0, family: 'qwen', local: true },
    { id: 'qwen2.5-32b-instruct',    ctx:  32768, inputPer1k: 0, outputPer1k: 0, family: 'qwen', local: true },
    { id: 'llama-3.3-70b-instruct',  ctx: 128000, inputPer1k: 0, outputPer1k: 0, family: 'llama', local: true },
    { id: 'gemma-3-27b-it',          ctx: 131072, inputPer1k: 0, outputPer1k: 0, family: 'gemma', local: true },
    { id: 'mistral-small-3.1-24b',   ctx: 128000, inputPer1k: 0, outputPer1k: 0, family: 'mistral', local: true },
    { id: 'phi-4-14b',               ctx:  16384, inputPer1k: 0, outputPer1k: 0, family: 'phi', local: true },
    { id: 'deepseek-r1-distill-32b', ctx:  32768, inputPer1k: 0, outputPer1k: 0, family: 'deepseek', local: true, reasoning: true },
  ],
  fal: [], // image-gen, no LLM models
};

// Non-LLM providers (Rakuten, Qoo10, Shopify, 도매매, fal) — 정적 카탈로그.
const ALL_PROVIDERS_META = {
  anthropic: { id: 'anthropic', name: 'Anthropic',          kind: 'llm',     keyPrefix: 'sk-ant-api03-', sample: 'sk-ant-api03-AAAA…', validateLabel: 'GET /v1/models' },
  gemini:    { id: 'gemini',    name: 'Google Gemini',      kind: 'llm',     keyPrefix: 'AIza',          sample: 'AIzaSy…',           validateLabel: 'GET /v1beta/models' },
  openai:    { id: 'openai',    name: 'OpenAI',             kind: 'llm',     keyPrefix: 'sk-',           sample: 'sk-proj-…',         validateLabel: 'GET /v1/models' },
  perplexity:{ id: 'perplexity',name: 'Perplexity',         kind: 'llm',     keyPrefix: 'pplx-',         sample: 'pplx-…',            validateLabel: 'GET /models' },
  llamaswap: { id: 'llamaswap', name: 'llama-swap (local)', kind: 'llm',     keyPrefix: '',              sample: 'optional',          validateLabel: 'GET /v1/models' },
  rakuten:   { id: 'rakuten',   name: 'Rakuten Ichiba',     kind: 'sourcing',keyPrefix: '',              sample: 'application_id',    validateLabel: 'IchibaItem.Search · ping' },
  qoo10:     { id: 'qoo10',     name: 'Qoo10 JP',           kind: 'listing', keyPrefix: 'Q10-',          sample: 'Q10-XXXX-PROD',      validateLabel: 'CertificationKey.Verify' },
  shopify:   { id: 'shopify',   name: 'Shopify',            kind: 'listing', keyPrefix: 'shpat_',        sample: 'shpat_…',           validateLabel: 'admin.graphql · ping' },
  domemei:   { id: 'domemei',   name: '도매매',             kind: 'sourcing',keyPrefix: '',              sample: 'partner token',     validateLabel: 'partner.health' },
  fal:       { id: 'fal',       name: 'fal.ai',             kind: 'imagegen',keyPrefix: 'fal_',          sample: 'fal_…',             validateLabel: 'GET /models' },
};

const ROUTING_MODES = ['scheduled', 'on-demand'];

const ROUTING_RULES = DATA.routingRules ?? [];

// ─── Cost Guard buckets ──────────────────────────────────
const COST_BUCKETS = DATA.costBuckets ?? [];
const COST_HISTORY = DATA.costHistory ?? []; // last 7 days USD

// ─── Hangfire jobs ───────────────────────────────────────
const JOBS = DATA.jobs ?? [];

// ─── DB / Postgres ──────────────────────────────────────
const DB_INFO = DATA.dbInfo ?? (DATA.database?.info ?? {
  host: '—',
  version: '—',
  size: '—',
  connections: 0,
  maxConn: 0,
  replicaLag: '—',
  lastBackup: '—',
  uptime: '—',
});
const DB_TABLES = DATA.dbTables ?? (DATA.database?.tables ?? []);
const MIGRATIONS_PENDING = DATA.migrationsPending ?? (DATA.database?.migrationsPending ?? 0);
const MIGRATIONS_LAST = DATA.migrationsLast ?? (DATA.database?.migrationsLast ?? '—');

// ─── API Keys ─────────────────────────────────────────────
// secret = mocked clear value (only used for ux demo; real impl never returns plaintext)
const API_KEYS = DATA.apiKeys ?? [];

// ─── Available Providers (2026-05-17 운영자 directive) ──────
// '+ provider 추가' 다이얼로그의 dropdown candidate — 카탈로그에 있지만 vault 미저장.
// 각 항목 = { id: 'openai', displayName: 'OpenAI', credentialKey: 'llm.openai.apikey' }
// JSX 측은 id 로 ALL_PROVIDERS_META lookup → sample/keyPrefix/validateLabel 표시.
const AVAILABLE_PROVIDERS = DATA.availableProviders ?? [];

// ─── Audit log (AgentDecisionLog tail) ─────────────────────
const AUDIT_LOG = DATA.auditLog ?? [];

// ─── Telemetry ────────────────────────────────────────────
const TELEMETRY = DATA.telemetry ?? {
  reqRate: 0,    // req/min
  errorRate: 0,  // %
  p50: 0,        // ms
  p95: 0,
  p99: 0,
  trace24h: 0,
  spans24h: 0,
  history: [],   // [[req, err, lat], ...]
};

// ─── Feature flags / kill switches (legacy hardcoded data) ────────────
// 본 entry 는 v0.8.14 까지의 hardcoded kill-toggle list. v0.8.15 부터 KILL_SWITCHES
// 가 source — Flags() 컴포넌트는 KillSwitch() 로 대체.
const FLAGS = DATA.flags ?? [];

// ─── Tool Manifest (v0.8.15 신규) ─────────────────────────────
// 9 분산 페이지 (admin/{agents,skills,prompts,packages,marketplace,mcp-servers,plugins}) 흡수
const TOOL_MANIFEST = DATA.toolManifest ?? {
  agents:      [],
  skills:      [],
  prompts:     [],
  packages:    [],
  marketplace: { packagesCount: 0, catalogCount: 0, pluginsCount: 0, driftCount: 0, snapshotAt: null },
  mcpServers:  [],
  plugins:     [],
};

// ─── Policy Sandbox (v0.8.15 신규) ────────────────────────────
// /admin/governance/policies 흡수 + 30d backtest fixtures
const POLICY_SANDBOX = DATA.policySandbox ?? {
  presets:        [], // [{ id, name, desc, rules: [{ key, label, unit, currentValue, min, max, step }] }]
  activePolicies: [], // [{ name, status, axisKind, jsonDsl, createdAt, createdBy }]
  fixtures:       [], // [{ presetId, eventId, at, desc, actual, metrics }]
};

// ─── Kill Switches (v0.8.15 신규) ─────────────────────────────
// /admin/governance/kill-switch 흡수 — 4-scope (all/agent/skill/plugin)
const KILL_SWITCHES = DATA.killSwitches ?? {
  active:        [],   // [{ id, scope, reason, activatedBy, activatedAt, expiresAt, deactivatedAt }]
  recentHistory: [],   // 최근 50건
};

// ─── Tasks (v0.8.15 신규) ─────────────────────────────────────
// /admin/tasks 흡수 — task list + run+steps + cancel
const TASKS = DATA.tasks ?? {
  recent: [],   // [{ taskId, slug, state, correlationId, startedAt, durationMs, stepCount, canCancel }]
};

// ─── Chat Prompts (v0.9.19 Spec 2026-05-15 §5) ────────────────
// chat agent + Briefing system prompt 9 row DB editing surface.
// Rows = [{ slug, content, version, updatedAt, updatedBy, length }]
// 운영자가 코드 / 빌드 / 배포 없이 즉시 편집. {{COMMON_RULES}} / {{KPI_DUMP}} / {{DECISIONS_DUMP}}
// placeholder anchor 가 helper text source (server-side warning).
const CHAT_PROMPTS = DATA.chatPrompts ?? { rows: [] };

// ─── Departments (v0.10.0 Spec 2026-05-15 §7) ─────────────────
// 5 부서 + N sub-agent + tool grant 매핑.
// rows = [{ slug, displayName, icon, toolPolicy, isActive, isCutover, manifestVersion, updatedAt, updatedBy }]
// subAgents = [{ slug, parentSlug, displayName, icon, toolPolicy, isActive, updatedAt }]
// bindings = [{ id, agentSlug, bindingType, toolSlug, mcpServerId, permission, grantedAt, grantedBy }]
const DEPARTMENTS = DATA.departments ?? { rows: [], subAgents: [], bindings: [] };

// 5 default 부서 slug — Delete client-side 차단 source (server-side double-check).
const DEPARTMENT_ROOT_SLUGS = ['curator', 'designer', 'listing-order', 'cs', 'tax'];

// ─── Legacy Admin Page Migration v0.10.8 (Spec 2026-05-17 §5.1) ─────────────
// IT 콘솔 흡수 4건의 default data shape — Razor 미주입 시 fallback.

// #site 의 신규 sub-section: Category Markup CRUD row source.
// rows = [{ category, markup, notes?, createdAt, updatedAt, updatedBy? }]
const CATEGORY_MARKUP = DATA.categoryMarkup ?? { rows: [], snapshotAt: null };

// #audit 의 view selector <auto-curation> view source. 6 DecisionType + page pagination.
// rows = [{ id, decidedAt, poolCandidateIdShort, decisionType, selectionBucket, selectionLabel,
//   productTitle, sourceChannel, sourceProductId, sourceUrl?, category?, originalPrice?,
//   stage3Score?, estimatedRoiRate?, preciseRoiRate?, selectionBasis, reasonsJson, reasonsPreview }]
const AUTO_CURATION_DECISIONS = DATA.autoCurationDecisions ?? {
  rows: [], decisionTypeFilter: null, totalCount: 0, page: 1, pageSize: 50,
  analyzedCount: 0, selectedCount: 0, notSelectedCount: 0, pendingCount: 0, selectionBucketFilter: null,
};

// #cost 의 신규 recentCalls collapse source. 부서 필터 chip + page pagination.
// rows = [{ id, calledAt, bucket?, department, agentName, model, promptTokens, completionTokens, costUsd, durationMs, failed }]
const DEPARTMENT_RECENT_CALLS = DATA.departmentRecentCalls ?? {
  rows: [], departmentFilter: null, totalCount: 0, page: 1, pageSize: 50,
};

// #jobs 의 신규 recentRuns collapse + ⚠ abort 액션 source.
// rows = [{ id, department, jobName, startedAt, endedAt?, status, stepCount, currentStep?, hangfireJobId?, errorText?, canAbort }]
const DEPARTMENT_RECENT_RUNS = DATA.departmentRecentRuns ?? {
  rows: [], departmentFilter: null,
};

// #audit 의 view selector <seed-lifecycle> view source. 큐레이터 부서 한정.
// rows = [{ seedId, seedHandle, createdAt, currentStage, statusChangedAt, curatorDecision?, promotedToPoolAt?, approvedAt? }]
const SEED_LIFECYCLE = DATA.seedLifecycle ?? {
  rows: [], totalCount: 0, page: 1, pageSize: 50,
};

// 6 known DecisionType — #audit auto-curation view 의 필터 chip + label source.
// AutoCurationDecisionLogEntity DecisionType 의 v0.5.7 6값.
const KNOWN_DECISION_TYPES = [
  'auto_reject', 'pending_evaluation', 'pending_approval',
  'stage4_rejected', 'approved_by_operator', 'rejected_by_operator',
];

// 5 부서 slug — #cost / #jobs 의 부서 필터 chip 의 client-side label.
const KNOWN_DEPT_SLUGS = ['curator', 'designer', 'listing-order', 'cs', 'tax'];

// 26 Core tool slug (5 부서 × ~5 tool) — SharedReadOnly grant 의 picklist source.
// hardcoded — 향후 dynamic discovery 는 별도 PR (Spec §10 후속).
const CORE_TOOL_INVENTORY = [
  // Curator
  'curator/list_curation_queue/query',
  'curator/get_pool_candidate/query',
  'curator/get_seed_proposal_run/query',
  'curator/approve_curator_decision/mutate',
  'curator/reject_curator_decision/mutate',
  // Designer
  'designer/list_design_drafts/query',
  'designer/get_design_draft/query',
  'designer/get_designer_briefing/query',
  'designer/approve_design_publish/mutate',
  // Listing Order
  'listing-order/list_channel_listings/query',
  'listing-order/get_channel_listing/query',
  'listing-order/list_orders/query',
  'listing-order/get_order/query',
  'listing-order/publish_listing/mutate',
  // CS
  'cs/list_cs_conversations/query',
  'cs/get_cs_conversation/query',
  'cs/list_cs_messages/query',
  'cs/send_cs_reply/mutate',
  // Tax
  'tax/get_tax_context/query',
  'tax/get_export_invoice/query',
];
