<!-- #region TargetSchemaHint [C:3] [TYPE Component] [SEMANTICS translate, schema, validation, hint, button] -->
<!-- @BRIEF Подсказка о колонках целевой таблицы + кнопка "Проверить схему".
     Пользователь сам нажимает кнопку — никакого авто-шума.
     Показывает diff ожидаемых vs актуальных колонок. -->
<!-- @LAYER UI -->
<!-- @RELATION DEPENDS_ON -> [EXT:frontend:checkTargetTableSchema] -->
<!-- @RELATION BINDS_TO -> [EXT:frontend:api] -->
<!-- @UX_STATE Idle -> Кнопка активна. Ждём нажатия. -->
<!-- @UX_STATE Checking -> Спиннер, кнопка disabled. -->
<!-- @UX_STATE Complete -> Показан результат: все ок / отсутствуют колонки / таблица не найдена. -->
<!-- @UX_STATE Error -> Ошибка соединения. Кнопка активна для повтора. -->
<!-- @UX_FEEDBACK Цветовой индикатор: зелёный (все ок), жёлтый (не все колонки), красный (таблица не найдена/ошибка). -->
<!-- @UX_REACTIVITY Props -> $props() для полей конфигурации. -->
<script lang="ts">
  import { onDestroy } from 'svelte';
  import { checkTargetTableSchema } from '$lib/api/translate.js';
  import { _ } from '$lib/i18n/index.svelte.js';

  let {
    environmentId = '',
    targetDatabaseId = '',
    targetSchema = '',
    targetTable = '',
    targetKeyCols = [],
    targetColumn = null,
    translationColumn = null,
    targetLanguageColumn = null,
    targetSourceColumn = null,
    targetSourceLanguageColumn = null,
  } = $props();

  /** @type {'idle'|'checking'|'complete'|'error'} */
  let state = $state('idle');
  let result = $state(null);
  let abortController = $state(null);
  let renderKey = $state(0);

  /** CSS-класс body в зависимости от состояния */
  let bodyClass = $derived.by(() => {
    if (state === 'complete' && result?.all_present) return 'px-3 py-2.5 bg-success-light';
    if (state === 'complete' && !result?.all_present && result?.table_exists) return 'px-3 py-2.5 bg-warning-light';
    if (state === 'error' || (state === 'complete' && !result?.table_exists)) return 'px-3 py-2.5 bg-destructive-light';
    return 'px-3 py-2.5';
  });

  /** Колонки с типами для отображения — $state, наполняется в handleCheck() */
  let actualColumns = $state([]);

  /** Есть ли минимальные данные для проверки? */
  let canCheck = $derived(
    !!environmentId
    && !!targetDatabaseId
    && !!targetTable
  );

  /** Текст кнопки */
  let buttonLabel = $derived.by(() => {
    if (state === 'checking') return _('translate.target_schema.checking') || 'Checking…';
    if (state === 'complete') return _('translate.target_schema.check_again') || 'Check Again';
    return _('translate.target_schema.check_button') || 'Check Target Schema';
  });

  /**
   * Выводит тип колонки по соглашению именования,
   * когда реальный тип из БД недоступен.
   */
  function inferType(colName) {
    const n = colName.toLowerCase();
    // Служебные флаги и boolean
    if (n === 'is_original' || n.startsWith('is_') || n.startsWith('has_') || n.endsWith('_flag')) return 'INT';
    // Внешние ключи
    if (n.endsWith('_id') || n.endsWith('_key')) return 'INT';
    // Код языка
    if (n.endsWith('_lang') || n === 'lang_code' || n.endsWith('_language')) return 'STRING';
    // Даты
    if (n.endsWith('_date') || n.endsWith('_time') || n.endsWith('_at')) return 'DATETIME';
    // Всё остальное — текст
    return 'STRING';
  }

  /** Основная проверка */
  async function handleCheck() {
    if (!canCheck || state === 'checking') return;

    // Abort предыдущего запроса если был
    if (abortController) abortController.abort();
    abortController = new AbortController();
    const signal = abortController.signal;

    state = 'checking';
    result = null;
    try {
      const res = await checkTargetTableSchema({
        environment_id: environmentId,
        target_database_id: targetDatabaseId,
        target_schema: targetSchema || 'public',
        target_table: targetTable,
        target_key_cols: targetKeyCols || [],
        target_column: targetColumn || null,
        translation_column: translationColumn || null,
        target_language_column: targetLanguageColumn || null,
        target_source_column: targetSourceColumn || null,
        target_source_language_column: targetSourceLanguageColumn || null,
      });
      // Если запрос был отменён — не обновляем state
      if (signal.aborted) return;
      result = res;
      // Build merged column list with types from actual_columns
      const ac = res?.actual_columns || [];
      const actualMap = {};
      for (const c of ac) actualMap[c.name] = c;
      actualColumns = (res?.expected_columns || []).map(col => {
        const match = actualMap[col.name];
        return {
          name: col.name,
          data_type: match ? match.data_type : inferType(col.name),
          is_missing: (res?.missing_columns || []).some(m => m.name === col.name),
        };
      });
      state = 'complete';
      renderKey++;
    } catch {
      if (signal.aborted) return;
      state = 'error';
      result = null;
    }
  }

  onDestroy(() => {
    if (abortController) abortController.abort();
  });
</script>

<div class="target-schema-hint mt-3 rounded-lg border text-sm transition-colors"
  class:border-success={state === 'complete' && result?.all_present}
  class:border-warning={state === 'complete' && !result?.all_present && result?.table_exists}
  class:border-destructive-ring={state === 'error' || (state === 'complete' && !result?.table_exists)}
  class:border-border={state === 'idle' || state === 'checking'}
  role="region"
  aria-label={_('translate.target_schema.region_label') || 'Target Schema Check'}
>
  <!-- Header: label + кнопка -->
  <div class="flex items-center justify-between px-3 py-2 border-b border-border"
    class:bg-success-light={state === 'complete' && result?.all_present}
    class:bg-warning-light={state === 'complete' && !result?.all_present && result?.table_exists}
    class:bg-destructive-light={state === 'error' || (state === 'complete' && !result?.table_exists)}
    class:bg-surface-muted={state === 'idle' || state === 'checking'}
  >
    <div class="flex items-center gap-2">
      <!-- Иконка состояния -->
      {#if state === 'checking'}
        <svg class="w-4 h-4 text-text-subtle animate-spin" fill="none" viewBox="0 0 24 24">
          <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/>
          <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/>
        </svg>
      {:else if state === 'complete' && result?.all_present}
        <svg class="w-4 h-4 text-success" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
          <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/>
        </svg>
      {:else if state === 'complete' && !result?.table_exists}
        <svg class="w-4 h-4 text-destructive" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
          <circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/>
        </svg>
      {:else if state === 'complete' && !result?.all_present}
        <svg class="w-4 h-4 text-warning" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
          <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
        </svg>
      {:else}
        <svg class="w-4 h-4 text-text-subtle" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
          <path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/>
        </svg>
      {/if}

      <span class="font-medium text-text text-xs uppercase tracking-wide">
        {_('translate.target_schema.title') || 'Target Schema'}
      </span>
    </div>

    <!-- Кнопка -->
    <button
      onclick={handleCheck}
      disabled={!canCheck || state === 'checking'}
      class="text-xs font-medium px-3 py-1.5 rounded-md border transition-colors focus-visible:ring-2 focus-visible:ring-primary-ring focus-visible:outline-none"
      class:bg-surface-card={state !== 'checking'}
      class:text-text={state !== 'checking'}
      class:border-border-strong={state !== 'checking'}
      class:hover:bg-surface-muted={state !== 'checking'}
      class:bg-surface-muted={state === 'checking' || !canCheck}
      class:text-text-subtle={state === 'checking' || !canCheck}
      class:border-border={state === 'checking' || !canCheck}
      class:cursor-not-allowed={!canCheck || state === 'checking'}
      aria-busy={state === 'checking'}
    >
      {buttonLabel}
    </button>
  </div>

  <!-- Body: результат проверки -->
  <div class={bodyClass}>
    {#if state === 'idle'}
      <p class="text-text-muted">
        {#if !targetTable}
          {_('translate.target_schema.enter_table') || 'Enter a target table name and click "Check Target Schema".'}
        {:else if !targetDatabaseId}
          {_('translate.target_schema.select_database') || 'Select a target database and click "Check Target Schema".'}
        {:else}
          {_('translate.target_schema.press_button') || 'Click "Check Target Schema" to verify the target table columns.'}
        {/if}
      </p>

    {:else if state === 'checking'}
      <p class="text-text-muted">
        {_('translate.target_schema.checking') || 'Checking target table schema…'}
      </p>

    {:else if state === 'complete' && result}
      {#key renderKey}
        {#if !result.table_exists}
          <div class="flex items-center gap-2 text-destructive">
            <svg class="w-4 h-4 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
              <circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/>
            </svg>
            <p class="font-medium">{_('translate.target_schema.table_not_found') || 'Target table not found in the database.'}</p>
          </div>

        {:else if result.all_present}
          <div class="flex items-center gap-2 text-success">
            <svg class="w-4 h-4 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
              <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/>
            </svg>
            <p class="font-medium">{_('translate.target_schema.all_present') || 'Target table has all required columns.'}</p>
          </div>

        {:else}
          <div class="flex items-center gap-2 text-warning mb-2">
            <svg class="w-4 h-4 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
              <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
            </svg>
            <p class="font-medium">{_('translate.target_schema.missing_columns_title') || 'Target table is missing some required columns.'}</p>
          </div>
        {/if}

        <!-- Список колонок с типами -->
        {#if actualColumns.length > 0}
          <div class="mt-1.5">
            <p class="text-xs font-medium text-text-muted mb-1.5">
              {_('translate.target_schema.expected_columns') || 'Required columns for translation inserts:'}
            </p>
            <div class="flex flex-wrap gap-1.5">
              {#each actualColumns as col}
                <span
                  class="inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-mono border"
                  class:bg-success-light={!col.is_missing}
                  class:text-success={!col.is_missing}
                  class:border-success={!col.is_missing}
                  class:bg-destructive-light={col.is_missing}
                  class:text-destructive={col.is_missing}
                  class:border-destructive-ring={col.is_missing}
                >
                  {#if col.is_missing}
                    <svg class="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
                      <line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
                    </svg>
                  {:else}
                    <svg class="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
                      <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/>
                    </svg>
                  {/if}
                  <span>{col.name}</span>
                  {#if col.data_type}<span class="text-[10px] text-success/70">({col.data_type})</span>{/if}
                </span>
              {/each}
            </div>
          </div>
        {/if}
      {/key}

      <!-- Сопроводительный текст если есть пропущенные -->
      {#if result.table_exists && !result.all_present}
        <div class="mt-2 text-xs text-warning">
          <p>{_('translate.target_schema.add_columns') || 'Add these missing columns to the target table, or configure custom column names in "Target Column Mapping" above.'}</p>
        </div>
      {/if}

      <!-- Ошибка от Superset -->
      {#if result.error}
        <p class="mt-1.5 text-xs text-destructive font-mono">{result.error}</p>
      {/if}

    {:else if state === 'error'}
      <div class="flex items-center gap-2 text-destructive">
        <svg class="w-4 h-4 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
          <circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/>
        </svg>
        <p class="font-medium">
          {_('translate.target_schema.check_error') || 'Could not verify target table schema. Make sure the table exists and is accessible.'}
        </p>
      </div>
    {/if}
  </div>
</div>
<!-- #endregion TargetSchemaHint -->
