// #region ValidationTasksListModel [C:4] [TYPE Model] [SEMANTICS validation,tasks,list,pagination,crud,model]
// @ingroup Models
// @BRIEF Screen model for validation tasks list — manages paginated list, search, inline actions (run/delete/toggle), and navigation.
// @RATIONALE Svelte 5 $state/$derived model-first pattern. Uses map-based array update instead of self-assignment hack for reactivity.
// @INVARIANT Search resets pagination to page 1.
// @INVARIANT Delete removes task from list and decrements total atomically.
// @INVARIANT isMounted prevents state mutation after component unmount.
// @STATE idle      — Initial state, no data loaded.
// @STATE loading   — API call in progress.
// @STATE loaded    — Data fetched, list populated.
// @STATE empty     — Query returned zero results.
// @STATE error     — API call failed.
// @ACTION loadTasks()        — Fetches paginated task list.
// @ACTION handleSearchInput() — Debounced search with pagination reset.
// @ACTION handleRunNow(id)   — Triggers validation run.
// @ACTION handleDelete(id)   — Deletes task with atomic list removal.
// @ACTION handleToggleStatus(task) — Toggles is_active.
// @ACTION goToPage(p)        — Navigates to page.
// @RELATION DEPENDS_ON -> [ApiModule]
// @RELATION CALLS -> [CotLogger]

import { goto } from '$app/navigation';
import { ROUTES } from '$lib/routes';
import { api } from '$lib/api.js';
import { log } from '$lib/cot-logger';
import { addToast } from '$lib/toasts.svelte.js';
import { getT } from '$lib/i18n/index.svelte.js';

// ── Types ───────────────────────────────────────────────────────

interface ValidationTask {
  id: string;
  name?: string;
  plugin_id?: string;
  is_active?: boolean;
  schedule?: string;
  [key: string]: unknown;
}

interface TaskListData {
  tasks?: ValidationTask[];
  total?: number;
  page?: number;
  page_size?: number;
  error?: string | null;
}

export class ValidationTasksListModel {
  // ── Data from load function ──────────────────────────────────
  tasks: ValidationTask[] = $state([]);
  total: number = $state(0);
  currentPage: number = $state(1);
  pageSize: number = $state(20);
  error: string | null = $state(null);
  isLoading: boolean = $state(false);
  searchQuery: string = $state('');

  // ── UI state ──────────────────────────────────────────────────
  runningTasks: Record<string, boolean> = $state({});
  deleteConfirmId: string | null = $state(null);
  isMounted: boolean = $state(true);

  // ── Internal ──────────────────────────────────────────────────
  private _searchTimeout: ReturnType<typeof setTimeout> | undefined;

  // ── Derived ───────────────────────────────────────────────────
  totalPages = $derived(Math.max(1, Math.ceil(this.total / this.pageSize)));

  // ── Init from load data ──────────────────────────────────────
  initFromLoad(data: TaskListData): void {
    this.tasks = data.tasks ?? [];
    this.total = data.total ?? 0;
    this.currentPage = data.page ?? 1;
    this.pageSize = data.page_size ?? 20;
    this.error = data.error ?? null;
  }

  // ── Actions ───────────────────────────────────────────────────

  async loadTasks(): Promise<void> {
    this.isLoading = true;
    this.error = null;
    log('ValidationTasksListModel', 'REASON', 'Loading validation tasks', { page: this.currentPage, pageSize: this.pageSize, search: this.searchQuery || undefined });
    try {
      const result = await api.getValidationTasks({ page: this.currentPage, page_size: this.pageSize, search: this.searchQuery || undefined });
      if (!this.isMounted) return;
      const items = (result as { tasks?: ValidationTask[]; results?: ValidationTask[] })?.tasks ?? (result as { tasks?: ValidationTask[]; results?: ValidationTask[] })?.results ?? [];
      this.tasks = items;
      this.total = (result as { total?: number })?.total ?? 0;
      log('ValidationTasksListModel', 'REFLECT', 'Tasks loaded', { count: items.length, total: this.total });
    } catch (e: unknown) {
      if (!this.isMounted) return;
      this.error = e instanceof Error ? e.message : 'Failed to load tasks';
      log('ValidationTasksListModel', 'EXPLORE', 'Failed to load tasks', {}, String(this.error));
    } finally {
      if (this.isMounted) this.isLoading = false;
    }
  }

  handleSearchInput(value: string): void {
    this.searchQuery = value;
    if (this._searchTimeout) clearTimeout(this._searchTimeout);
    this._searchTimeout = setTimeout(() => {
      this.currentPage = 1;
      this.loadTasks();
    }, 300);
  }

  goToPage(p: number): void {
    if (p < 1 || p > this.totalPages) return;
    this.currentPage = p;
    this.loadTasks();
  }

  // ── Navigation ────────────────────────────────────────────────

  navToNew(): void { goto(ROUTES.validationTasks.new(), { invalidateAll: false }); }
  navToDetail(id: string): void { goto(ROUTES.validationTasks.detail(id), { invalidateAll: false }); }
  navToEdit(id: string): void { goto(ROUTES.validationTasks.edit(id), { invalidateAll: false }); }

  // ── CRUD Actions ─────────────────────────────────────────────

  async handleRunNow(id: string): Promise<void> {
    this.runningTasks = { ...this.runningTasks, [id]: true };
    log('ValidationTasksListModel', 'REASON', 'Triggering run', { taskId: id });
    try {
      await api.triggerValidationRun(id);
      if (!this.isMounted) return;
      addToast(getT()?.validation?.run_started || 'Validation task started', 'success');
      log('ValidationTasksListModel', 'REFLECT', 'Run triggered', { taskId: id });
    } catch (e: unknown) {
      if (!this.isMounted) return;
      addToast(e instanceof Error ? e.message : 'Failed to trigger run', 'error');
      log('ValidationTasksListModel', 'EXPLORE', 'Failed to trigger run', { taskId: id }, String(e));
    } finally {
      if (this.isMounted) this.runningTasks = { ...this.runningTasks, [id]: false };
    }
  }

  async handleDelete(id: string): Promise<void> {
    log('ValidationTasksListModel', 'REASON', 'Deleting task', { taskId: id });
    try {
      await api.deleteValidationTask(id);
      if (!this.isMounted) return;
      addToast(getT()?.validation?.delete_success || 'Task deleted', 'success');
      this.deleteConfirmId = null;
      this.tasks = this.tasks.filter(t => t.id !== id);
      this.total = Math.max(0, this.total - 1);
      log('ValidationTasksListModel', 'REFLECT', 'Task deleted', { taskId: id });
    } catch (e: unknown) {
      if (!this.isMounted) return;
      addToast(e instanceof Error ? e.message : 'Failed to delete', 'error');
      this.deleteConfirmId = null;
      log('ValidationTasksListModel', 'EXPLORE', 'Failed to delete task', { taskId: id }, String(e));
    }
  }

  async handleToggleStatus(task: ValidationTask): Promise<void> {
    const newActive = !(task.is_active !== false);
    log('ValidationTasksListModel', 'REASON', 'Toggling status', { taskId: task.id, to: newActive });
    try {
      await api.toggleValidationTaskStatus(task.id, newActive);
      if (!this.isMounted) return;
      task.is_active = newActive;
      this.tasks = this.tasks.map(t => t.id === task.id ? { ...t, is_active: newActive } : t);
      log('ValidationTasksListModel', 'REFLECT', 'Status toggled', { taskId: task.id });
    } catch (e: unknown) {
      if (!this.isMounted) return;
      addToast(e instanceof Error ? e.message : 'Failed to update status', 'error');
      log('ValidationTasksListModel', 'EXPLORE', 'Failed to toggle status', { taskId: task.id }, String(e));
    }
  }

  destroy(): void { this.isMounted = false; }
}
// #endregion ValidationTasksListModel
