// #region ValidationTaskFormTests [C:3] [TYPE Module] [SEMANTICS test, validation, form, v2, model-invariants]
// @BRIEF Model invariant tests for ValidationTaskForm — data mapping, provider filter, schedule config, dead code.
// @RELATION BINDS_TO -> [ValidationTaskForm]
// @TEST_EDGE: dashboard_options_mapping -> d.title used (not d.dashboard_title)
// @TEST_EDGE: provider_filter_fields -> p.is_multimodal / p.is_active used
// @TEST_EDGE: form_data_provider_id -> provider_id (not llm_provider_id)
// @TEST_EDGE: schedule_fields -> schedule_days, window_start, window_end in output
// @TEST_EDGE: cron_preset_dropdown -> Preset values match expected cron expressions
// @TEST_EDGE: no_dead_code -> No nextRunsLoading, no llm_provider_id in form data

import { describe, it, expect } from 'vitest';
import fs from 'node:fs';
import path from 'node:path';

const FORM_PATH = path.resolve(
  process.cwd(),
  'src/lib/components/llm/ValidationTaskForm.svelte',
);

const API_PATH = path.resolve(
  process.cwd(),
  'src/lib/api.js',
);

const DRAWER_PATH = path.resolve(
  process.cwd(),
  'src/lib/components/layout/TaskDrawer.svelte',
);

// #region readSource:Function [C:1] [TYPE Function]
// @BRIEF Helper to read source file content.
function readSource(filePath) {
  if (!fs.existsSync(filePath)) return null;
  return fs.readFileSync(filePath, 'utf-8');
}
// #endregion readSource:Function


// #region DashboardOptionsMapping [C:2] [TYPE Class] [SEMANTICS test, dashboard, options, mapping]
// @BRIEF Verify dashboardOptions maps d.title correctly (not d.dashboard_title).
describe('ValidationTaskForm — dashboardOptions mapping', () => {
  it('maps dashboard d.title (not d.dashboard_title) in dashboardOptions', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    // dashboardOptions should use d.title
    expect(source).toContain('d.title');
    // Should NOT use d.dashboard_title in the map
    expect(source).not.toMatch(/dashboardOptions.*dashboard_title/s);
  });

  it('dashboardOptions derived uses String(d.id) for id', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    expect(source).toContain('id: String(d.id)');
  });
});
// #endregion DashboardOptionsMapping


// #region ProviderFilterFields [C:2] [TYPE Class] [SEMANTICS test, provider, filter, is-prefix]
// @BRIEF Verify provider filter uses is_multimodal/is_active (not .multimodal/.active).
describe('ValidationTaskForm — provider filter field names', () => {
  it('filters providers using p.is_multimodal and p.is_active', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    expect(source).toContain('p.is_multimodal');
    expect(source).toContain('p.is_active');
  });

  it('does NOT use bare .multimodal or .active without is_ prefix', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    // Check that filteredProviders doesn't use p.multimodal (without is_)
    const filteredProvidersMatch = source.match(/filteredProviders.*?;/s);
    if (filteredProvidersMatch) {
      expect(filteredProvidersMatch[0]).not.toMatch(/p\.multimodal\b/);
      expect(filteredProvidersMatch[0]).not.toMatch(/p\.active\b/);
    }
  });

  it('provider type annotation includes is_multimodal and is_active', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    expect(source).toContain('is_multimodal: boolean');
    expect(source).toContain('is_active: boolean');
  });
});
// #endregion ProviderFilterFields


// #region FormDataProviderId [C:2] [TYPE Class] [SEMANTICS test, form-data, provider-id]
// @BRIEF Verify form output uses provider_id (not llm_provider_id).
describe('ValidationTaskForm — form data provider_id', () => {
  it('sends provider_id in form output (not llm_provider_id)', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    // formData object should contain provider_id
    expect(source).toContain('provider_id: selectedProviderId');
  });

  it('does NOT send llm_provider_id in form data', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    // Check the formData construction section
    const formDataMatch = source.match(/const formData = \{[\s\S]*?\};/);
    if (formDataMatch) {
      expect(formDataMatch[0]).not.toContain('llm_provider_id');
    }
  });
});
// #endregion FormDataProviderId


// #region ScheduleFields [C:2] [TYPE Class] [SEMANTICS test, schedule, fields, cron]
// @BRIEF Verify form output has schedule_days, window_start, window_end.
describe('ValidationTaskForm — schedule fields', () => {
  it('includes schedule_days in form output', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    expect(source).toContain('schedule_days:');
  });

  it('includes window_start in form output', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    expect(source).toContain('window_start:');
  });

  it('includes window_end in form output', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    expect(source).toContain('window_end:');
  });

  it('schedule_days comes from scheduleDays state (v2 schedule API)', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    expect(source).toContain('schedule_days:');
  });

  it('window_start comes from scheduleStartTime state (v2 schedule API)', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    expect(source).toContain('window_start:');
  });
});
// #endregion ScheduleFields


// #region ScheduleTypeDropdown [C:2] [TYPE Class] [SEMANTICS test, schedule, type, dropdown]
// @BRIEF Verify schedule type dropdown values are correct (v2 schedule API).
describe('ValidationTaskForm — schedule type dropdown', () => {
  it('has manual and scheduled type options', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    expect(source).toContain("'manual'");
    expect(source).toContain("'scheduled'");
  });

  it('scheduleType defaults to manual', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    expect(source).toContain("= $state('manual')");
  });

  it('has scheduleDays state for day selection', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    expect(source).toContain('scheduleDays');
  });

  it('has scheduleStartTime and scheduleEndTime for time window', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    expect(source).toContain('scheduleStartTime');
    expect(source).toContain('scheduleEndTime');
  });
});
// #endregion ScheduleTypeDropdown


// #region DeadCodeCheck [C:2] [TYPE Class] [SEMANTICS test, dead-code, no-next-runs]
// @BRIEF Verify no dead code: nextRunsLoading, nextRuns state removed.
describe('ValidationTaskForm — dead code check', () => {
  it('does NOT contain nextRunsLoading state', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    expect(source).not.toContain('nextRunsLoading');
  });

  it('does NOT contain nextRuns state (uses scheduleDays instead)', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    // Should not have nextRuns as a state variable
    expect(source).not.toMatch(/let nextRuns\b/);
    // Should use scheduleDays instead
    expect(source).toContain('scheduleDays');
  });

  it('does NOT make API call to /validation-tasks/next-runs', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    expect(source).not.toContain('next-runs');
  });
});
// #endregion DeadCodeCheck


// #region ApiDeleteTaskDefaults [C:2] [TYPE Class] [SEMANTICS test, api, delete, runs]
// @BRIEF Verify deleteTask API defaults deleteRuns=true.
describe('Validation API — deleteTask defaults', () => {
  it('deleteTask defaults deleteRuns to true', () => {
    const source = readSource(API_PATH);
    if (!source) return;

    expect(source).toContain('deleteRuns = true');
  });

  it('deleteTask sends delete_runs=true query param', () => {
    const source = readSource(API_PATH);
    if (!source) return;

    expect(source).toContain('delete_runs=true');
  });
});
// #endregion ApiDeleteTaskDefaults


// #region WebSocketCloseBehavior [C:2] [TYPE Class] [SEMANTICS test, websocket, close, code-1000]
// @BRIEF Verify TaskDrawer WebSocket checks close code 1000.
describe('TaskDrawer — WebSocket close behavior', () => {
  it('checks close code 1000 before reconnecting', () => {
    const source = readSource(DRAWER_PATH);
    if (!source) return;

    expect(source).toContain('1000');
  });

  it('has onclose handler', () => {
    const source = readSource(DRAWER_PATH);
    if (!source) return;

    expect(source).toMatch(/onclose|\.close/);
  });
});
// #endregion WebSocketCloseBehavior


// #region FormStepStructure [C:2] [TYPE Class] [SEMANTICS test, form, steps]
// @BRIEF Verify form has 5 steps with correct labels.
describe('ValidationTaskForm — step structure', () => {
  it('has 5 steps', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    expect(source).toContain('const totalSteps = 5');
  });

  it('step labels include name, sources, options, schedule, review', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    expect(source).toContain('step_name');
    expect(source).toContain('step_sources');
    expect(source).toContain('step_options');
    expect(source).toContain('step_schedule');
    expect(source).toContain('step_review');
  });
});
// #endregion FormStepStructure


// #region PathAToggle [C:2] [TYPE Class] [SEMANTICS test, form, path-a, toggle]
// @BRIEF Verify screenshot toggle switches between Path A and Path B.
describe('ValidationTaskForm — Path A/B toggle', () => {
  it('has screenshotEnabled state', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    expect(source).toContain('let screenshotEnabled');
  });

  it('handleScreenshotToggle function exists', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    expect(source).toContain('function handleScreenshotToggle');
  });

  it('provider validation checks is_multimodal on toggle', () => {
    const source = readSource(FORM_PATH);
    if (!source) return;

    expect(source).toContain('is_multimodal');
  });
});
// #endregion PathAToggle
