<script lang="ts">
  import type { ProviderId } from './provider-capabilities';
  import CustomDropdown from './ui/CustomDropdown.svelte';
  import CustomRadio from './ui/CustomRadio.svelte';

  interface Props { provider: ProviderId; model: string; config: Record<string, unknown>; onChange: (config: Record<string, unknown>) => void; }
  let { provider, model, config, onChange }: Props = $props();

  let claudeThinking = $state<'disabled' | 'enabled' | 'adaptive'>('disabled');
  let claudeEffort = $state('medium'); let claudeTemp = $state(1.0); let claudeMaxTokens = $state(8192);
  let claudeTempLocked = $derived(claudeThinking === 'enabled');

  let codexSandbox = $state('workspace-write'); let codexApproval = $state('on-request'); let codexReasoning = $state('medium');

  let ollamaTemp = $state(0.8); let ollamaCtx = $state(32768); let ollamaPredict = $state(0);
  let ollamaTopK = $state(40); let ollamaTopP = $state(0.9);
  let ollamaCtxWarn = $derived(ollamaCtx < 8192);

  let geminiTemp = $state(1.0); let geminiThinkingMode = $state<'level' | 'budget'>('level');
  let geminiThinkingLevel = $state('medium'); let geminiThinkingBudget = $state(8192); let geminiMaxOutput = $state(8192);

  $effect(() => {
    const c = config;
    claudeThinking = (c.thinking as typeof claudeThinking) ?? 'disabled'; claudeEffort = (c.effort as string) ?? 'medium';
    claudeTemp = (c.temperature as number) ?? 1.0; claudeMaxTokens = (c.max_tokens as number) ?? 8192;
    codexSandbox = (c.sandbox as string) ?? 'workspace-write'; codexApproval = (c.approval as string) ?? 'on-request'; codexReasoning = (c.reasoning as string) ?? 'medium';
    ollamaTemp = (c.temperature as number) ?? 0.8; ollamaCtx = (c.num_ctx as number) ?? 32768; ollamaPredict = (c.num_predict as number) ?? 0; ollamaTopK = (c.top_k as number) ?? 40; ollamaTopP = (c.top_p as number) ?? 0.9;
    geminiTemp = (c.temperature as number) ?? 1.0; geminiThinkingMode = (c.thinkingMode as 'level'|'budget') ?? 'level'; geminiThinkingLevel = (c.thinkingLevel as string) ?? 'medium'; geminiThinkingBudget = (c.thinkingBudget as number) ?? 8192; geminiMaxOutput = (c.maxOutputTokens as number) ?? 8192;
  });

  function emitClaude() { onChange({ thinking: claudeThinking, effort: claudeThinking === 'adaptive' ? claudeEffort : undefined, temperature: claudeTempLocked ? 1.0 : claudeTemp, max_tokens: claudeMaxTokens }); }
  function emitCodex() { onChange({ sandbox: codexSandbox, approval: codexApproval, reasoning: codexReasoning }); }
  function emitOllama() { onChange({ temperature: ollamaTemp, num_ctx: ollamaCtx, num_predict: ollamaPredict || undefined, top_k: ollamaTopK, top_p: ollamaTopP }); }
  function emitGemini() { onChange({ temperature: geminiTemp, thinkingMode: geminiThinkingMode, thinkingLevel: geminiThinkingMode === 'level' ? geminiThinkingLevel : undefined, thinkingBudget: geminiThinkingMode === 'budget' ? geminiThinkingBudget : undefined, maxOutputTokens: geminiMaxOutput }); }

  function fmtT(n: number): string { return n >= 1000 ? `${(n / 1000).toFixed(n % 1000 === 0 ? 0 : 1)}K` : String(n); }
  function pf(e: Event) { return parseFloat((e.target as HTMLInputElement).value); }
  function pi(e: Event, d: number) { return parseInt((e.target as HTMLInputElement).value, 10) || d; }

  const THINKING_OPTIONS = [{ value: 'disabled', label: 'Disabled' }, { value: 'enabled', label: 'Enabled' }, { value: 'adaptive', label: 'Adaptive' }];
  const EFFORT_ITEMS = [{ value: 'low', label: 'Low' }, { value: 'medium', label: 'Medium' }, { value: 'high', label: 'High' }, { value: 'max', label: 'Max' }];
  const SANDBOX_ITEMS = ['read-only', 'workspace-write', 'danger-full-access'];
  const APPROVAL_ITEMS = ['untrusted', 'on-request', 'never'];
  const REASONING_ITEMS = ['minimal', 'low', 'medium', 'high', 'xhigh'];
  const GEMINI_LEVELS = [{ value: 'minimal', label: 'Minimal' }, { value: 'low', label: 'Low' }, { value: 'medium', label: 'Medium' }, { value: 'high', label: 'High' }];
</script>

<div class="mcp-root">
  {#if provider === 'claude'}
    <div class="mcp-field">
      <span class="mcp-label">Thinking mode</span>
      <CustomRadio options={THINKING_OPTIONS} selected={claudeThinking} name="claude-thinking" onChange={v => { claudeThinking = v as typeof claudeThinking; emitClaude(); }} />
      <span class="mcp-explain">{claudeThinking === 'disabled' ? 'thinking.type = disabled' : claudeThinking === 'enabled' ? 'thinking.type = enabled (always)' : 'thinking.type = adaptive (model decides)'}</span>
    </div>
    <div class="mcp-field" style:display={claudeThinking === 'adaptive' ? 'flex' : 'none'}>
      <span class="mcp-label">Effort level <span class="mcp-hint">(output_config.effort)</span></span>
      <CustomDropdown items={EFFORT_ITEMS} selected={claudeEffort} onSelect={v => { claudeEffort = v; emitClaude(); }} />
    </div>
    <div class="mcp-field">
      <span class="mcp-label">Temperature {#if claudeTempLocked}<span class="mcp-hint" title="Locked when thinking.type=enabled">Locked at 1.0</span>{/if}</span>
      <div class="mcp-slider-row">
        <input type="range" class="mcp-slider" min="0" max="2" step="0.1" value={claudeTempLocked ? 1.0 : claudeTemp} disabled={claudeTempLocked} oninput={e => { claudeTemp = pf(e); emitClaude(); }} />
        <span class="mcp-slider-val">{claudeTempLocked ? '1.0' : claudeTemp.toFixed(1)}</span>
      </div>
    </div>
    <div class="mcp-field">
      <span class="mcp-label">Max tokens <span class="mcp-slider-val-inline">{fmtT(claudeMaxTokens)}</span></span>
      <div class="mcp-slider-row">
        <input type="range" class="mcp-slider" min="256" max="200000" step="256" value={claudeMaxTokens} oninput={e => { claudeMaxTokens = pi(e, 8192); emitClaude(); }} />
        <span class="mcp-slider-val">{fmtT(claudeMaxTokens)}</span>
      </div>
    </div>
  {:else if provider === 'codex'}
    <div class="mcp-field"><span class="mcp-label">Sandbox mode</span><div class="mcp-seg">{#each SANDBOX_ITEMS as s}<button class="mcp-seg-btn" class:active={codexSandbox === s} onclick={() => { codexSandbox = s; emitCodex(); }}>{s}</button>{/each}</div></div>
    <div class="mcp-field"><span class="mcp-label">Approval policy</span><div class="mcp-seg">{#each APPROVAL_ITEMS as a}<button class="mcp-seg-btn" class:active={codexApproval === a} onclick={() => { codexApproval = a; emitCodex(); }}>{a}</button>{/each}</div></div>
    <div class="mcp-field"><span class="mcp-label">Reasoning effort</span><div class="mcp-seg">{#each REASONING_ITEMS as r}<button class="mcp-seg-btn" class:active={codexReasoning === r} onclick={() => { codexReasoning = r; emitCodex(); }}>{r}</button>{/each}</div></div>
  {:else if provider === 'ollama'}
    <div class="mcp-field"><span class="mcp-label">Temperature</span><div class="mcp-slider-row"><input type="range" class="mcp-slider" min="0" max="2" step="0.1" value={ollamaTemp} oninput={e => { ollamaTemp = pf(e); emitOllama(); }} /><span class="mcp-slider-val">{ollamaTemp.toFixed(1)}</span></div></div>
    <div class="mcp-field"><span class="mcp-label">Context window {#if ollamaCtxWarn}<span class="mcp-warn">Low context</span>{/if}</span><div class="mcp-slider-row"><input type="range" class="mcp-slider" min="512" max="131072" step="1024" value={ollamaCtx} oninput={e => { ollamaCtx = pi(e, 32768); emitOllama(); }} /><span class="mcp-slider-val">{fmtT(ollamaCtx)}</span></div></div>
    <div class="mcp-field"><span class="mcp-label">Max predict (0=unlimited)</span><div class="mcp-slider-row"><input type="range" class="mcp-slider" min="0" max="131072" step="256" value={ollamaPredict} oninput={e => { ollamaPredict = pi(e, 0); emitOllama(); }} /><span class="mcp-slider-val">{ollamaPredict === 0 ? '\u221E' : fmtT(ollamaPredict)}</span></div></div>
    <div class="mcp-field"><span class="mcp-label">Top-K</span><div class="mcp-slider-row"><input type="range" class="mcp-slider" min="1" max="200" step="1" value={ollamaTopK} oninput={e => { ollamaTopK = pi(e, 40); emitOllama(); }} /><span class="mcp-slider-val">{ollamaTopK}</span></div></div>
    <div class="mcp-field"><span class="mcp-label">Top-P</span><div class="mcp-slider-row"><input type="range" class="mcp-slider" min="0" max="1" step="0.05" value={ollamaTopP} oninput={e => { ollamaTopP = pf(e); emitOllama(); }} /><span class="mcp-slider-val">{ollamaTopP.toFixed(2)}</span></div></div>
  {:else if provider === 'gemini'}
    <div class="mcp-field"><span class="mcp-label">Temperature</span><div class="mcp-slider-row"><input type="range" class="mcp-slider" min="0" max="2" step="0.1" value={geminiTemp} oninput={e => { geminiTemp = pf(e); emitGemini(); }} /><span class="mcp-slider-val">{geminiTemp.toFixed(1)}</span></div></div>
    <div class="mcp-field"><span class="mcp-label">Thinking</span><div class="mcp-seg" style="max-width: 14rem;"><button class="mcp-seg-btn" class:active={geminiThinkingMode === 'level'} onclick={() => { geminiThinkingMode = 'level'; emitGemini(); }}>Level</button><button class="mcp-seg-btn" class:active={geminiThinkingMode === 'budget'} onclick={() => { geminiThinkingMode = 'budget'; emitGemini(); }}>Budget</button></div></div>
    <div class="mcp-field" style:display={geminiThinkingMode === 'level' ? 'flex' : 'none'}><span class="mcp-label">Thinking level</span><div class="mcp-seg">{#each GEMINI_LEVELS as l}<button class="mcp-seg-btn" class:active={geminiThinkingLevel === l.value} onclick={() => { geminiThinkingLevel = l.value; emitGemini(); }}>{l.label}</button>{/each}</div></div>
    <div class="mcp-field" style:display={geminiThinkingMode === 'budget' ? 'flex' : 'none'}><span class="mcp-label">Budget (tokens)</span><div class="mcp-slider-row"><input type="range" class="mcp-slider" min="0" max="65536" step="1024" value={geminiThinkingBudget} oninput={e => { geminiThinkingBudget = pi(e, 8192); emitGemini(); }} /><span class="mcp-slider-val">{fmtT(geminiThinkingBudget)}</span></div></div>
    <div class="mcp-field"><span class="mcp-label">Max output tokens</span><div class="mcp-slider-row"><input type="range" class="mcp-slider" min="1" max="65536" step="1024" value={geminiMaxOutput} oninput={e => { geminiMaxOutput = pi(e, 8192); emitGemini(); }} /><span class="mcp-slider-val">{fmtT(geminiMaxOutput)}</span></div></div>
  {/if}
</div>

<style>
  .mcp-root { display: flex; flex-direction: column; gap: 0.5rem; margin-top: 0.375rem; }
  .mcp-field { display: flex; flex-direction: column; gap: 0.25rem; }
  .mcp-label { font-size: 0.75rem; font-weight: 500; color: var(--ctp-subtext0); display: flex; align-items: center; gap: 0.375rem; }
  .mcp-hint { font-size: 0.6875rem; color: var(--ctp-overlay0); font-weight: 400; font-style: italic; }
  .mcp-warn { font-size: 0.6875rem; color: var(--ctp-peach); font-weight: 400; }
  .mcp-explain { font-size: 0.625rem; color: var(--ctp-overlay0); font-style: italic; }
  .mcp-slider-row { display: flex; align-items: center; gap: 0.5rem; }
  .mcp-slider { flex: 1; accent-color: var(--ctp-blue); }
  .mcp-slider:disabled { opacity: 0.4; }
  .mcp-slider:focus-visible { outline: 2px solid var(--ctp-blue); outline-offset: 2px; }
  .mcp-slider-val { font-size: 0.8125rem; color: var(--ctp-text); min-width: 2.5rem; text-align: right; }
  .mcp-slider-val-inline { font-size: 0.6875rem; color: var(--ctp-text); font-weight: 400; }
  .mcp-seg { display: flex; border-radius: 0.25rem; overflow: hidden; border: 1px solid var(--ctp-surface1); }
  .mcp-seg-btn { flex: 1; padding: 0.25rem 0.375rem; background: var(--ctp-surface0); border: none; color: var(--ctp-overlay1); font-size: 0.6875rem; cursor: pointer; font-family: var(--ui-font-family); border-right: 1px solid var(--ctp-surface1); }
  .mcp-seg-btn:last-child { border-right: none; }
  .mcp-seg-btn:hover { background: var(--ctp-surface1); color: var(--ctp-subtext1); }
  .mcp-seg-btn:focus-visible { outline: 2px solid var(--ctp-blue); outline-offset: -2px; }
  .mcp-seg-btn.active { background: color-mix(in srgb, var(--ctp-blue) 20%, var(--ctp-surface0)); color: var(--ctp-blue); font-weight: 600; }
</style>
