<!-- #region ValidationTaskForm [C:4] [TYPE Component] [SEMANTICS llm,validation,form,multi-step] -->
<!-- @BRIEF Multi-step validation task creation/edit form — manages all state for name, sources, analysis options, schedule, and review. -->
<!-- @RELATION DEPENDS_ON -> [ApiModule] -->
<!-- @RELATION DEPENDS_ON -> [UrlParser] -->
<!-- @RELATION DEPENDS_ON -> [SearchableMultiSelect] -->
<!-- @RELATION BINDS_TO -> [I18nModule] -->
<!-- @RELATION BINDS_TO -> [environmentContextStore] -->
<!-- @UX_STATE step_1 -> Name & Environment visible -->
<!-- @UX_STATE step_2 -> Sources tab visible (From List / From URL) -->
<!-- @UX_STATE step_3 -> Analysis Options visible -->
<!-- @UX_STATE step_4 -> Schedule selection visible -->
<!-- @UX_STATE step_5 -> Review summary visible -->
<!-- @UX_STATE submitting -> Form submitting spinner on submit button -->
<!-- @UX_FEEDBACK Toast on validation errors, provider switch warnings -->
<!-- @UX_RECOVERY Back button to previous step; clear and retry on errors -->
<script lang="ts">
  import { t } from '$lib/i18n/index.svelte.js';
  import { addToast } from '$lib/toasts.svelte.js';
  import { environmentContextStore } from '$lib/stores/environmentContext.svelte.js';
  import { api } from '$lib/api.js';
  import UrlParser from './UrlParser.svelte';
  import SearchableMultiSelect from '$lib/components/ui/SearchableMultiSelect.svelte';
  import HelpTooltip from '$lib/ui/HelpTooltip.svelte';

  // ── Props ─────────────────────────────────────────────────────
  /**
   * @prop {Object|null} initialData — Task data for edit mode
   * @prop {Function} onSubmit — Called with form data object on submit
   * @prop {Function} onCancel — Called when cancel is clicked
   * @prop {Array} llmProviders — List of LLM providers from load function
   * @prop {boolean} isSubmitting — External submitting state
   */
  let {
    initialData = null,
    onSubmit = undefined,
    onCancel = undefined,
    llmProviders = [],
    isSubmitting = false,
  } = $props();

  // ── Step Management ───────────────────────────────────────────
  let currentStep = $state(1);
  const totalSteps = 5;

  // ── Form State (initialized empty, populated via $effect for edit mode) ──
  let taskName = $state('');
  let taskDescription = $state('');
  /** @type {string} */
  let selectedEnvId = $state('');

  // Derive environment list from store
  let envOptions = $derived(
    $environmentContextStore.environments.map((/** @type {any} */ e) => ({
      id: e.id,
      name: e.name || e.id,
    }))
  );

  // ── Step 2: Sources ───────────────────────────────────────────
  /** @type {'list'|'url'} */
  let sourceTab = $state('list');
  /** @type {string[]} */
  let selectedDashboardIds = $state([]);
  /** @type {Array<{url: string, title: string, filters_count?: number, tabs_count?: number}>} */
  let parsedSources = $state([]);
  /** @type {Array<{id: string, dashboard_title: string}>} */
  let dashboards = $state([]);
  let dashboardsLoading = $state(false);
  let dashboardsError = $state('');
  let dashboardSearchQuery = $state('');

  // ── Step 3: Analysis Options ──────────────────────────────────
  let selectedProviderId = $state('');
  let screenshotEnabled = $state(false);
  let logsEnabled = $state(true);
  let executeChartData = $state(false);
  let llmBatchSize = $state(1);
  let promptTemplate = $state('');

  // Provider data
  /** @type {Array<{id: string, name: string, is_multimodal: boolean, is_active: boolean}>} */
  let providers = $state([]);

  // Filter providers based on screenshot mode
  let filteredProviders = $derived(
    screenshotEnabled
      ? providers.filter((p) => p.is_multimodal && p.is_active)
      : providers.filter((p) => p.is_active)
  );

  let selectedProvider = $derived(
    filteredProviders.find((p) => p.id === selectedProviderId) || null
  );

  // ── Step 4: Schedule ──────────────────────────────────────────
  /** @type {'manual'|'scheduled'} */
  let scheduleType = $state('manual');
  /** @type {number[]} */
  let scheduleDays = $state([]);
  let scheduleStartTime = $state('02:00');
  let scheduleEndTime = $state('03:00');

  // ── Initialization from initialData (edit mode) ───────────────
  // $effect captures prop values once on mount, avoiding state_referenced_locally warning
  let initialized = $state(false);
  $effect(() => {
    if (initialData && !initialized) {
      taskName = initialData.name ?? '';
      taskDescription = initialData.description ?? '';
      selectedEnvId = initialData.environment_id ?? '';
      selectedDashboardIds = initialData.dashboard_ids ?? [];
      parsedSources = initialData.parsed_urls ?? [];
      selectedProviderId = initialData.llm_provider_id ?? '';
      screenshotEnabled = initialData.screenshot_enabled ?? false;
      logsEnabled = initialData.logs_enabled ?? true;
      executeChartData = initialData.execute_chart_data ?? false;
      llmBatchSize = initialData.llm_batch_size ?? 1;
      promptTemplate = initialData.prompt_template ?? '';
      // Schedule: use raw schedule_days, window_start, window_end from server
      if (initialData.schedule_days && initialData.schedule_days.length > 0) {
        scheduleType = 'scheduled';
        scheduleDays = [...initialData.schedule_days];
        scheduleStartTime = initialData.window_start || '02:00';
        scheduleEndTime = initialData.window_end || '03:00';
      } else {
        scheduleType = 'manual';
        scheduleDays = [];
        scheduleStartTime = '02:00';
        scheduleEndTime = '03:00';
      }
      // Set default prompt if not provided
      if (!promptTemplate) {
        promptTemplate = screenshotEnabled
          ? ($t.validation?.prompt_default_a || 'Analyze this dashboard screenshot for issues...')
          : ($t.validation?.prompt_default_b || 'Analyze this dashboard data for issues...');
      }
      initialized = true;
    }
  });

  function getDefaultPrompt() {
    return screenshotEnabled
      ? ($t.validation?.prompt_default_a || 'Analyze this dashboard screenshot for issues with chart rendering, data accuracy, and visual consistency.')
      : ($t.validation?.prompt_default_b || 'Analyze this dashboard data for issues with chart queries, dataset health, and configuration.');
  }

  // When screenshot toggles, update prompt if it's still the default from the other path
  function handleScreenshotToggle() {
    const oldVal = screenshotEnabled;
    screenshotEnabled = !screenshotEnabled;

    // Reset prompt to default for new path if unchanged
    promptTemplate = getDefaultPrompt();

    // If turning ON and current provider is not multimodal, reset provider
    if (screenshotEnabled) {
      if (selectedProviderId && !providers.find(p => p.id === selectedProviderId)?.is_multimodal) {
        selectedProviderId = '';
        addToast($t.validation?.provider_screenshot_warning || 'Screenshot enabled — provider was reset (not multimodal)', 'warning');
      }
    }

    // If turning OFF, batch size becomes visible (keep current)
    if (!screenshotEnabled && llmBatchSize < 1) {
      llmBatchSize = 1;
    }

    // Hide execute_chart_data when screenshot is ON
    if (screenshotEnabled) {
      executeChartData = false;
    }

    addToast($t.validation?.prompt_toggle_warning || 'Switching path may change the prompt template', 'info');
  }

  // ── Derived ───────────────────────────────────────────────────
  /** @type {Array<{id: string, name: string}>} */
  let dashboardOptions = $derived(
    dashboards.map((d) => ({ id: String(d.id), name: d.title || String(d.id) }))
  );

  let hasSources = $derived(selectedDashboardIds.length > 0 || parsedSources.length > 0);
  let totalSourceCount = $derived(selectedDashboardIds.length + parsedSources.length);

  // Validation per step
  let stepErrors = $derived.by(() => {
    /** @type {Record<string, string>} */
    const errs = {};
    if (currentStep === 1) {
      if (!taskName.trim()) errs.taskName = $t.validation?.form_validation_required || 'Required';
      if (!selectedEnvId) errs.selectedEnvId = $t.validation?.form_validation_required || 'Required';
    }
    if (currentStep === 3) {
      if (!selectedProviderId) errs.selectedProviderId = $t.validation?.provider_required || 'Provider is required';
      if (screenshotEnabled && selectedProviderId && !providers.find(p => p.id === selectedProviderId)?.is_multimodal) {
        errs.selectedProviderId = $t.validation?.multimodal_required || 'Screenshot mode requires a multimodal provider';
      }
      if (llmBatchSize < 1) errs.llmBatchSize = 'Minimum is 1';
    }
    if (currentStep === 4) {
      if (scheduleType === 'scheduled' && scheduleDays.length === 0) {
        errs.scheduleDays = $t.validation?.schedule_days_required || 'Select at least one day';
      }
    }
    return errs;
  });

  let canAdvance = $derived(Object.keys(stepErrors).length === 0);

  // ── Dashboard loading ─────────────────────────────────────────
  async function loadDashboards(envId) {
    if (!envId) {
      dashboards = [];
      return;
    }
    dashboardsLoading = true;
    dashboardsError = '';
    try {
      const result = await api.getDashboards(envId, { page_size: 100 });
      const items = result?.results ?? result?.dashboards ?? result ?? [];
      dashboards = Array.isArray(items) ? items : [];
    } catch (err) {
      dashboardsError = err?.message || ($t.validation?.dashboards_load_error || 'Failed to load dashboards');
      dashboards = [];
    } finally {
      dashboardsLoading = false;
    }
  }

  const dayNames = $derived([
    $t.validation?.days_sun || 'Sun',
    $t.validation?.days_mon || 'Mon',
    $t.validation?.days_tue || 'Tue',
    $t.validation?.days_wed || 'Wed',
    $t.validation?.days_thu || 'Thu',
    $t.validation?.days_fri || 'Fri',
    $t.validation?.days_sat || 'Sat',
  ]);

  function toggleDay(day: number) {
    if (scheduleDays.includes(day)) {
      scheduleDays = scheduleDays.filter((d) => d !== day);
    } else {
      scheduleDays = [...scheduleDays, day].sort();
    }
  }

  let scheduleWindowLabel = $derived.by(() => {
    if (!scheduleStartTime || !scheduleEndTime) return '';
    const startH = parseInt(scheduleStartTime.split(':')[0]);
    const endH = parseInt(scheduleEndTime.split(':')[0]);
    const startM = parseInt(scheduleStartTime.split(':')[1]);
    const endM = parseInt(scheduleEndTime.split(':')[1]);
    const durationMin = (endH * 60 + endM) - (startH * 60 + startM);
    if (durationMin <= 0) return $t.validation?.window_invalid || 'Window must end after start';
    if (durationMin < 60) return `${durationMin} min`;
    const hours = Math.floor(durationMin / 60);
    const mins = durationMin % 60;
    return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;
  });

  // Watch environment changes to load dashboards
  $effect(() => {
    if (selectedEnvId) {
      loadDashboards(selectedEnvId);
    }
  });

  // Initialize providers from prop
  $effect(() => {
    if (llmProviders && llmProviders.length > 0) {
      providers = llmProviders;
    }
  });

  // ── Navigation ────────────────────────────────────────────────
  function nextStep() {
    if (!canAdvance) {
      const firstError = Object.values(stepErrors)[0];
      if (firstError) addToast(firstError, 'warning');
      return;
    }
    if (currentStep < totalSteps) {
      currentStep++;
    }
  }

  function prevStep() {
    if (currentStep > 1) {
      currentStep--;
    }
  }

  function handleSubmit() {
    if (!onSubmit) return;

    // Final validation
    if (!taskName.trim()) {
      currentStep = 1;
      addToast($t.validation?.form_validation_required || 'Task name is required', 'warning');
      return;
    }
    if (!selectedEnvId) {
      currentStep = 1;
      addToast($t.validation?.form_validation_required || 'Environment is required', 'warning');
      return;
    }
    if (!hasSources) {
      currentStep = 2;
      addToast($t.validation?.sources_required || 'At least one dashboard source is required', 'warning');
      return;
    }
    if (!selectedProviderId) {
      currentStep = 3;
      addToast($t.validation?.provider_required || 'Provider is required', 'warning');
      return;
    }

    /** @type {Record<string, any>} */
    const formData = {
      name: taskName.trim(),
      description: taskDescription.trim() || undefined,
      environment_id: selectedEnvId,
      dashboard_ids: selectedDashboardIds,
      sources: parsedSources.map((s) => ({ type: 'dashboard_url', value: s.url })),
      screenshot_enabled: screenshotEnabled,
      logs_enabled: logsEnabled,
      execute_chart_data: executeChartData && !screenshotEnabled,
      llm_batch_size: screenshotEnabled ? 1 : llmBatchSize,
      provider_id: selectedProviderId,
      prompt_template: promptTemplate.trim() || undefined,
      schedule_days: scheduleType === 'scheduled' ? [...scheduleDays] : null,
      window_start: scheduleType === 'scheduled' ? scheduleStartTime : null,
      window_end: scheduleType === 'scheduled' ? scheduleEndTime : null,
      is_active: true,
    };

    onSubmit(formData);
  }

  function handleAddParsedSource(source) {
    // Avoid duplicates
    if (!parsedSources.some((s) => s.url === source.url)) {
      parsedSources = [...parsedSources, source];
    }
  }

  function removeParsedSource(url) {
    parsedSources = parsedSources.filter((s) => s.url !== url);
  }

  // ── Step labels ───────────────────────────────────────────────
  const stepLabels = [
    'step_name',
    'step_sources',
    'step_options',
    'step_schedule',
    'step_review',
  ];

  // ── Provider display helpers ──────────────────────────────────
  function getProviderName(id) {
    const p = providers.find((p) => p.id === id);
    return p?.name || id;
  }

  function getEnvName(id) {
    const env = $environmentContextStore.environments.find((/** @type {any} */ e) => e.id === id);
    return env?.name || env?.id || id;
  }
</script>

<div class="max-w-3xl mx-auto">
  <!-- Step Indicator -->
  <nav class="mb-8" aria-label="Progress">
    <div class="flex items-center justify-between">
      {#each stepLabels as label, i (i)}
        <button
          onclick={() => { if (i < currentStep || (i === currentStep - 1)) currentStep = i + 1; }}
          disabled={i >= currentStep}
          class="flex flex-col items-center gap-1.5 {i >= currentStep ? 'cursor-default' : 'cursor-pointer'}"
        >
          <div
            class="flex items-center justify-center w-8 h-8 rounded-full text-sm font-medium transition-colors"
            class:bg-blue-600={i + 1 === currentStep}
            class:text-white={i + 1 === currentStep}
            class:bg-blue-100={i + 1 < currentStep}
            class:text-blue-700={i + 1 < currentStep}
            class:bg-gray-100={i + 1 > currentStep}
            class:text-gray-400={i + 1 > currentStep}
          >
            {#if i + 1 < currentStep}
              <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.5" d="M5 13l4 4L19 7" />
              </svg>
            {:else}
              {i + 1}
            {/if}
          </div>
          <span
            class="text-xs font-medium hidden sm:block"
            class:text-blue-600={i + 1 === currentStep}
            class:text-blue-500={i + 1 < currentStep}
            class:text-gray-400={i + 1 > currentStep}
          >
            {$t.validation?.[label] || label}
          </span>
        </button>
        {#if i < stepLabels.length - 1}
          <div class="flex-1 h-0.5 mx-2 rounded"
            class:bg-blue-300={i + 1 < currentStep}
            class:bg-gray-200={i + 1 >= currentStep}
          ></div>
        {/if}
      {/each}
    </div>
    <p class="text-center text-sm text-gray-500 mt-2 sm:hidden">
      {($t.validation?.step_x_of_y || 'Step {x} of {y}')
        .replace('{x}', String(currentStep))
        .replace('{y}', String(totalSteps))}
    </p>
  </nav>

  <!-- Step Content -->
  <div class="bg-white border border-gray-200 rounded-lg shadow-sm">
    <!-- ────── Step 1: Name & Environment ────── -->
    {#if currentStep === 1}
      <div class="p-6 space-y-6">
        <h2 class="text-lg font-semibold text-gray-900">{$t.validation?.step_name || 'Name & Environment'}</h2>

        <!-- Task Name -->
        <div>
          <label for="task-name" class="block text-sm font-medium text-gray-700 mb-1">
            {$t.validation?.task_name || 'Task Name'} <span class="text-red-500">*</span>
          </label>
          <input
            id="task-name"
            type="text"
            value={taskName}
            oninput={(e) => { taskName = /** @type {HTMLInputElement} */(e.target).value; }}
            class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none {stepErrors.taskName ? 'border-red-400' : ''}"
            placeholder={$t.validation?.task_name || 'My Validation Task'}
            aria-required="true"
            aria-invalid={!!stepErrors.taskName}
          />
          {#if stepErrors.taskName}
            <p class="mt-1 text-xs text-red-500">{stepErrors.taskName}</p>
          {/if}
        </div>

        <!-- Description -->
        <div>
          <label for="task-desc" class="block text-sm font-medium text-gray-700 mb-1">
            {$t.validation?.task_description || 'Description (optional)'}
          </label>
          <textarea
            id="task-desc"
            value={taskDescription}
            oninput={(e) => { taskDescription = /** @type {HTMLTextAreaElement} */(e.target).value; }}
            rows="3"
            class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none resize-y"
            placeholder="Describe what this validation task checks..."
          ></textarea>
        </div>

        <!-- Environment -->
        <div>
          <label for="env-select" class="block text-sm font-medium text-gray-700 mb-1">
            {$t.validation?.environment || 'Environment'} <span class="text-red-500">*</span>
          </label>
          <select
            id="env-select"
            value={selectedEnvId}
            onchange={(e) => { selectedEnvId = /** @type {HTMLSelectElement} */(e.target).value; }}
            class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none {stepErrors.selectedEnvId ? 'border-red-400' : ''}"
            aria-required="true"
            aria-invalid={!!stepErrors.selectedEnvId}
          >
            <option value="">-- {$t.validation?.select_environment || 'Select environment'} --</option>
            {#each envOptions as env (env.id)}
              <option value={env.id}>{env.name}</option>
            {/each}
          </select>
          {#if stepErrors.selectedEnvId}
            <p class="mt-1 text-xs text-red-500">{stepErrors.selectedEnvId}</p>
          {/if}
        </div>
      </div>

    <!-- ────── Step 2: Sources ────── -->
    {:else if currentStep === 2}
      <div class="p-6 space-y-6">
        <h2 class="text-lg font-semibold text-gray-900">{$t.validation?.step_sources || 'Sources'}</h2>

        <!-- Tab Bar -->
        <div class="flex border-b border-gray-200">
          <button
            onclick={() => { sourceTab = 'list'; }}
            class="px-4 py-2.5 text-sm font-medium border-b-2 transition-colors -mb-px"
            class:border-blue-600={sourceTab === 'list'}
            class:text-blue-600={sourceTab === 'list'}
            class:border-transparent={sourceTab !== 'list'}
            class:text-gray-500={sourceTab !== 'list'}
            class:hover:text-gray-700={sourceTab !== 'list'}
            class:hover:border-gray-300={sourceTab !== 'list'}
          >
            {$t.validation?.from_list || 'From List'}
          </button>
          <button
            onclick={() => { sourceTab = 'url'; }}
            class="px-4 py-2.5 text-sm font-medium border-b-2 transition-colors -mb-px"
            class:border-blue-600={sourceTab === 'url'}
            class:text-blue-600={sourceTab === 'url'}
            class:border-transparent={sourceTab !== 'url'}
            class:text-gray-500={sourceTab !== 'url'}
            class:hover:text-gray-700={sourceTab !== 'url'}
            class:hover:border-gray-300={sourceTab !== 'url'}
          >
            {$t.validation?.from_url || 'From URL'}
          </button>
        </div>

        <!-- Tab: From List -->
        {#if sourceTab === 'list'}
          <div>
            {#if !selectedEnvId}
              <div class="bg-amber-50 border border-amber-200 rounded-lg p-4 text-sm text-amber-700">
                {$t.validation?.select_environment || 'Select an environment first'}
              </div>
            {:else if dashboardsLoading}
              <div class="flex items-center gap-2 text-sm text-gray-500 py-4">
                <svg class="animate-spin h-4 w-4 text-blue-500" 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>
                {$t.validation?.load_dashboards || 'Loading dashboards...'}
              </div>
            {:else if dashboardsError}
              <div class="bg-red-50 border border-red-200 rounded-lg p-4 text-sm text-red-700">
                {dashboardsError}
              </div>
            {:else}
              <SearchableMultiSelect
                options={dashboardOptions}
                bind:selected={selectedDashboardIds}
                label={$t.validation?.dashboard || 'Dashboards'}
                placeholder={$t.validation?.search_dashboards || 'Search dashboards...'}
                emptyMessage={$t.validation?.no_dashboards || 'No dashboards found'}
              />
            {/if}
          </div>

        <!-- Tab: From URL -->
        {:else}
          <div class="space-y-4">
            <UrlParser
              envId={selectedEnvId}
              onAdd={handleAddParsedSource}
            />

            <!-- Parsed Sources List -->
            {#if parsedSources.length > 0}
              <div class="mt-4">
                <h4 class="text-sm font-medium text-gray-700 mb-2">
                  {$t.validation?.parsed_sources || 'Parsed sources'} ({parsedSources.length})
                </h4>
                <ul class="space-y-2">
                  {#each parsedSources as source, i (source.url)}
                    <li class="flex items-center gap-2 px-3 py-2 bg-gray-50 border border-gray-200 rounded-lg text-sm">
                      <svg class="w-4 h-4 text-gray-400 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
                      </svg>
                      <span class="flex-1 truncate font-medium text-gray-900">{source.title}</span>
                      <span class="text-xs text-gray-400">
                        {source.filters_count ?? 0}f · {source.tabs_count ?? 0}t
                      </span>
                      <button
                        onclick={() => removeParsedSource(source.url)}
                        class="flex-shrink-0 p-1 text-gray-400 hover:text-red-500 rounded hover:bg-red-50 transition-colors"
                        aria-label={($t.validation?.remove || 'Remove') + ' ' + source.title}
                      >
                        <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>
                    </li>
                  {/each}
                </ul>
              </div>
            {/if}
          </div>
        {/if}

        <!-- Source summary -->
        <div class="text-sm text-gray-500 pt-2 border-t border-gray-100">
          {#if totalSourceCount > 0}
            {($t.validation?.source_count || '{n} source(s) configured')
              .replace('{n}', String(totalSourceCount))}
            {#if selectedDashboardIds.length > 0}
              · {($t.validation?.dashboard_count || '{n} dashboard(s) selected')
                .replace('{n}', String(selectedDashboardIds.length))}
            {/if}
          {:else}
            {$t.validation?.no_sources || 'No sources configured yet'}
          {/if}
        </div>
      </div>

    <!-- ────── Step 3: Analysis Options ────── -->
    {:else if currentStep === 3}
      <div class="p-6 space-y-6">
        <h2 class="text-lg font-semibold text-gray-900">{$t.validation?.step_options || 'Analysis Options'}</h2>

        <!-- Path indicator -->
        <div class="flex gap-3 p-3 bg-gray-50 rounded-lg border border-gray-200">
          <div class="flex items-center gap-2 text-sm">
            <span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium {screenshotEnabled ? 'bg-blue-100 text-blue-700' : 'bg-gray-200 text-gray-500'}">
              {$t.validation?.screenshot_path_a || 'Path A'}
            </span>
            <span class="text-gray-500">vs</span>
            <span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium {!screenshotEnabled ? 'bg-green-100 text-green-700' : 'bg-gray-200 text-gray-500'}">
              {$t.validation?.screenshot_path_b || 'Path B'}
            </span>
          </div>
        </div>

        <!-- Screenshot Toggle -->
        <div class="flex items-start gap-3">
          <button
            onclick={handleScreenshotToggle}
            class="relative inline-flex h-6 w-11 items-center rounded-full transition-colors flex-shrink-0 mt-0.5 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
            class:bg-blue-600={screenshotEnabled}
            class:bg-gray-300={!screenshotEnabled}
            role="switch"
            aria-checked={screenshotEnabled}
            aria-label={$t.validation?.screenshot_enabled || 'Screenshot'}
          >
            <span
              class="inline-block h-4 w-4 transform rounded-full bg-white transition-transform"
              class:translate-x-6={screenshotEnabled}
              class:translate-x-1={!screenshotEnabled}
            ></span>
          </button>
          <div>
            <span id="screenshot-label" class="text-sm font-medium text-gray-900">
              {$t.validation?.screenshot_enabled || 'Screenshot (Playwright)'}
            </span>
            <p class="text-xs text-gray-500 mt-0.5">
              {screenshotEnabled
                ? ($t.validation?.path_a_label || 'ON — Visual analysis via screenshots (Path A)')
                : ($t.validation?.path_b_label || 'OFF — Text-only analysis via API (Path B)')}
            </p>
          </div>
        </div>

        <!-- LLM Provider -->
        <div>
          <label for="provider-select" class="block text-sm font-medium text-gray-700 mb-1">
            {$t.validation?.llm_provider || 'LLM Provider'} <span class="text-red-500">*</span>
          </label>
          {#if providers.length === 0}
            <div class="bg-amber-50 border border-amber-200 rounded-lg p-3 text-sm text-amber-700">
              {$t.validation?.no_providers || 'No LLM providers configured'}
            </div>
          {:else}
            <select
              id="provider-select"
              value={selectedProviderId}
              onchange={(e) => { selectedProviderId = /** @type {HTMLSelectElement} */(e.target).value; }}
              class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none {stepErrors.selectedProviderId ? 'border-red-400' : ''}"
              aria-required="true"
              aria-invalid={!!stepErrors.selectedProviderId}
            >
              <option value="">-- {$t.validation?.llm_provider || 'Select provider'} --</option>
              {#each filteredProviders as provider (provider.id)}
                <option value={provider.id}>
                  {provider.name} {provider.is_multimodal ? '📷' : ''}
                </option>
              {/each}
            </select>
            {#if filteredProviders.length < providers.length && screenshotEnabled}
              <p class="mt-1 text-xs text-amber-600">
                {$t.validation?.multimodal_required || 'Showing only multimodal providers'}
              </p>
            {/if}
            {#if stepErrors.selectedProviderId}
              <p class="mt-1 text-xs text-red-500">{stepErrors.selectedProviderId}</p>
            {/if}
          {/if}
        </div>

        <!-- Logs Toggle -->
        <div class="flex items-center gap-3">
          <input
            id="logs-enabled"
            type="checkbox"
            checked={logsEnabled}
            onchange={(e) => { logsEnabled = /** @type {HTMLInputElement} */(e.target).checked; }}
            class="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
          />
          <label for="logs-enabled" class="text-sm text-gray-700">
            {$t.validation?.logs_enabled || 'Fetch Superset execution logs'}
          </label>
        </div>

        <!-- Execute Chart Data (only when screenshot disabled) -->
        {#if !screenshotEnabled}
          <div class="flex items-center gap-3">
            <input
              id="execute-chart"
              type="checkbox"
              checked={executeChartData}
              onchange={(e) => { executeChartData = /** @type {HTMLInputElement} */(e.target).checked; }}
              class="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
            />
            <label for="execute-chart" class="text-sm text-gray-700">
              {$t.validation?.execute_chart_data || 'Execute chart queries (Path B, load-aware)'}
            </label>
          </div>
        {/if}

        <!-- LLM Batch Size (only when screenshot disabled) -->
        {#if !screenshotEnabled}
          <div>
            <label for="batch-size" class="block text-sm font-medium text-gray-700 mb-1">
              {$t.validation?.llm_batch_size || 'Dashboards per LLM call (1 = full isolation)'}
            </label>
            <input
              id="batch-size"
              type="number"
              value={llmBatchSize}
              oninput={(e) => { llmBatchSize = Math.max(1, parseInt(/** @type {HTMLInputElement} */(e.target).value) || 1); }}
              min="1"
              max="50"
              class="w-24 px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none {stepErrors.llmBatchSize ? 'border-red-400' : ''}"
            />
            {#if stepErrors.llmBatchSize}
              <p class="mt-1 text-xs text-red-500">{stepErrors.llmBatchSize}</p>
            {/if}
          </div>
        {/if}

        <!-- Prompt Template -->
        <div>
          <div class="flex items-center justify-between mb-1">
            <label for="prompt-template" class="block text-sm font-medium text-gray-700">
              {$t.validation?.prompt_template || 'Prompt Template (optional)'}
            </label>
            <button
              onclick={() => { promptTemplate = getDefaultPrompt(); }}
              class="text-xs text-blue-600 hover:text-blue-800"
            >
              {$t.common?.reset || 'Reset to default'}
            </button>
          </div>
          <textarea
            id="prompt-template"
            value={promptTemplate}
            oninput={(e) => { promptTemplate = /** @type {HTMLTextAreaElement} */(e.target).value; }}
            rows="4"
            class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none resize-y font-mono"
            placeholder={getDefaultPrompt()}
          ></textarea>
        </div>
      </div>

    <!-- ────── Step 4: Schedule ────── -->
    {:else if currentStep === 4}
      <div class="p-6 space-y-6">
        <h2 class="text-lg font-semibold text-gray-900">{$t.validation?.step_schedule || 'Schedule'}</h2>

        <!-- Manual trigger -->
        <label class="flex items-start gap-3 p-4 border rounded-lg cursor-pointer transition-colors {scheduleType === 'manual' ? 'border-blue-300 bg-blue-50' : 'border-gray-200 hover:bg-gray-50'}">
          <input
            type="radio"
            name="schedule"
            value="manual"
            checked={scheduleType === 'manual'}
            onchange={() => { scheduleType = 'manual'; }}
            class="mt-0.5 text-blue-600 focus:ring-blue-500"
          />
          <div class="flex-1">
            <div class="flex items-center gap-2">
              <span class="text-sm font-medium text-gray-900">
                {$t.validation?.schedule_manual || 'Manual trigger only'}
              </span>
              <HelpTooltip text={$t.validation?.help_schedule_manual || 'Run this validation task manually from the task detail page. No automatic execution.'} />
            </div>
            <p class="text-xs text-gray-500 mt-0.5">
              {$t.validation?.manual_only || 'Run this validation task on-demand only'}
            </p>
          </div>
        </label>

        <!-- Scheduled: day toggles + time window -->
        <div class="relative">
          <label class="flex items-start gap-3 p-4 border rounded-lg cursor-pointer transition-colors {scheduleType === 'scheduled' ? 'border-blue-300 bg-blue-50' : 'border-gray-200 hover:bg-gray-50'}">
            <input
              type="radio"
              name="schedule"
              value="scheduled"
              checked={scheduleType === 'scheduled'}
              onchange={() => { scheduleType = 'scheduled'; }}
              class="mt-0.5 text-blue-600 focus:ring-blue-500"
            />
            <div class="flex-1 min-w-0">
              <div class="flex items-center gap-2">
                <span class="text-sm font-medium text-gray-900">
                  {$t.validation?.schedule_scheduled || 'Scheduled'}
                </span>
                <HelpTooltip text={$t.validation?.help_schedule_scheduled || 'The task runs automatically on the selected days. It executes once within the configured time window. Scheduler must be running on the server.'} />
              </div>
              <p class="text-xs text-gray-500 mt-0.5">
                {$t.validation?.scheduled_desc || 'Run automatically on selected days at specified time'}
              </p>
            </div>
          </label>

          {#if scheduleType === 'scheduled'}
            <div class="mt-3 ml-8 space-y-4">
              <!-- Day-of-week toggles -->
              <div>
                <div class="flex items-center gap-1.5 mb-2">
                  <label class="block text-xs font-medium text-gray-600">
                    {$t.validation?.schedule_days_label || 'Days of week'}
                  </label>
                  <HelpTooltip text={$t.validation?.help_schedule_days || 'Select which days the validation task should run. Hold any combination of days.'} />
                </div>
                <div class="flex flex-wrap gap-1.5">
                  {#each dayNames as name, day (day)}
                    <button
                      onclick={() => toggleDay(day)}
                      class="px-3 py-1.5 text-xs font-medium rounded-lg border transition-colors focus:outline-none focus:ring-2 focus:ring-blue-400"
                      class:bg-blue-600={scheduleDays.includes(day)}
                      class:text-white={scheduleDays.includes(day)}
                      class:border-blue-600={scheduleDays.includes(day)}
                      class:bg-white={!scheduleDays.includes(day)}
                      class:text-gray-700={!scheduleDays.includes(day)}
                      class:border-gray-300={!scheduleDays.includes(day)}
                      class:hover:bg-gray-50={!scheduleDays.includes(day)}
                      aria-pressed={scheduleDays.includes(day)}
                    >
                      {name}
                    </button>
                  {/each}
                </div>
                {#if stepErrors.scheduleDays}
                  <p class="mt-1 text-xs text-red-500">{stepErrors.scheduleDays}</p>
                {/if}
              </div>

              <!-- Quick selection helpers -->
              <div class="flex gap-2">
                <button
                  onclick={() => { scheduleDays = [0,1,2,3,4,5,6]; }}
                  class="text-xs text-blue-600 hover:text-blue-800 underline"
                >
                  {$t.validation?.every_day || 'Every day'}
                </button>
                <button
                  onclick={() => { scheduleDays = [1,2,3,4,5]; }}
                  class="text-xs text-blue-600 hover:text-blue-800 underline"
                >
                  {$t.validation?.weekdays || 'Weekdays'}
                </button>
                <button
                  onclick={() => { scheduleDays = []; }}
                  class="text-xs text-gray-500 hover:text-gray-700 underline"
                >
                  {$t.validation?.clear || 'Clear'}
                </button>
              </div>

              <!-- Time window -->
              <div>
                <div class="flex items-center gap-1.5 mb-2">
                  <span class="block text-xs font-medium text-gray-600">
                    {$t.validation?.time_window || 'Time window'}
                  </span>
                  <HelpTooltip text={$t.validation?.help_schedule_window || 'The task runs once within this window. Set the earliest possible start time and the deadline. The actual execution time depends on scheduler capacity.'} />
                </div>
                <div class="grid grid-cols-2 gap-4">
                  <div>
                    <label for="schedule-start" class="block text-xs font-medium text-gray-600 mb-1">
                      {$t.validation?.window_start || 'Start time'}
                    </label>
                    <input
                      id="schedule-start"
                      type="time"
                      bind:value={scheduleStartTime}
                      class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none"
                    />
                  </div>
                  <div>
                    <label for="schedule-end" class="block text-xs font-medium text-gray-600 mb-1">
                      {$t.validation?.window_end || 'End time'}
                    </label>
                    <input
                      id="schedule-end"
                      type="time"
                      bind:value={scheduleEndTime}
                      class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none"
                    />
                  </div>
                </div>
              </div>

              <!-- Window duration summary -->
              {#if scheduleStartTime && scheduleEndTime && scheduleDays.length > 0}
                <div class="bg-gray-50 rounded-lg p-3 space-y-1.5">
                  <p class="text-xs font-medium text-gray-600">{$t.validation?.schedule_summary || 'Schedule summary'}</p>
                  <div class="flex flex-wrap gap-1">
                    {#each scheduleDays as day}
                      <span class="inline-flex items-center px-2 py-0.5 bg-blue-50 text-blue-700 rounded-full text-xs font-medium">
                        {dayNames[day]}
                      </span>
                    {/each}
                  </div>
                  <p class="text-xs text-gray-500">
                    {$t.validation?.window || 'Window'}: {scheduleStartTime} – {scheduleEndTime}
                    {#if scheduleWindowLabel}
                      <span class="ml-1 text-gray-400">({scheduleWindowLabel})</span>
                    {/if}
                  </p>
                </div>
              {/if}
            </div>
          {/if}
        </div>
      </div>

    <!-- ────── Step 5: Review ────── -->
    {:else if currentStep === 5}
      <div class="p-6 space-y-6">
        <h2 class="text-lg font-semibold text-gray-900">{$t.validation?.review_title || 'Review & Create'}</h2>

        <div class="space-y-4 divide-y divide-gray-100">
          <!-- Name & Description -->
          <div class="pb-4">
            <h3 class="text-xs font-medium text-gray-500 uppercase tracking-wider mb-1">{$t.validation?.review_name || 'Name'}</h3>
            <p class="text-sm text-gray-900">{taskName || '—'}</p>
            {#if taskDescription}
              <p class="text-sm text-gray-500 mt-1">{taskDescription}</p>
            {:else}
              <p class="text-xs text-gray-400 italic">{$t.validation?.no_description || 'No description'}</p>
            {/if}
          </div>

          <!-- Environment -->
          <div class="py-4">
            <h3 class="text-xs font-medium text-gray-500 uppercase tracking-wider mb-1">{$t.validation?.review_environment || 'Environment'}</h3>
            <p class="text-sm text-gray-900">{selectedEnvId ? getEnvName(selectedEnvId) : '—'}</p>
          </div>

          <!-- Sources -->
          <div class="py-4">
            <h3 class="text-xs font-medium text-gray-500 uppercase tracking-wider mb-1">{$t.validation?.review_sources || 'Sources'}</h3>
            {#if totalSourceCount > 0}
              <p class="text-sm text-gray-900 mb-2">
                {($t.validation?.source_count || '{n} source(s) configured').replace('{n}', String(totalSourceCount))}
              </p>
              {#if selectedDashboardIds.length > 0}
                <div class="flex flex-wrap gap-1">
                  {#each selectedDashboardIds.slice(0, 10) as id (id)}
                    {@const name = dashboardOptions.find((d) => d.id === id)?.name || id}
                    <span class="inline-flex items-center px-2 py-0.5 bg-blue-50 text-blue-700 rounded-full text-xs font-medium">{name}</span>
                  {/each}
                  {#if selectedDashboardIds.length > 10}
                    <span class="text-xs text-gray-400">+{selectedDashboardIds.length - 10} more</span>
                  {/if}
                </div>
              {/if}
              {#if parsedSources.length > 0}
                <div class="mt-2 space-y-1">
                  {#each parsedSources as source (source.url)}
                    <p class="text-xs text-gray-500">• {source.title}</p>
                  {/each}
                </div>
              {/if}
            {:else}
              <p class="text-sm text-gray-400 italic">{$t.validation?.no_sources || 'No sources configured'}</p>
            {/if}
          </div>

          <!-- Analysis Path & Provider -->
          <div class="py-4">
            <h3 class="text-xs font-medium text-gray-500 uppercase tracking-wider mb-1">{$t.validation?.review_path || 'Analysis Path'}</h3>
            <p class="text-sm text-gray-900">
              {screenshotEnabled
                ? ($t.validation?.screenshot_path_a || 'Path A (screenshot)')
                : ($t.validation?.screenshot_path_b || 'Path B (text-only)')}
            </p>
            <h3 class="text-xs font-medium text-gray-500 uppercase tracking-wider mt-2 mb-1">{$t.validation?.review_provider || 'LLM Provider'}</h3>
            <p class="text-sm text-gray-900">{selectedProviderId ? getProviderName(selectedProviderId) : '—'}</p>
          </div>

          <!-- Options -->
          <div class="py-4">
            <h3 class="text-xs font-medium text-gray-500 uppercase tracking-wider mb-1">{$t.validation?.review_logs || 'Execution Logs'}</h3>
            <p class="text-sm text-gray-900">{logsEnabled ? ($t.validation?.enabled || 'Enabled') : ($t.validation?.disabled || 'Disabled')}</p>
            {#if !screenshotEnabled}
              <h3 class="text-xs font-medium text-gray-500 uppercase tracking-wider mt-2 mb-1">{$t.validation?.review_chart_data || 'Chart Data'}</h3>
              <p class="text-sm text-gray-900">{executeChartData ? ($t.validation?.enabled || 'Enabled') : ($t.validation?.disabled || 'Disabled')}</p>
              <h3 class="text-xs font-medium text-gray-500 uppercase tracking-wider mt-2 mb-1">{$t.validation?.review_batch_size || 'Batch Size'}</h3>
              <p class="text-sm text-gray-900">{llmBatchSize}</p>
            {/if}
            {#if promptTemplate}
              <h3 class="text-xs font-medium text-gray-500 uppercase tracking-wider mt-2 mb-1">{$t.validation?.review_prompt || 'Prompt Template'}</h3>
              <pre class="text-xs text-gray-600 bg-gray-50 p-2 rounded border border-gray-200 max-h-24 overflow-y-auto whitespace-pre-wrap">{promptTemplate}</pre>
            {/if}
          </div>

          <!-- Schedule -->
          <div class="pt-4">
            <h3 class="text-xs font-medium text-gray-500 uppercase tracking-wider mb-1">{$t.validation?.review_schedule || 'Schedule'}</h3>
            {#if scheduleType === 'manual'}
              <p class="text-sm text-gray-900">{$t.validation?.manual_trigger || 'Manual trigger'}</p>
            {:else}
              <p class="text-sm text-gray-900">{$t.validation?.scheduled || 'Scheduled'}</p>
              {#if scheduleDays.length > 0}
                <div class="flex flex-wrap gap-1 mt-1.5">
                  {#each scheduleDays as day}
                    <span class="inline-flex items-center px-2 py-0.5 bg-blue-50 text-blue-700 rounded-full text-xs font-medium">{dayNames[day]}</span>
                  {/each}
                </div>
              {/if}
              <p class="text-xs text-gray-500 mt-1">
                {scheduleStartTime} – {scheduleEndTime}
                {#if scheduleWindowLabel}
                  <span class="ml-1 text-gray-400">({scheduleWindowLabel})</span>
                {/if}
              </p>
            {/if}
          </div>
        </div>
      </div>
    {/if}

    <!-- ────── Navigation Buttons ────── -->
    <div class="flex items-center justify-between px-6 py-4 bg-gray-50 border-t border-gray-200 rounded-b-lg">
      <div>
        {#if currentStep > 1}
          <button
            onclick={prevStep}
            class="inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
          >
            <svg class="w-4 h-4 mr-1.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
            </svg>
            {$t.validation?.back || 'Back'}
          </button>
        {:else if onCancel}
          <button
            onclick={onCancel}
            class="inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
          >
            {$t.validation?.cancel || 'Cancel'}
          </button>
        {/if}
      </div>

      <div class="flex items-center gap-2">
        <span class="text-xs text-gray-400">
          {($t.validation?.step_x_of_y || 'Step {x} of {y}')
            .replace('{x}', String(currentStep))
            .replace('{y}', String(totalSteps))}
        </span>

        {#if currentStep < totalSteps}
          <button
            onclick={nextStep}
            disabled={!canAdvance}
            class="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
          >
            {$t.common?.next || 'Next'}
            <svg class="w-4 h-4 ml-1.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
            </svg>
          </button>
        {:else}
          <button
            onclick={handleSubmit}
            disabled={isSubmitting}
            class="inline-flex items-center px-5 py-2 text-sm font-medium text-white bg-green-600 rounded-lg hover:bg-green-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
          >
            {#if isSubmitting}
              <svg class="animate-spin -ml-1 mr-2 h-4 w-4 text-white" 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>
              {$t.validation?.saving || 'Saving...'}
            {:else}
              {initialData
                ? ($t.validation?.save_changes || 'Save Changes')
                : ($t.validation?.create_task || 'Create Task')}
            {/if}
          </button>
        {/if}
      </div>
    </div>
  </div>
</div>
<!-- #endregion ValidationTaskForm -->
