// frontend/src/lib/models/Migration.ExecutorModel.svelte.ts
// #region Migration.ExecutorModel [C:4] [TYPE Model] [SEMANTICS migration,execution,dry-run,password]
// @ingroup Migration
// @BRIEF Migration execution sub-model — dry-run, execute, resume, password prompt handling.
// @RELATION DEPENDS_ON -> [Migration.Model]
// @INVARIANT Dry-run must complete before migration execution (see parent.canExecute).
// @INVARIANT Password prompt triggers only for AWAITING_INPUT tasks with type "database_password".
// @STATE dryRunResult — Dry-run analysis result.
// @STATE dryRunLoading — True while dry-run API call is in flight.
// @STATE selectedDashboardIds — Set of selected dashboard IDs for migration.
// @STATE showPasswordPrompt — Whether the database password prompt is visible.
// @ACTION calculateDryRun() — Runs dry-run analysis, advances to step 3 on success.
// @ACTION executeMigration(endpoint?) — Submits migration execution task.
// @ACTION resumeMigration(passwords) — Resumes a paused migration with database passwords.
// @ACTION checkPasswordPrompt() — Watches the active task for password-request signals.

import { api } from "$lib/api.js";
import { selectedTask } from "$lib/stores.svelte.js";
import { resumeTask } from "../../services/taskService.js";
import { t } from "$lib/i18n/index.svelte.js";
import type { MigrationModel } from "./MigrationModel.svelte.ts";

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

export interface DryRunResult {
  summary?: Record<string, unknown>;
  risk?: { score: number; level: string; items: unknown[] };
  selected_dashboard_titles?: string[];
  [key: string]: unknown;
}

export interface DashboardSelection {
  selected_ids: string[];
  source_env_id: string;
  target_env_id: string;
  replace_db_config: boolean;
  fix_cross_filters: boolean;
}

export class MigrationExecutor {
  parent: MigrationModel;

  // ── Atoms (reactive state) ──────────────────────────────────

  selectedDashboardIds: string[] = $state([]);
  dryRunResult: DryRunResult | null = $state(null);
  dryRunLoading: boolean = $state(false);
  showPasswordPrompt: boolean = $state(false);
  passwordPromptDatabases: string[] = $state([]);
  passwordPromptErrorMessage: string = $state("");

  constructor(parent: MigrationModel) {
    this.parent = parent;
  }

  // ── Derived ─────────────────────────────────────────────────

  /** Alias for dryRunLoading — used externally for UI gating. */
  get isCalculating(): boolean {
    return this.dryRunLoading;
  }

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

  /** Run dry-run analysis. Sets dryRunResult and advances to step 3 on success. */
  async calculateDryRun(): Promise<void> {
    if (!this.parent._validatePreconditions()) return;
    this.parent.error = "";
    this.dryRunLoading = true;
    try {
      this.dryRunResult = await api.postApi("/migration/dry-run", this.parent._buildSelection());
      this.parent.wizard.currentStep = 3;
    } catch (e: unknown) {
      this.parent.error = e instanceof Error ? e.message : "Dry-run failed";
      this.dryRunResult = null;
    } finally {
      this.dryRunLoading = false;
    }
  }

  /** Execute migration. Submits task and activates task runner view. */
  async executeMigration(endpoint: string = "/migration/execute"): Promise<void> {
    if (!this.parent._validatePreconditions()) return;
    this.parent.error = "";
    try {
      this.dryRunResult = null;
      const result = await api.postApi(endpoint, this.parent._buildSelection());
      await new Promise((r) => setTimeout(r, 500));
      try {
        const task = await api.getTask(result.task_id);
        this.parent.selectedTaskStore.set(task);
      } catch {
        this.parent.selectedTaskStore.set({
          id: result.task_id,
          plugin_id: "superset-migration",
          status: "RUNNING",
          logs: [],
          params: {},
        });
      }
    } catch (e: unknown) {
      this.parent.error = e instanceof Error ? e.message : "Migration execution failed";
    }
  }

  /** Resume a paused migration task with database passwords. */
  async resumeMigration(passwords: Record<string, string>): Promise<void> {
    const task = this.parent.selectedTaskStore.current;
    if (!task) return;
    try {
      await resumeTask(task.id, passwords);
      this.showPasswordPrompt = false;
    } catch (e: unknown) {
      this.passwordPromptErrorMessage = e instanceof Error ? e.message : (t.migration?.resume_failed || "Resume failed");
    }
  }

  /** Watch for password-prompt signals from active task. Call in an $effect. */
  checkPasswordPrompt(): void {
    const activeTask = this.parent.selectedTaskStore.current;
    if (
      !activeTask ||
      activeTask.status !== "AWAITING_INPUT" ||
      !activeTask.input_request
    ) {
      return;
    }
    const req = activeTask.input_request;
    if (req.type === "database_password") {
      this.passwordPromptDatabases = req.databases || [];
      this.passwordPromptErrorMessage = req.error_message || "";
      this.showPasswordPrompt = true;
    }
  }
}
// #endregion Migration.ExecutorModel
