// 零件提交：沙盒驗收 → 派發 hash id → 寫入 SUBMISSIONS_KV
// Requirements: 2.1, 2.2, 2.3
// SDD: matrix/arcrun/.agents/specs/component-registry-canon/design.md Phase 1.5
//
// 2026-05-07：移除 R2 寫入。cypher-executor 已不從 R2 動態載 wasm（每個零件 = 獨立 Worker）。
// R2 是 dead storage，移除避免誤導 AI 以為零件部署需要 wasm bytes。
//
// KV key 設計：
//   comp:{hash_id}:{version}  → 零件元數據 JSON
//   idx:{canonical_id}        → hash_id 反查索引（canonical_id → hash_id）
//
// hash_id 派發規則：
//   hash_id = 'cmp_' + sha256(canonical_id).slice(0, 8)
//   相同 canonical_id 永遠得到相同 hash_id（冪等）

import { runSandboxAcceptance } from './sandboxAcceptance';
import type { GherkinEvidence } from './sandboxAcceptance';
import type { ComponentContract, SandboxResult, Bindings } from '../types';

// ── G0 人類閘門（component-gatekeeping SDD R4）─────────────────────────────────
//
// 建零件不是 AI 能自己決定的事。submit 預設拒絕，除非帶人類確認 + 舉證。
// 把關點在「建立零件的 API」本身（此處）→ CLI/MCP/Python/JS 四路全收斂到這關。
// 誠實限制：AI 技術上能偽造 confirmed_by_human:true。靠 reason 留記錄（軌跡可審）+
// mindset 明示「絕不代替人類確認建零件」+ 純 WASI 沙箱框死能力，讓偽造成明確越界。

export interface HumanConfirmation {
  confirmed_by_human: true;          // 必須為 literal true
  reason_why_not_workflow: string;   // 非空：AI 舉證「為何工作流做不到」
  confirmed_at: string;              // ISO timestamp
}

export interface SubmitOptions {
  /** backfill 既有零件用：跳過人類閘門 + 沙盒（這些是已驗、已部署的存量） */
  skip_acceptance?: boolean;
  /** 人類確認 + 舉證（新投稿必填，除非 skip_acceptance） */
  human_confirmation?: HumanConfirmation;
  /** 投稿者本地跑 Gherkin 的結果（CLI 上傳，registry 存證可審） */
  gherkin_evidence?: GherkinEvidence[];
}

function gateError(contract: ComponentContract, reason: string): SandboxResult {
  return {
    success: false,
    failed_step: 'fake_component_scan',  // 復用最前步驟欄位語意：未過閘門
    reason,
    guide_anchor: '#human-gate',
    component_hash_id: '',
    canonical_id: contract.canonical_id,
    version: contract.version,
  };
}

// ── hash id 生成 ─────────────────────────────────────────────────────────────

async function deriveHashId(canonicalId: string): Promise<string> {
  const encoder = new TextEncoder();
  const data = encoder.encode(canonicalId);
  const hashBuffer = await crypto.subtle.digest('SHA-256', data);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  const hex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
  return 'cmp_' + hex.slice(0, 8);
}

// ── 主流程 ────────────────────────────────────────────────────────────────────

export async function submitComponent(
  wasmBytes: Uint8Array,
  contract: ComponentContract,
  env: Bindings,
  options: SubmitOptions = {},
): Promise<SandboxResult> {
  const { skip_acceptance, human_confirmation, gherkin_evidence } = options;

  // 0. G0 人類閘門（新投稿必經；backfill 既有存量 skip）
  if (!skip_acceptance) {
    if (
      !human_confirmation ||
      human_confirmation.confirmed_by_human !== true ||
      !human_confirmation.reason_why_not_workflow ||
      human_confirmation.reason_why_not_workflow.trim() === ''
    ) {
      return gateError(
        contract,
        '建零件需人類確認。請用 `acr component create`（會互動式問你），' +
          '並說明「為何這件事無法用工作流達成」。預設假設工作流 / recipe 能做——先試工作流。',
      );
    }
  }

  // 1. 沙盒驗收（靜態把關 + gherkin_evidence 一致性；backfill 仍可選擇性跳過 wasm 驗收）
  if (!skip_acceptance) {
    const sandboxResult = runSandboxAcceptance(wasmBytes, contract, gherkin_evidence);
    if (!sandboxResult.success) {
      return sandboxResult;
    }
  }

  // 2. 派發 hash id
  const hashId = await deriveHashId(contract.canonical_id);
  const kvKey = `comp:${hashId}:${contract.version}`;

  // 3. 冪等
  const existing = await env.SUBMISSIONS_KV.get(kvKey);
  if (existing) {
    return {
      success: true,
      component_hash_id: hashId,
      canonical_id: contract.canonical_id,
      version: contract.version,
    };
  }

  // 4. 寫入 metadata
  const record = {
    component_hash_id: hashId,
    canonical_id: contract.canonical_id,
    display_name: contract.display_name,
    category: contract.category,
    version: contract.version,
    wasi_target: contract.wasi_target,
    stability: contract.stability,
    runtime_compat: contract.runtime_compat,
    component_type: contract.component_type ?? 'wasm',
    constraints: contract.constraints,
    input_schema: contract.input_schema,
    output_schema: contract.output_schema,
    gherkin_tests: contract.gherkin_tests,
    description: contract.description ?? '',
    aliases: contract.aliases ?? [],
    tags: contract.tags ?? [],
    success_rate: 1,
    avg_duration_ms: 0,
    call_count: 0,
    visibility: 'public' as const,
    status: 'active' as const,
    submitted_at: new Date().toISOString(),
    deprecated_at: null,
    // G0 軌跡可審：人類為何建此零件（舉證）+ 投稿者本地 Gherkin 結果證據
    human_confirmation: human_confirmation ?? null,
    gherkin_evidence: gherkin_evidence ?? null,
  };

  await env.SUBMISSIONS_KV.put(kvKey, JSON.stringify(record));
  await env.SUBMISSIONS_KV.put(`idx:${contract.canonical_id}`, hashId);

  return {
    success: true,
    component_hash_id: hashId,
    canonical_id: contract.canonical_id,
    version: contract.version,
  };
}
