<!--
  /ask — Phase 3.4 Ask Pipeline Frontend.

  URL-driven: `/ask?q=<encoded>[&backend=<alias>]` 가 진입점.
  $effect 로 (q, backend) 변화 감지 → `/api/search/ask` 호출 →
  3-panel 렌더 (Answer / Evidence / Results).

  중복 호출 방지: lastKey (q+backend) 가드.

  Backend selector (PR-3 of DS AI routing policy, 2026-05-23,
  [[document-server-ai-routing-policy]]) — PR-DocSrv-Web-Ask-Selector-1 확장:
    - `auto` (기본, URL param 없음 → router 의 rule + LLM triage)
    - `mac-mini-default` (명시, Mac mini gemma-4-26b)
    - `qwen-macbook` (명시, M5 Max Qwen3.6-27B; "This device" 토글 on 시만)
    - `claude-cloud` (명시, 503 scaffold; VITE_ENABLE_CLOUD_BACKEND_DEV=true 시만)
    - "This device" 토글: localStorage `ds_device_self_label = 'macbook-m5-max' | null`.
      source IP 의존 0 (PR-0 round 2 발견: caddy 2-hop + X-Forwarded-For 미설정 →
      DS 가 보는 source IP = LAN gateway, 신뢰 불가).
    - 503 + error_reason ∈ {macbook_unavailable, provider_not_configured, router_*}
      시 자동 fallback 금지. UI 가 친절한 메시지 + "Mac mini default 로 재요청" 버튼.
    - legacy URL `?backend=default|gemma-macmini` 는 그대로 받아서 mac-mini-default 와 동등 처리.
-->
<script lang="ts">
  import { page } from '$app/stores';
  import { goto } from '$app/navigation';
  import { api, type ApiError } from '$lib/api';
  import { addToast } from '$lib/stores/toast';
  import EmptyState from '$lib/components/ui/EmptyState.svelte';
  import Button from '$lib/components/ui/Button.svelte';
  import AskAnswer from '$lib/components/ask/AskAnswer.svelte';
  import AskEvidence from '$lib/components/ask/AskEvidence.svelte';
  import AskResults from '$lib/components/ask/AskResults.svelte';
  import { Sparkles, Search, AlertCircle } from 'lucide-svelte';
  import type { AskResponse } from '$lib/types/ask';

  type BackendChoice = 'auto' | 'mac-mini-default' | 'qwen-macbook' | 'claude-cloud';

  function parseBackend(raw: string | null): BackendChoice {
    if (raw === 'qwen-macbook') return 'qwen-macbook';
    if (raw === 'mac-mini-default') return 'mac-mini-default';
    if (raw === 'claude-cloud') return 'claude-cloud';
    // legacy aliases (?backend=default | gemma-macmini) → mac-mini-default 와 동등
    if (raw === 'default' || raw === 'gemma-macmini') return 'mac-mini-default';
    return 'auto';
  }

  // Build-time feature flag — Claude Cloud UI 노출 여부 (default false).
  // VITE_ENABLE_CLOUD_BACKEND_DEV=true npm run build 시만 활성. 운영 토글 X
  // (build-time 한계). DS runtime feature flag API migrate 는 후속 PR.
  const CLOUD_DEV_ENABLED = import.meta.env.VITE_ENABLE_CLOUD_BACKEND_DEV === 'true';
  const DEVICE_LABEL_KEY = 'ds_device_self_label';
  const DEVICE_LABEL_M5_MAX = 'macbook-m5-max';

  // ── state ───────────────────────────────────────────
  let queryInput = $state('');
  let selectedBackend = $state<BackendChoice>('auto');
  let data = $state<AskResponse | null>(null);
  let loading = $state(false);
  let backendUnavailable = $state(false);
  let backendUnavailableMessage = $state('');
  // "I am on MacBook M5 Max" 토글. mount 시 localStorage 에서 복원.
  let isMacBookM5Max = $state(false);

  $effect(() => {
    if (typeof window === 'undefined') return;
    const stored = window.localStorage.getItem(DEVICE_LABEL_KEY);
    isMacBookM5Max = stored === DEVICE_LABEL_M5_MAX;
  });

  function toggleMacBookM5Max() {
    isMacBookM5Max = !isMacBookM5Max;
    if (typeof window === 'undefined') return;
    if (isMacBookM5Max) {
      window.localStorage.setItem(DEVICE_LABEL_KEY, DEVICE_LABEL_M5_MAX);
    } else {
      window.localStorage.removeItem(DEVICE_LABEL_KEY);
      // 토글 off 시 qwen-macbook 선택돼 있었으면 auto 로 복귀 (선택권 박탈 X 명시 신호).
      if (selectedBackend === 'qwen-macbook') {
        selectedBackend = 'auto';
      }
    }
  }

  // 중복 호출 방지 가드 (hydration + reactive trigger 이중 발동 방지)
  let lastKey = '';

  // citation scroll 연동: Answer 가 [n] 클릭 → Evidence 카드로 이동 + highlight
  const citationNodes = new Map<number, HTMLElement>();
  let activeCitation = $state<number | null>(null);

  function registerCitation(n: number, node: HTMLElement) {
    citationNodes.set(n, node);
    return {
      destroy() {
        citationNodes.delete(n);
      },
    };
  }

  function scrollToCitation(n: number) {
    activeCitation = n;
    const node = citationNodes.get(n);
    node?.scrollIntoView({ behavior: 'smooth', block: 'center' });
  }

  // ── URL 빌더: backend !== 'auto' 일 때만 param 추가 ─────
  function buildAskUrl(q: string, backend: BackendChoice): string {
    const params = new URLSearchParams({ q });
    if (backend !== 'auto') params.set('backend', backend);
    return `/ask?${params.toString()}`;
  }

  // ── submit (URL-driven, back 자동) ──────────────────
  function submit() {
    const q = queryInput.trim();
    if (!q) return;
    goto(buildAskUrl(q, selectedBackend));
  }

  function handleKeydown(e: KeyboardEvent) {
    if (e.key === 'Enter' && !e.isComposing) {
      e.preventDefault();
      submit();
    }
  }

  // 503 후 "Mac mini default 로 재요청" — auto 로 reset (param 명시 제거).
  function retryWithMacMiniDefault() {
    const q = $page.url.searchParams.get('q') ?? queryInput.trim();
    if (!q) return;
    goto(`/ask?q=${encodeURIComponent(q)}`);
  }

  // PR-3 of routing policy — error_reason → 친절 메시지 매핑.
  // silent fallback 금지 ([[feedback_no_silent_fallback_explicit_opt_in]]):
  // 모든 503 case 는 명시 표시, 다른 backend 자동 재호출 X.
  function friendlyErrorMessage(reason: string | undefined, detail: string): string {
    switch (reason) {
      case 'macbook_unavailable':
        return 'MacBook M5 Max 가 응답하지 않습니다. 깨우거나 (launchctl start) Mac mini default 로 다시 요청하세요.';
      case 'provider_not_configured':
        return 'Claude Cloud 백엔드는 아직 구성되지 않았습니다 (2026-06-15 이후 별 PR 활성화 예정).';
      default:
        if (reason && reason.startsWith('router_')) {
          return `라우터 호출 실패 (${reason}). Mac mini default 로 다시 요청하거나 잠시 후 재시도하세요.`;
        }
        if (reason && reason.startsWith('upstream_')) {
          return `Upstream backend 가 응답하지 않습니다 (${reason}). 잠시 후 재시도하세요.`;
        }
        return detail || '답변 생성 실패';
    }
  }

  // ── API 호출 ───────────────────────────────────────
  async function runAsk(q: string, backend: BackendChoice) {
    loading = true;
    activeCitation = null;
    backendUnavailable = false;
    backendUnavailableMessage = '';
    const path = backend !== 'auto'
      ? `/search/ask?q=${encodeURIComponent(q)}&backend=${encodeURIComponent(backend)}&limit=10`
      : `/search/ask?q=${encodeURIComponent(q)}&limit=10`;
    try {
      data = await api<AskResponse>(path);
    } catch (err) {
      const apiErr = err as ApiError;
      if (apiErr.status === 503) {
        backendUnavailable = true;
        backendUnavailableMessage = friendlyErrorMessage(apiErr.errorReason, apiErr.detail);
        data = null;
      } else {
        addToast('error', apiErr.detail || '답변 생성 실패');
        data = null;
      }
    } finally {
      loading = false;
    }
  }

  // ── URL → runAsk (중복 가드) ────────────────────────
  $effect(() => {
    const q = $page.url.searchParams.get('q') ?? '';
    const backend = parseBackend($page.url.searchParams.get('backend'));
    queryInput = q;
    selectedBackend = backend;
    if (!q) {
      data = null;
      loading = false;
      backendUnavailable = false;
      lastKey = '';
      return;
    }
    const key = `${q}|${backend}`;
    if (key === lastKey) return;
    lastKey = key;
    runAsk(q, backend);
  });
</script>

<svelte:head>
  <title>질문 - PKM</title>
</svelte:head>

<div class="h-full overflow-auto">
  <!-- 상단 검색바 (sticky) -->
  <div class="sticky top-0 z-10 bg-bg/80 backdrop-blur border-b border-default px-4 py-3">
    <div class="flex flex-wrap items-center gap-2 max-w-[1680px] mx-auto">
      <div class="relative flex-1 min-w-0">
        <Search
          size={14}
          class="absolute left-3 top-1/2 -translate-y-1/2 text-dim pointer-events-none"
        />
        <input
          data-search-input
          type="text"
          bind:value={queryInput}
          onkeydown={handleKeydown}
          placeholder="질문을 입력하세요 (/ 키로 포커스)"
          class="w-full pl-9 pr-3 py-2 bg-surface border border-default rounded-lg text-text text-sm focus:border-accent outline-none"
        />
      </div>
      <label
        class="flex items-center gap-1.5 text-xs text-dim cursor-pointer select-none"
        title="이 디바이스가 MacBook M5 Max 인 경우 체크 — This device (qwen-macbook) 옵션 활성화됩니다. localStorage 저장."
      >
        <input
          type="checkbox"
          checked={isMacBookM5Max}
          onchange={toggleMacBookM5Max}
          class="accent-accent"
        />
        <span>This is M5 Max</span>
      </label>
      <select
        bind:value={selectedBackend}
        title="Backend 선택 — silent fallback 0 정책 (선택한 backend 만 시도, 실패 시 503)."
        class="py-2 px-2 bg-surface border border-default rounded-lg text-text text-xs focus:border-accent outline-none min-w-0 max-w-[42vw] truncate"
      >
        <option value="auto">Auto (router)</option>
        <option value="mac-mini-default">Mac mini (default)</option>
        <option
          value="qwen-macbook"
          disabled={!isMacBookM5Max}
          title={isMacBookM5Max
            ? 'MacBook M5 Max Qwen3.6-27B (직접 호출)'
            : 'Check "This is M5 Max" toggle to enable'}
        >
          {isMacBookM5Max ? 'This device (Qwen MacBook)' : 'This device (unavailable)'}
        </option>
        <option
          value="claude-cloud"
          disabled={!CLOUD_DEV_ENABLED}
          title={CLOUD_DEV_ENABLED
            ? 'Claude Cloud (dev mode — returns 503 until activation PR)'
            : 'Cloud backend not configured yet'}
        >
          Claude Cloud {CLOUD_DEV_ENABLED ? '(dev)' : '(unavailable)'}
        </option>
      </select>
    </div>
  </div>

  <!-- 본문 -->
  <div class="max-w-[1680px] mx-auto p-4">
    {#if backendUnavailable}
      <div class="py-16">
        <EmptyState
          icon={AlertCircle}
          title="Backend 가 응답하지 않습니다"
          description={backendUnavailableMessage}
        >
          <Button variant="primary" size="sm" onclick={retryWithMacMiniDefault}>
            Mac mini (default) 로 재요청
          </Button>
        </EmptyState>
      </div>
    {:else if !queryInput && !loading && !data}
      <div class="py-16">
        <EmptyState
          icon={Sparkles}
          title="근거 기반 답변을 받아보세요"
          description="질문을 입력하면 문서에서 근거를 찾아 인용 기반 답변을 생성합니다."
        />
      </div>
    {:else}
      <div class="grid gap-4 lg:grid-cols-[1.2fr_0.9fr] items-start">
        <!-- 좌: Answer + Results -->
        <div class="flex flex-col gap-4 min-w-0">
          <AskAnswer {data} {loading} onCitationClick={scrollToCitation} />
          <AskResults {data} {loading} />
        </div>

        <!-- 우: Evidence (lg 이상 sticky) -->
        <div class="lg:sticky lg:top-20 lg:self-start min-w-0">
          <AskEvidence
            {data}
            {loading}
            {activeCitation}
            {registerCitation}
          />
        </div>
      </div>
    {/if}
  </div>
</div>
