<!-- #region TranslationJobConfig [C:4] [TYPE Page] [SEMANTICS sveltekit, translate, job, config, llm, datasource] -->
<!-- @ingroup Routes -->
<!-- @BRIEF Translation job configuration wizard — renders TranslationJobModel state. 5 tabs: Config, Preview, Target, Run, Schedule. -->
<!-- @LAYER Page -->
<!-- @RELATION BINDS_TO -> [TranslationJobModel] -->

<!-- ===== UX CONTRACTS ===== -->
<!-- @UX_STATE idle — page not yet initialised. Skeleton loader visible. -->
<!-- @UX_STATE loading — environments, LLM providers and dictionaries being fetched. Full-page spinner. -->
<!-- @UX_STATE configured — job data loaded, form populated, tabs rendered. User interaction enabled. -->
<!-- @UX_STATE saving — PUT/POST in flight. Save button disabled, spinner shown. -->
<!-- @UX_STATE validation_error — form validation failed. Red borders on invalid fields, error summary card. -->
<!-- @UX_STATE datasource_unavailable — selected datasource not found in Superset. Warning banner, datasource re-selection prompt. -->
<!-- @UX_STATE error — unrecoverable error (job not found, network down). Error page with retry button. -->

<!-- @UX_STEP Config (tab) — Step 1: datasource selection with auto-detected DB dialect + column mapping + LLM + target languages. -->
<!-- @UX_STEP Preview (tab) — Step 2: translation quality gate. Available after save when configValid=true. -->
<!-- @UX_STEP Target (tab) — Step 3: target DB/schema/table config. Only for saved jobs (after Preview). -->
<!-- @UX_STEP Run (tab) — Step 4: translation execution. Run history, incremental/full modes, progress tracking. -->
<!-- @UX_STEP Schedule (tab) — Step 5: cron scheduling. Only for saved jobs. -->

<!-- @UX_FEEDBACK Toast on save/run/error actions. -->
<!-- @UX_FEEDBACK Modal — BulkReplaceModal for find-and-replace corrections. -->
<!-- @UX_RECOVERY Config tab save error — user can retry save; validation errors shown inline. -->

<script lang="ts">
  import { onMount } from 'svelte';
  import { goto } from '$app/navigation';
  import { ROUTES } from '$lib/routes';
  import { page } from '$app/state';
  import { getT } from '$lib/i18n/index.svelte.js';
  import { api } from '$lib/api.js';
  import { TranslationJobModel } from '$lib/models/TranslationJobModel.svelte';
  import TranslationPreview from '$lib/components/translate/TranslationPreview.svelte';

  import ScheduleConfig from '$lib/components/translate/ScheduleConfig.svelte';
  import BulkReplaceModal from '$lib/components/translate/BulkReplaceModal.svelte';
  import ConfigTabForm from '$lib/components/translate/ConfigTabForm.svelte';
  import TargetTabForm from '$lib/components/translate/TargetTabForm.svelte';
  import RunTabContent from '$lib/components/translate/RunTabContent.svelte';

  const m = new TranslationJobModel();
  // @RATIONALE Svelte 5 compiler fails to detect `t` as store in deeply nested
  //             template blocks, generating undefined `$t`. Bypass with `getT()`
  //             wrapped in $derived to keep template reactive to locale changes.
  const _t = $derived(getT());

  $effect(() => {
    m.jobId = page.params.id;
    m.isNewJob = page.params.id === 'new';
  });

  onMount(async () => {
    try {
      const envs = await api.getEnvironments?.() || [];
      m.environments = Array.isArray(envs) ? envs : [];
      if (m.environments.length > 0 && !m.environmentId) {
        m.environmentId = (m.environments[0]?.id as string) || '';
      }
    } catch { /* ignore */ }
    await m.loadInitialData();
    if (m.isNewJob && m.environmentId) { await m.loadDatabases(); }
  });

  $effect(() => {
    const env = m.environmentId;
    if (env && m.isNewJob) { m.loadDatabases(); if (m.datasourceId) m.loadDatasourceColumns(); }
  });

</script>

<svelte:head>
  <title>{m.pageTitle}</title>
</svelte:head>

<div class="container mx-auto px-4 py-6 max-w-full xl:max-w-7xl">
  <!-- Header -->
  <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-3 mb-6">
    <div class="min-w-0 flex-1">
      <h1 class="text-2xl font-bold text-text">
        {m.isNewJob ? _t.translate?.config?.new_title : _t.translate?.config?.edit_title}
      </h1>
      {#if !m.isNewJob && m.existingJob}
        <p class="text-sm text-text-muted mt-1">{_t.translate?.config?.id_label.replace('{id}', m.existingJob.id)}</p>
      {/if}
    </div>
    <div class="flex items-center gap-2 sm:gap-3 shrink-0">
      {#if m.isDirty}
        <span class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium bg-warning-light text-warning border border-warning">
          <span class="w-1.5 h-1.5 rounded-full bg-warning animate-pulse"></span>
          {_t.translate?.config?.unsaved_changes_title || 'Unsaved changes'}
        </span>
      {/if}
      <button onclick={() => goto(ROUTES.translate.list())} class="px-3 sm:px-4 py-2 border border-border-strong text-text rounded-lg hover:bg-surface-muted transition-colors text-sm sm:text-base whitespace-nowrap">
        {_t.translate?.config?.cancel}
      </button>
      <button onclick={() => m.saveJob()} disabled={m.isSaving} class="px-4 sm:px-6 py-2 bg-primary text-white rounded-lg hover:bg-primary-hover disabled:opacity-50 disabled:cursor-not-allowed transition-colors text-sm sm:text-base whitespace-nowrap">
        {m.isSaving ? _t.translate?.config?.saving : _t.translate?.config?.save}
      </button>
    </div>
  </div>

  <!-- Warnings -->
  {#if m.warnings.length > 0}
    <div class="bg-warning-light border border-warning rounded-lg p-4 mb-6">
      <h4 class="text-sm font-medium text-warning mb-2">{_t.translate?.config?.warnings_title}</h4>
      <ul class="list-disc list-inside text-sm text-warning space-y-1">
        {#each m.warnings as w}
          <li>{w}</li>
        {/each}
      </ul>
    </div>
  {/if}

  <!-- Loading -->
  {#if m.uxState === 'loading'}
    <div class="space-y-6">{#each Array(6) as _}<div class="h-16 bg-surface-muted rounded-lg animate-pulse"></div>{/each}</div>

  <!-- Error -->
  {:else if m.uxState === 'error'}
    <div class="bg-destructive-light border border-destructive-light rounded-lg p-6 text-center">
      <p class="text-destructive mb-3">{m.error || _t.translate?.common?.unknown_error}</p>
      <button onclick={() => goto(ROUTES.translate.list())} class="px-4 py-2 bg-primary text-white rounded-lg hover:bg-primary-hover transition-colors">{_t.translate?.config?.back_to_jobs}</button>
    </div>

  <!-- Datasource Unavailable -->
  {:else if m.uxState === 'datasource_unavailable'}
    <div class="bg-warning-light border border-orange-200 rounded-lg p-4 mb-6">
      <p class="text-warning text-sm">{_t.translate?.config?.datasource_unavailable}</p>
    </div>

  <!-- Form -->
  {:else if m.uxState === 'configured' || m.uxState === 'saving' || m.uxState === 'validation_error' || m.uxState === 'idle'}
    <!-- Tab Navigation -->
    <div class="border-b border-border mb-6">
      <nav class="flex gap-1" aria-label="Tabs">
        {#each m.tabs as tab}
          <button
            onclick={() => { m.activeTab = tab.id; }}
            disabled={(tab.id === 'preview' && (!m.configValid || m.isNewJob)) || (tab.id === 'target' && m.isNewJob)}
            class="flex-1 px-3 sm:px-4 py-2.5 text-sm font-medium rounded-t-lg transition-colors whitespace-nowrap
              {m.activeTab === tab.id
                ? 'bg-surface-card text-primary border border-b-white border-border -mb-px'
                : 'text-text-muted hover:text-text hover:bg-surface-muted'}
              {(tab.id === 'preview' && (!m.configValid || m.isNewJob)) || (tab.id === 'target' && m.isNewJob) ? 'opacity-40 cursor-not-allowed' : ''}"
            title={tab.id === 'preview' && (!m.configValid || m.isNewJob) ? (_t.translate?.preview?.config_incomplete || 'Configuration incomplete') : tab.id === 'target' && m.isNewJob ? (_t.translate?.config?.save_job_first || 'Save the job first') : ''}
          >
            {tab.label}
          </button>
        {/each}
      </nav>
    </div>

    <!-- Form content with dirty tracking -->
    <div oninput={() => m.markDirty()} onchange={() => m.markDirty()}>

    <!-- Config tab -->
    <div class={m.activeTab === 'config' ? '' : 'hidden'}>
      <ConfigTabForm
        bind:name={m.name}
        bind:description={m.description}
        bind:environmentId={m.environmentId}
        environments={m.environments}
        bind:datasourceId={m.datasourceId}
        bind:datasourceSearch={m.datasourceSearch}
        bind:databaseDialect={m.databaseDialect}
        bind:availableColumns={m.availableColumns}
        bind:virtualColumns={m.virtualColumns}
        bind:sourceKeyCols={m.sourceKeyCols}
        bind:targetKeyCols={m.targetKeyCols}
        bind:translationColumn={m.translationColumn}
        bind:contextColumns={m.contextColumns}
        bind:targetLanguages={m.targetLanguages}
        bind:targetLanguageColumn={m.targetLanguageColumn}
        bind:targetSourceColumn={m.targetSourceColumn}
        bind:targetSourceLanguageColumn={m.targetSourceLanguageColumn}
        bind:providerId={m.providerId}
        llmProviders={m.llmProviders}
        bind:dictionaryIds={m.dictionaryIds}
        availableDictionaries={m.availableDictionaries}
        bind:disableReasoning={m.disableReasoning}
        validationErrors={m.validationErrors}
        onEnvChange={(envId) => m.handleEnvChange(envId)}
      />
    </div>

    <!-- Schedule tab -->
    {#if !m.isNewJob}
      <div class={m.activeTab === 'schedule' ? '' : 'hidden'}>
        <section class="bg-surface-card border border-border rounded-lg">
          <ScheduleConfig jobId={m.jobId} />
        </section>
      </div>
    {/if}

    <!-- Preview tab -->
    <div class={m.activeTab === 'preview' ? '' : 'hidden'}>
      {#if !m.isNewJob && m.existingJob}
        {#if !m.configValid}
          <div class="bg-warning-light border border-warning rounded-lg p-6 text-center">
            <p class="text-sm text-warning font-medium mb-2">{_t.translate?.preview?.config_incomplete}</p>
            <p class="text-xs text-warning">{_t.translate?.preview?.config_requirements}</p>
          </div>
        {:else}
          <TranslationPreview jobId={m.jobId} environmentId={m.environmentId} />
        {/if}
      {:else}
        <div class="bg-surface-muted border border-border rounded-lg p-8 text-center">
          <p class="text-sm text-text-muted">{_t.translate?.config?.save_job_first || 'Save the job first'}</p>
        </div>
      {/if}
    </div>

    <!-- Target Config tab -->
    <div class={m.activeTab === 'target' ? '' : 'hidden'}>
      {#if !m.isNewJob && m.existingJob}
        <TargetTabForm
          bind:targetSchema={m.targetSchema}
          bind:targetTable={m.targetTable}
          bind:targetDatabaseId={m.targetDatabaseId}
          bind:targetColumn={m.targetColumn}
          bind:targetLanguageColumn={m.targetLanguageColumn}
          bind:targetSourceColumn={m.targetSourceColumn}
          bind:targetSourceLanguageColumn={m.targetSourceLanguageColumn}
          bind:targetKeyCols={m.targetKeyCols}
          bind:translationColumn={m.translationColumn}
          bind:batchSize={m.batchSize}
          bind:includeSourceReference={m.includeSourceReference}
          bind:upsertStrategy={m.upsertStrategy}
          bind:insertMethod={m.insertMethod}
          bind:connectionId={m.connectionId}
          databaseDialect={m.databaseDialect}
          environmentId={m.environmentId}
          databases={m.databases}
          databasesLoading={m.databasesLoading}
          onSchemaCheckResult={(ok) => { m.schemaValidated = ok; }}
        />
      {:else}
        <div class="bg-surface-muted border border-border rounded-lg p-8 text-center">
          <p class="text-sm text-text-muted">{_t.translate?.config?.save_job_first || 'Save the job first'}</p>
        </div>
      {/if}
    </div>

    <!-- Run tab -->
    <div class={m.activeTab === 'run' ? '' : 'hidden'}>
      {#if !m.isNewJob && m.existingJob}
        <!-- Insert method badge — visible before run -->
        <div class="mb-4 flex items-center gap-2">
          <span class="text-xs text-text-muted">{_t.translate?.config?.insert_method || 'Insert Method'}:</span>
          <span class="inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-medium border
            {m.insertMethod === 'direct_db' ? 'bg-primary/10 text-primary border-primary/20' : 'bg-surface-muted text-text-subtle border-border'}">
            {#if m.insertMethod === 'direct_db'}
              <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="M4 7v10c0 2 1 3 3 3h10c2 0 3-1 3-3V7M4 7c0-2 1-3 3-3h10c2 0 3 1 3 3M4 7h16M9 11h.01M15 11h.01M9 15h.01M15 15h.01"/></svg>
              {_t.translate?.config?.insert_method_direct_db || 'Direct DB'}
            {: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="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"/></svg>
              {_t.translate?.config?.insert_method_sqllab || 'SQL Lab'}
            {/if}
          </span>
        </div>
        <RunTabContent
          bind:status={m.status}
          jobId={m.jobId}
          isRunning={m.isRunning}
          isFullRun={m.isFullRun}
          runError={m.runError}
          currentRunId={m.currentRunId}
          runComplete={m.runComplete}
          completedRuns={m.completedRuns}
          expandedRunIds={m.expandedRunIds}
          runHistoryHasMore={m.runHistoryHasMore}
          bind:showPageBulkReplace={m.showPageBulkReplace}
          schemaValidated={m.schemaValidated}
          onTriggerRun={(full) => m.handleTriggerRun(full)}
          onRetryRun={() => m.handleRetryRun()}
          onRetryInsert={() => m.handleRetryInsert()}
          onLoadRunHistory={() => m.loadRunHistory()}
          onLoadMoreRuns={() => m.loadRunHistory(true)}
          onToggleRunDetails={(id) => m.toggleRunDetails(id)}
          onGoToTargetTab={() => m.activeTab = 'target'}
          onDismissRun={() => m.handleDismissRun()}
        />
      {:else}
        <div class="bg-surface-muted border border-border rounded-lg p-8 text-center">
          <p class="text-sm text-text-muted">{_t.translate?.config?.save_job_first || 'Save the job first'}</p>
        </div>
      {/if}
    </div>
    </div>
  {/if}
</div>

<BulkReplaceModal
  show={m.showPageBulkReplace}
  runId={m.completedRuns[0]?.id || ''}
  targetLanguages={m.targetLanguages}
  onClose={() => m.showPageBulkReplace = false}
  onApplied={() => { m.showPageBulkReplace = false; m.loadRunHistory(); }}
/>
<!-- #endregion TranslationJobConfig -->
