<!-- #region ConfigTabForm [C:4] [TYPE Component] [SEMANTICS translate, config, datasource, llm, columns] -->
<!-- @ingroup Translate -->
<!-- @BRIEF Configuration tab content for Translation Job — datasource selection with auto-detected
     DB dialect, column mapping, LLM provider, target languages (multi-select from settings-allowed languages),
     dictionaries, disable reasoning toggle. -->
<!-- @LAYER UI -->
<!-- @RELATION DEPENDS_ON -> [EXT:frontend:fetchDatasources] -->
<!-- @RELATION DEPENDS_ON -> [EXT:frontend:fetchDatasourceColumns] -->
<!-- @RELATION DEPENDS_ON -> [getAllowedLanguages] -->
<!-- @RELATION DEPENDS_ON -> [MultiSelect] -->
<!-- @RELATION CALLS -> [filterLanguages]
<!-- @RATIONALE Target language list is now fetched from /settings/allowed-languages instead of static ALL_LANGUAGES.
     This ensures only admin-configured languages (Settings → Languages) are shown. Falls back to full list on API error
     or when allowed-languages is empty. -->
<!-- @UX_STATE Datasource searching -> Dropdown with filtered results, spinner on load -->
<!-- @UX_STATE Datasource selected -> Columns loaded, DB dialect detected, mapping ready -->
<!-- @UX_STATE Columns loading -> Skeleton pulse in column section -->
<!-- @UX_STATE Validation error -> Red border on invalid fields, inline error text -->
<!-- @UX_FEEDBACK Detected dialect badge (green pill) when datasource selected -->
<!-- @UX_FEEDBACK Spinner in datasource input while searching -->
<!-- @UX_FEEDBACK Virtual column warning (yellow bg + asterisk) -->
<!-- @UX_RECOVERY Datasource not found -> try different search term -->
<!-- @UX_RECOVERY Environment changed -> datasource search cleared, new DB list loaded -->
<!-- @UX_REACTIVITY Props -> $bindable() for all form fields, $props() for environment list -->
<!-- @UX_REACTIVITY LocalState -> datasourceList, datasourceLoading, showDatasourceDropdown -->
<script lang="ts">
  import { getT } from '$lib/i18n/index.svelte.js';
  import { ALL_LANGUAGES, filterLanguages } from '$lib/i18n/languages.js';
  import { api } from '$lib/api.js';
  import { fetchDatasources, fetchDatasourceColumns } from '$lib/api/translate.js';
  import MultiSelect from '$lib/components/ui/MultiSelect.svelte';
  import HelpTooltip from '$lib/ui/HelpTooltip.svelte';

  // ---- Bindable form state (parent-owned) ----
  let {
    name = $bindable(''),
    description = $bindable(''),
    environmentId = $bindable(''),
    environments = [],
    datasourceId = $bindable(''),
    datasourceSearch = $bindable(''),
    databaseDialect = $bindable(''),
    availableColumns = [],
    virtualColumns = $bindable([]),
    sourceKeyCols = $bindable([]),
    targetKeyCols = $bindable([]),
    translationColumn = $bindable(''),
    contextColumns = $bindable([]),
    targetLanguages = $bindable(['en']),
    targetLanguageColumn = $bindable(''),
    targetSourceColumn = $bindable(''),
    targetSourceLanguageColumn = $bindable(''),
    providerId = $bindable(''),
    llmProviders = [],
    dictionaryIds = $bindable([]),
    availableDictionaries = [],
    disableReasoning = $bindable(false),
    validationErrors = {},
    onEnvChange = () => {},
    insertMethod = $bindable('sqllab'),
    connectionId = $bindable(null),
  } = $props();

  // ---- Local state ----
  let datasourceList = $state([]);
  let datasourceLoading = $state(false);
  let showDatasourceDropdown = $state(false);
  let isColumnsLoading = $state(false);
  let columnList = $derived(availableColumns);
  let allowedLanguageCodes: string[] = $state([]);
  // @RATIONALE Svelte 5 store detection fails for `$t` in deeply nested templates.
  //             Use getT() + $derived to keep reactivity to locale changes.
  const _t = $derived(getT());
  // Language options filtered by backend-allowed codes (fallback to full list)
  let languageOptions = $derived(
    allowedLanguageCodes.length > 0
      ? filterLanguages(allowedLanguageCodes)
      : ALL_LANGUAGES
  );

  // Load allowed languages from settings once on mount
  $effect(() => {
    api.getAllowedLanguages().then((codes) => {
      if (Array.isArray(codes) && codes.length > 0) {
        allowedLanguageCodes = codes;
      }
    }).catch(() => {
      // Non-critical: fall back to full list
      allowedLanguageCodes = [];
    });
  });

  // ---- Derived ----
  function isVirtual(colName) {
    return (virtualColumns || []).includes(colName);
  }

  // Auto-load columns when datasourceId changes (from parent loadJob or user selection)
  $effect(() => {
    if (datasourceId && environmentId) {
      loadColumnsForDatasource();
    }
  });

  // ---- Datasource search ----
  let searchTimer = null;
  async function handleDatasourceSearch() {
    clearTimeout(searchTimer);
    searchTimer = setTimeout(() => searchDatasources(datasourceSearch), 300);
  }

  async function searchDatasources(searchTerm = '') {
    if (!environmentId) return;
    datasourceLoading = true;
    try {
      datasourceList = await fetchDatasources(environmentId, searchTerm);
      showDatasourceDropdown = true;
    } catch {
      datasourceList = [];
    } finally {
      datasourceLoading = false;
    }
  }

  /** Select a dataset from the dropdown */
  function selectDatasource(ds) {
    datasourceId = String(ds.id);
    datasourceSearch = `${ds.table_name} (${ds.database_name} · ${ds.database_dialect})`;
    showDatasourceDropdown = false;
    availableColumns = [];
    virtualColumns = [];
    sourceKeyCols = [];
    targetKeyCols = [];
    translationColumn = '';
    targetLanguageColumn = '';
    targetSourceColumn = '';
    targetSourceLanguageColumn = '';
    contextColumns = [];
    databaseDialect = ds.database_dialect || '';
  }

  async function loadColumnsForDatasource() {
    if (!datasourceId || !environmentId) return;
    isColumnsLoading = true;
    try {
      const response = await fetchDatasourceColumns(datasourceId, environmentId);
      availableColumns = response.columns || response || [];
      virtualColumns = response.virtual_columns || [];
    } catch {
      availableColumns = [];
      virtualColumns = [];
    } finally {
      isColumnsLoading = false;
    }
  }

  // ---- Key column helpers ----
  function toggleSourceKeyCol(colName) {
    if (sourceKeyCols.includes(colName)) {
      const idx = sourceKeyCols.indexOf(colName);
      sourceKeyCols = sourceKeyCols.filter((_, i) => i !== idx);
      targetKeyCols = targetKeyCols.filter((_, i) => i !== idx);
    } else {
      sourceKeyCols = [...sourceKeyCols, colName];
      targetKeyCols = [...targetKeyCols, colName];
    }
  }

  function updateTargetKeyCol(idx, value) {
    targetKeyCols[idx] = value;
    targetKeyCols = targetKeyCols; // trigger reactivity
  }

  function toggleContextColumn(col) {
    if (contextColumns.includes(col)) {
      contextColumns = contextColumns.filter(c => c !== col);
    } else {
      contextColumns = [...contextColumns, col];
    }
  }
</script>

<div class="space-y-6">
  <!-- Basic Info -->
  <section class="bg-surface-card border border-border rounded-lg p-6">
    <h2 class="text-lg font-semibold text-text mb-4">{_t.translate?.config?.basic_info}</h2>
    <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
      <div class="md:col-span-2">
        <label class="block text-sm font-medium text-text mb-1 flex items-center gap-1">
          {_t.translate?.config?.name} <span class="text-destructive">*</span>
          <HelpTooltip text={_t.translate?.config?.help_name || ''} />
        </label>
        <input
          type="text"
          bind:value={name}
          class="w-full px-3 py-2 border rounded-lg text-sm {validationErrors.name ? 'border-destructive-ring bg-destructive-light' : 'border-border-strong'} focus-visible:ring-2 focus-visible:ring-primary-ring focus-visible:border-primary-ring"
          placeholder={_t.translate?.config?.name_placeholder}
        />
        {#if validationErrors.name}
          <p class="text-xs text-destructive mt-1">{validationErrors.name}</p>
        {/if}
      </div>
      <div class="md:col-span-2">
        <label class="block text-sm font-medium text-text mb-1 flex items-center gap-1">
          {_t.translate?.config?.description}
          <HelpTooltip text={_t.translate?.config?.help_description || ''} />
        </label>
        <textarea
          bind:value={description}
          rows="2"
          class="w-full px-3 py-2 border border-border-strong rounded-lg text-sm focus-visible:ring-2 focus-visible:ring-primary-ring focus-visible:border-primary-ring"
          placeholder={_t.translate?.config?.description_placeholder}
        ></textarea>
      </div>
    </div>
  </section>

  <!-- Datasource & Environment -->
  <section class="bg-surface-card border border-border rounded-lg p-6">
    <h2 class="text-lg font-semibold text-text mb-4">{_t.translate?.config?.datasource}</h2>
    <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
      <div>
        <label class="block text-sm font-medium text-text mb-1 flex items-center gap-1">
          {_t.translate?.config?.environment}
          <HelpTooltip text={_t.translate?.config?.help_environment || ''} />
        </label>
        <select
          bind:value={environmentId}
          onchange={(e) => onEnvChange(e.target.value)}
          class="w-full px-3 py-2 border border-border-strong rounded-lg text-sm focus-visible:ring-2 focus-visible:ring-primary-ring focus-visible:border-primary-ring"
        >
          <option value="">{_t.translate?.config?.select_environment}</option>
          {#each environments as env}
            <option value={env.id}>{env.name} ({env.id})</option>
          {/each}
        </select>
      </div>
      <div class="relative">
        <label class="block text-sm font-medium text-text mb-1 flex items-center gap-1">
          {_t.translate?.config?.datasource_id}
          <HelpTooltip text={_t.translate?.config?.help_datasource || ''} />
        </label>
        <input
          type="text"
          bind:value={datasourceSearch}
          oninput={handleDatasourceSearch}
          onfocus={() => searchDatasources('')}
          onblur={() => setTimeout(() => (showDatasourceDropdown = false), 150)}
          class="w-full px-3 py-2 border border-border-strong rounded-lg text-sm focus-visible:ring-2 focus-visible:ring-primary-ring focus-visible:border-primary-ring"
          placeholder={_t.translate?.config?.datasource_search_placeholder || 'Search datasets...'}
        />
        {#if datasourceLoading}
          <div class="absolute right-3 top-9 animate-spin h-4 w-4 border-2 border-primary-ring border-t-transparent rounded-full"></div>
        {/if}
        {#if showDatasourceDropdown}
          <div class="absolute z-10 mt-1 w-full bg-surface-card border border-border rounded-lg shadow-lg max-h-60 overflow-y-auto">
            {#each datasourceList as ds}
              <button
                type="button"
                onmousedown={() => selectDatasource(ds)}
                class="w-full text-left px-3 py-2 text-sm hover:bg-primary-light border-b border-border last:border-b-0"
              >
                <span class="font-medium">{ds.table_name}</span>
                <span class="text-text-subtle ml-2">{ds.schema}</span>
                <span class="float-right text-xs text-text-subtle">{ds.database_name} · {ds.database_dialect}</span>
              </button>
            {/each}
          </div>
        {/if}
      </div>
      {#if databaseDialect && databaseDialect !== 'unknown'}
        <div class="md:col-span-2">
          <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-success-light text-success">
            {_t.translate?.config?.detected_dialect.replace('{dialect}', databaseDialect)}
          </span>
        </div>
      {/if}
    </div>

    {#if isColumnsLoading}
      <div class="mt-4 h-8 bg-surface-muted rounded animate-pulse"></div>
    {/if}

    {#if columnList.length > 0}
      <div class="mt-4">
        <label class="block text-sm font-medium text-text mb-2" for="available-columns">
          {_t.translate?.config?.available_columns.replace('{count}', columnList.length)}
        </label>
        <div id="available-columns" class="max-h-40 overflow-y-auto border border-border rounded-lg divide-y divide-border">
          {#each columnList as col}
            <div class="px-3 py-1.5 text-sm flex items-center gap-2 {isVirtual(col.name) ? 'bg-warning-light' : ''}">
              <span class="font-mono text-xs">{col.name}</span>
              {#if col.type}
                <span class="text-xs text-text-subtle">({col.type})</span>
              {/if}
              {#if isVirtual(col.name)}
                <span class="text-xs text-warning italic">{_t.translate?.config?.virtual}</span>
              {/if}
            </div>
          {/each}
        </div>
      </div>
    {/if}
  </section>

  <!-- Column Mapping -->
  <section class="bg-surface-card border border-border rounded-lg p-6">
    <h2 class="text-lg font-semibold text-text mb-4">{_t.translate?.config?.column_mapping}</h2>

    <!-- Translation Column -->
    <div class="mb-4">
      <label class="block text-sm font-medium text-text mb-1 flex items-center gap-1">
        {_t.translate?.config?.translation_column} <span class="text-destructive">*</span>
        <HelpTooltip text={_t.translate?.config?.help_translation_column || ''} />
      </label>
      <select
        bind:value={translationColumn}
        class="w-full px-3 py-2 border rounded-lg text-sm {validationErrors.translationColumn ? 'border-destructive-ring bg-destructive-light' : 'border-border-strong'} focus-visible:ring-2 focus-visible:ring-primary-ring focus-visible:border-primary-ring"
      >
        <option value="">{_t.translate?.config?.select_column}</option>
        {#each columnList as col}
          <option value={col.name}>{col.name}{isVirtual(col.name) ? ` (${_t.translate?.config?.virtual})` : ''}</option>
        {/each}
      </select>
      {#if validationErrors.translationColumn}
        <p class="text-xs text-destructive mt-1">{validationErrors.translationColumn}</p>
      {/if}
    </div>

    <!-- Key Mapping (source -> target pairs) -->
    <div class="mb-4">
      <div class="flex items-center justify-between mb-2">
        <label class="block text-sm font-medium text-text flex items-center gap-1">
          {_t.translate?.config?.key_columns}
          <HelpTooltip text={_t.translate?.config?.help_key_columns || ''} />
        </label>
        {#if sourceKeyCols.length > 0}
          <button
            onclick={() => { sourceKeyCols = []; targetKeyCols = []; }}
            class="text-xs text-destructive hover:text-destructive"
          >
            {_t.translate?.config?.clear_all}
          </button>
        {/if}
      </div>

      {#if columnList.length === 0}
        <div class="flex flex-wrap gap-2 mb-3">
          <button
            onclick={() => {
              sourceKeyCols = [...sourceKeyCols, ''];
              targetKeyCols = [...targetKeyCols, ''];
            }}
            class="px-3 py-1 text-xs border border-dashed border-border-strong rounded text-text-muted hover:border-primary-ring hover:text-primary"
          >
            {_t.translate?.config?.add_key_column}
          </button>
        </div>
      {:else}
        <div class="flex flex-wrap gap-2 mb-3">
          {#each columnList as col}
            <button
              onclick={() => toggleSourceKeyCol(col.name)}
              class="px-2.5 py-1 text-xs rounded-full border transition-colors
                {sourceKeyCols.includes(col.name)
                  ? 'bg-primary-light border-primary-ring text-primary'
                  : 'bg-surface-card border-border text-text-muted hover:border-border-strong'}"
              title={isVirtual(col.name) ? _t.translate?.config?.virtual_column_warning.replace('{col}', col.name) : ''}
            >
              {col.name}
              {#if isVirtual(col.name)}
                <span class="text-warning">*</span>
              {/if}
            </button>
          {/each}
        </div>
      {/if}

      {#if sourceKeyCols.length > 0}
        <div class="space-y-2">
          {#each sourceKeyCols as srcCol, idx}
            <div class="flex items-center gap-2">
              <input
                type="text"
                value={srcCol}
                disabled
                class="flex-1 px-3 py-1.5 border border-border bg-surface-muted rounded text-sm font-mono"
              />
              <span class="text-text-subtle text-sm">&rarr;</span>
              <input
                type="text"
                value={targetKeyCols[idx] || ''}
                placeholder={_t.translate?.config?.target_column_placeholder}
                oninput={(e) => updateTargetKeyCol(idx, e.target.value)}
                class="flex-1 px-3 py-1.5 border border-border-strong rounded text-sm font-mono focus-visible:ring-2 focus-visible:ring-primary-ring"
              />
              <button
                onclick={() => {
                  sourceKeyCols = sourceKeyCols.filter((_, i) => i !== idx);
                  targetKeyCols = targetKeyCols.filter((_, i) => i !== idx);
                }}
                class="p-1 text-text-subtle hover:text-destructive"
                aria-label={_t.translate?.config?.remove_key_column || 'Remove key column'}
              >
                <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
                </svg>
              </button>
            </div>
          {/each}
        </div>
      {/if}
      {#if validationErrors.targetKeyCols}
        <p class="text-xs text-destructive mt-1">{validationErrors.targetKeyCols}</p>
      {/if}
    </div>

    <!-- Context Columns -->
    <div>
      <label class="block text-sm font-medium text-text mb-2 flex items-center gap-1">
        {_t.translate?.config?.context_columns}
        <HelpTooltip text={_t.translate?.config?.help_context_columns || ''} />
      </label>
      {#if columnList.length === 0}
        <p class="text-xs text-text-subtle">{_t.translate?.config?.select_datasource_hint}</p>
      {:else}
        <div class="flex flex-wrap gap-2">
          {#each columnList as col}
            <button
              onclick={() => toggleContextColumn(col.name)}
              class="px-2.5 py-1 text-xs rounded-full border transition-colors
                {contextColumns.includes(col.name)
                  ? 'bg-info-light border-purple-300 text-info'
                  : 'bg-surface-card border-border text-text-muted hover:border-border-strong'}"
            >
              {col.name}
              {#if isVirtual(col.name)}
                <span class="text-warning">*</span>
              {/if}
            </button>
          {/each}
        </div>
      {/if}
    </div>
  </section>

  <!-- LLM Settings -->
  <section class="bg-surface-card border border-border rounded-lg p-6">
    <h2 class="text-lg font-semibold text-text mb-4">{_t.translate?.config?.llm_settings}</h2>
    <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
      <div>
        <label class="block text-sm font-medium text-text mb-1 flex items-center gap-1">
          {_t.translate?.config?.provider}
          <HelpTooltip text={_t.translate?.config?.help_provider || ''} />
        </label>
        <select bind:value={providerId} class="w-full px-3 py-2 border border-border-strong rounded-lg text-sm">
          <option value="">{_t.translate?.config?.select_provider}</option>
          {#each llmProviders as provider}
            <option value={provider.id}>{provider.name || provider.provider_type}</option>
          {/each}
        </select>
      </div>
      <div>
        <div class="flex items-center gap-1 mb-1">
          <span class="text-sm font-medium text-text">{_t.translate?.config?.target_language}</span>
          <span class="text-destructive">*</span>
          <HelpTooltip text={_t.translate?.config?.help_target_language || ''} />
        </div>
        <MultiSelect
          label=""
          options={languageOptions}
          bind:selected={targetLanguages}
          searchable={true}
          placeholder={_t.translate?.config?.target_language_search_placeholder || 'Search languages...'}
          required={false}
        />
        {#if targetLanguages.length === 0}
          <p class="text-xs text-warning mt-1">{_t.translate?.config?.target_language_required || 'Select at least one target language'}</p>
        {/if}
      </div>
    </div>

    <!-- Disable reasoning toggle -->
    <div class="mt-3">
      <label class="flex items-start gap-3 cursor-pointer">
        <input
          type="checkbox"
          bind:checked={disableReasoning}
          class="mt-0.5 rounded border-border-strong text-primary focus-visible:ring-primary-ring"
        />
        <div>
          <span class="text-sm font-medium text-text flex items-center gap-1">
            {_t.translate?.config?.disable_reasoning || 'Disable reasoning (save tokens)'}
            <HelpTooltip text={_t.translate?.config?.help_disable_reasoning || ''} />
          </span>
          <p class="text-xs text-text-subtle mt-0.5">
            {_t.translate?.config?.disable_reasoning_hint || 'Saves output tokens by suppressing Chain of Thought reasoning'}
          </p>
        </div>
      </label>
    </div>
  </section>

  <!-- Dictionary Attachment -->
  <section class="bg-surface-card border border-border rounded-lg p-6">
    <h2 class="text-lg font-semibold text-text mb-4 flex items-center gap-2">
      {_t.translate?.config?.terminology_dictionaries}
      <HelpTooltip text={_t.translate?.config?.help_dictionaries || ''} />
    </h2>
    {#if availableDictionaries.length === 0}
      <p class="text-sm text-text-subtle">
        {_t.translate?.config?.no_dictionaries}
      </p>
    {:else}
      <div class="space-y-2">
        {#each availableDictionaries as dict}
          <label class="flex items-center gap-3 p-3 border border-border rounded-lg hover:bg-surface-muted cursor-pointer">
            <input
              type="checkbox"
              checked={dictionaryIds.includes(dict.id)}
              onchange={() => {
                if (dictionaryIds.includes(dict.id)) {
                  dictionaryIds = dictionaryIds.filter(d => d !== dict.id);
                } else {
                  dictionaryIds = [...dictionaryIds, dict.id];
                }
              }}
              class="rounded border-border-strong text-primary focus-visible:ring-primary-ring"
            />
            <div>
              <span class="text-sm font-medium text-text">{dict.name}</span>
              {#if dict.description}
                <p class="text-xs text-text-muted">{dict.description}</p>
              {/if}
            </div>
          </label>
        {/each}
      </div>
    {/if}
  </section>
</div>
<!-- #endregion ConfigTabForm -->
