<!-- [DEF:SettingsPage:Page] -->
<script>
  /**
   * @TIER: CRITICAL
   * @PURPOSE: Consolidated Settings Page - All settings in one place with tabbed navigation
   * @LAYER: UI
   * @RELATION: BINDS_TO -> sidebarStore
   * @INVARIANT: Always shows tabbed interface with all settings categories
   *
   * @UX_STATE: Loading -> Shows skeleton loader
   * @UX_STATE: Loaded -> Shows tabbed settings interface
   * @UX_STATE: Error -> Shows error banner with retry button
   * @UX_FEEDBACK: Toast notifications on save success/failure
   * @UX_RECOVERY: Refresh button reloads settings data
   */

  import { onMount } from "svelte";
  import { t } from "$lib/i18n";
  import { api } from "$lib/api.js";
  import { addToast } from "$lib/toasts";
  import ProviderConfig from "../../components/llm/ProviderConfig.svelte";

  const DEFAULT_LLM_PROMPTS = {
    dashboard_validation_prompt:
      'Analyze the attached dashboard screenshot and the following execution logs for health and visual issues.\\n\\nLogs:\\n{logs}\\n\\nProvide the analysis in JSON format with the following structure:\\n{\\n    \\"status\\": \\"PASS\\" | \\"WARN\\" | \\"FAIL\\",\\n    \\"summary\\": \\"Short summary of findings\\",\\n    \\"issues\\": [\\n        {\\n            \\"severity\\": \\"WARN\\" | \\"FAIL\\",\\n            \\"message\\": \\"Description of the issue\\",\\n            \\"location\\": \\"Optional location info (e.g. chart name)\\"\\n        }\\n    ]\\n}',
    documentation_prompt:
      'Generate professional documentation for the following dataset and its columns.\\nDataset: {dataset_name}\\nColumns: {columns_json}\\n\\nProvide the documentation in JSON format:\\n{\\n    \\"dataset_description\\": \\"General description of the dataset\\",\\n    \\"column_descriptions\\": [\\n        {\\n            \\"name\\": \\"column_name\\",\\n            \\"description\\": \\"Generated description\\"\\n        }\\n    ]\\n}',
    git_commit_prompt:
      "Generate a concise and professional git commit message based on the following diff and recent history.\\nUse Conventional Commits format (e.g., feat: ..., fix: ..., docs: ...).\\n\\nRecent History:\\n{history}\\n\\nDiff:\\n{diff}\\n\\nCommit Message:",
  };
  const DEFAULT_LLM_PROVIDER_BINDINGS = {
    dashboard_validation: "",
    documentation: "",
    git_commit: "",
  };

  // State
  const SETTINGS_TABS = [
    "environments",
    "logging",
    "connections",
    "llm",
    "migration",
    "storage",
  ];
  let activeTab = "environments";
  let settings = null;
  let isLoading = true;
  let error = null;

  // Environment editing state
  let editingEnvId = null;
  let isAddingEnv = false;
  let newEnv = {
    id: "",
    name: "",
    url: "",
    username: "",
    password: "",
    is_default: false,
    backup_schedule: {
      enabled: false,
      cron_expression: "0 0 * * *",
    },
  };

  function normalizeTab(value) {
    const normalized = String(value || "").trim().toLowerCase();
    const aliases = {
      environment: "environments",
      env: "environments",
      "migration-sync": "migration",
      storages: "storage",
    };
    const resolved = aliases[normalized] || normalized;
    return SETTINGS_TABS.includes(resolved) ? resolved : "environments";
  }

  function readTabFromUrl() {
    if (typeof window === "undefined") return "environments";
    const params = new URLSearchParams(window.location.search);
    const fromQuery = params.get("tab");
    if (fromQuery) return normalizeTab(fromQuery);
    const fromHash = window.location.hash?.replace(/^#/, "");
    if (fromHash) return normalizeTab(fromHash);
    return "environments";
  }

  function writeTabToUrl(tab) {
    if (typeof window === "undefined") return;
    const url = new URL(window.location.href);
    url.searchParams.set("tab", tab);
    url.hash = tab;
    window.history.replaceState({}, "", url.toString());
  }

  // Load settings on mount
  onMount(async () => {
    activeTab = readTabFromUrl();
    const syncTabFromUrl = () => {
      activeTab = readTabFromUrl();
    };
    window.addEventListener("popstate", syncTabFromUrl);
    window.addEventListener("hashchange", syncTabFromUrl);
    await loadSettings();
    await loadMigrationSettings();
    return () => {
      window.removeEventListener("popstate", syncTabFromUrl);
      window.removeEventListener("hashchange", syncTabFromUrl);
    };
  });

  // Load consolidated settings from API
  async function loadSettings() {
    isLoading = true;
    error = null;
    try {
      const response = await api.getConsolidatedSettings();
      response.llm = normalizeLlmSettings(response.llm);
      settings = response;
    } catch (err) {
      error = err.message || $t.settings?.load_failed ;
      console.error("[SettingsPage][Coherence:Failed]", err);
    } finally {
      isLoading = false;
    }
  }

  function normalizeLlmSettings(llm) {
    const normalized = {
      providers: [],
      default_provider: "",
      prompts: { ...DEFAULT_LLM_PROMPTS },
      provider_bindings: { ...DEFAULT_LLM_PROVIDER_BINDINGS },
      assistant_planner_provider: "",
      assistant_planner_model: "",
      ...(llm || {}),
    };
    normalized.prompts = {
      ...DEFAULT_LLM_PROMPTS,
      ...(llm?.prompts || {}),
    };
    normalized.provider_bindings = {
      ...DEFAULT_LLM_PROVIDER_BINDINGS,
      ...(llm?.provider_bindings || {}),
    };
    normalized.assistant_planner_provider =
      llm?.assistant_planner_provider || "";
    normalized.assistant_planner_model = llm?.assistant_planner_model || "";
    return normalized;
  }

  function isMultimodalModel(modelName) {
    const token = (modelName || "").toLowerCase();
    if (!token) return false;
    return (
      token.includes("gpt-4o") ||
      token.includes("gpt-4.1") ||
      token.includes("vision") ||
      token.includes("vl") ||
      token.includes("gemini") ||
      token.includes("claude-3") ||
      token.includes("claude-sonnet-4")
    );
  }

  function getProviderById(providerId) {
    if (!providerId) return null;
    return (
      (settings?.llm_providers || []).find((p) => p.id === providerId) || null
    );
  }

  function isDashboardValidationBindingValid() {
    const providerId = settings?.llm?.provider_bindings?.dashboard_validation;
    if (!providerId) return true;
    const provider = getProviderById(providerId);
    return provider ? isMultimodalModel(provider.default_model) : true;
  }

  // Handle tab change
  function handleTabChange(tab) {
    const normalizedTab = normalizeTab(tab);
    activeTab = normalizedTab;
    writeTabToUrl(activeTab);
    if (normalizedTab === "migration") {
      loadMigrationSettings();
    }
  }

  // Migration Settings State
  let migrationCron = "0 2 * * *";
  let displayMappings = [];
  let mappingsTotal = 0;
  let mappingsPage = 0;
  let mappingsPageSize = 25;
  let mappingsSearch = "";
  let mappingsEnvFilter = "";
  let mappingsTypeFilter = "";
  let isSavingMigration = false;
  let isLoadingMigration = false;
  let isSyncing = false;
  let searchTimeout = null;

  $: mappingsTotalPages = Math.max(
    1,
    Math.ceil(mappingsTotal / mappingsPageSize),
  );

  async function loadMigrationSettings() {
    isLoadingMigration = true;
    try {
      const settingsRes = await api.requestApi("/migration/settings");
      migrationCron = settingsRes.cron;
      await loadMappingsPage();
    } catch (err) {
      console.error("[SettingsPage][Migration] Failed to load:", err);
    } finally {
      isLoadingMigration = false;
    }
  }

  async function loadMappingsPage() {
    try {
      const skip = mappingsPage * mappingsPageSize;
      let url = `/migration/mappings-data?skip=${skip}&limit=${mappingsPageSize}`;
      if (mappingsSearch)
        url += `&search=${encodeURIComponent(mappingsSearch)}`;
      if (mappingsEnvFilter)
        url += `&env_id=${encodeURIComponent(mappingsEnvFilter)}`;
      if (mappingsTypeFilter)
        url += `&resource_type=${encodeURIComponent(mappingsTypeFilter)}`;
      const res = await api.requestApi(url);
      displayMappings = res.items || [];
      mappingsTotal = res.total || 0;
    } catch (err) {
      console.error("[SettingsPage][Migration] Failed to load mappings:", err);
    }
  }

  function onMappingsSearchInput(e) {
    clearTimeout(searchTimeout);
    searchTimeout = setTimeout(() => {
      mappingsPage = 0;
      loadMappingsPage();
    }, 300);
  }

  function onMappingsFilterChange() {
    mappingsPage = 0;
    loadMappingsPage();
  }

  function goToMappingsPage(page) {
    if (page < 0 || page >= mappingsTotalPages) return;
    mappingsPage = page;
    loadMappingsPage();
  }

  async function saveMigrationSettings() {
    isSavingMigration = true;
    try {
      await api.putApi("/migration/settings", { cron: migrationCron });
      addToast(
        $t.settings?.save_success ,
        "success",
      );
    } catch (err) {
      addToast(
        $t.settings?.save_failed ,
        "error",
      );
    } finally {
      isSavingMigration = false;
    }
  }

  async function triggerSyncNow() {
    isSyncing = true;
    try {
      const result = await api.postApi("/migration/sync-now", {});
      addToast(
        `Synced ${result.synced_count} environment(s)${result.failed_count > 0 ? `, ${result.failed_count} failed` : ""}`,
        result.failed_count > 0 ? "warning" : "success",
      );
      await loadMigrationSettings();
    } catch (err) {
      console.error("[SettingsPage][Migration] Sync failed:", err);
      addToast(err.message || $t.settings?.migration_sync_failed , "error");
    } finally {
      isSyncing = false;
    }
  }

  // Handle global settings save (Logging, Storage)
  async function handleSave() {
    console.log("[SettingsPage][Action] Saving settings");
    try {
      settings.llm = normalizeLlmSettings(settings.llm);
      // In a real app we might want to only send the changed section,
      // but updateConsolidatedSettings expects full object or we can use specific endpoints.
      // For now we use the consolidated update.
      await api.updateConsolidatedSettings(settings);
      addToast($t.settings?.save_success , "success");
    } catch (err) {
      console.error("[SettingsPage][Coherence:Failed]", err);
      addToast($t.settings?.save_failed , "error");
    }
  }

  // Handle environment actions
  async function handleTestEnv(id) {
    console.log(`[SettingsPage][Action] Test environment ${id}`);
    addToast($t.settings?.testing_connection , "info");
    try {
      const result = await api.testEnvironmentConnection(id);
      if (result.status === "success") {
        addToast($t.settings?.connection_success , "success");
      } else {
        addToast(
          ($t.settings?.connection_failed ).replace(
            "{error}",
            result.message || $t.common?.unknown ,
          ),
          "error",
        );
      }
    } catch (err) {
      console.error(
        "[SettingsPage][Coherence:Failed] Error testing connection:",
        err,
      );
      addToast($t.settings?.connection_test_failed , "error");
    }
  }

  function editEnv(env) {
    console.log(`[SettingsPage][Action] Edit environment ${env.id}`);
    newEnv = JSON.parse(JSON.stringify(env)); // Deep copy
    // Ensure backup_schedule exists
    if (!newEnv.backup_schedule) {
      newEnv.backup_schedule = { enabled: false, cron_expression: "0 0 * * *" };
    }
    editingEnvId = env.id;
    isAddingEnv = false;
  }

  function resetEnvForm() {
    newEnv = {
      id: "",
      name: "",
      url: "",
      username: "",
      password: "",
      is_default: false,
      backup_schedule: {
        enabled: false,
        cron_expression: "0 0 * * *",
      },
    };
    editingEnvId = null;
  }

  async function handleAddOrUpdateEnv() {
    try {
      console.log(
        `[SettingsPage][Action] ${editingEnvId ? "Updating" : "Adding"} environment.`,
      );

      // Basic validation
      if (!newEnv.id || !newEnv.name || !newEnv.url) {
        addToast(
          $t.settings?.env_required_fields,
          "error",
        );
        return;
      }

      if (editingEnvId) {
        await api.updateEnvironment(editingEnvId, newEnv);
        addToast($t.settings?.env_updated , "success");
      } else {
        await api.addEnvironment(newEnv);
        addToast($t.settings?.env_added , "success");
      }

      resetEnvForm();
      editingEnvId = null;
      isAddingEnv = false;
      await loadSettings();
    } catch (error) {
      console.error(
        "[SettingsPage][Coherence:Failed] Failed to save environment:",
        error,
      );
      addToast(error.message || $t.settings?.env_save_failed , "error");
    }
  }

  async function handleDeleteEnv(id) {
    if (
      confirm(
        $t.settings?.env_delete_confirm,
      )
    ) {
      console.log(`[SettingsPage][Action] Delete environment ${id}`);
      try {
        await api.deleteEnvironment(id);
        addToast($t.settings?.env_deleted , "success");
        await loadSettings();
      } catch (error) {
        console.error(
          "[SettingsPage][Coherence:Failed] Failed to delete environment:",
          error,
        );
        addToast($t.settings?.env_delete_failed , "error");
      }
    }
  }
</script>

<div class="mx-auto w-full max-w-7xl space-y-6">
  <!-- Header -->
  <div class="flex items-center justify-between mb-6">
    <h1 class="text-2xl font-bold text-gray-900">
      {$t.settings?.title }
    </h1>
    <button
      class="inline-flex items-center justify-center rounded-lg bg-primary px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-primary-hover"
      on:click={loadSettings}
    >
      {$t.common?.refresh }
    </button>
  </div>

  <!-- Error Banner -->
  {#if error}
    <div
      class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4 flex items-center justify-between"
    >
      <span>{error}</span>
      <button
        class="px-4 py-2 bg-destructive text-white rounded hover:bg-destructive-hover transition-colors"
        on:click={loadSettings}
      >
        {$t.common?.retry }
      </button>
    </div>
  {/if}

  <!-- Loading State -->
  {#if isLoading}
    <div class="rounded-xl border border-slate-200 bg-white p-6 shadow-sm">
      <div class="space-y-3">
        <div class="h-8 animate-pulse rounded bg-slate-200"></div>
        <div class="h-8 animate-pulse rounded bg-slate-200"></div>
        <div class="h-8 animate-pulse rounded bg-slate-200"></div>
        <div class="h-8 animate-pulse rounded bg-slate-200"></div>
        <div class="h-8 animate-pulse rounded bg-slate-200"></div>
      </div>
    </div>
  {:else if settings}
    <!-- Tabs -->
    <div class="border-b border-gray-200 mb-6">
      <button
        class="px-4 py-2 text-sm font-medium transition-colors focus:outline-none border-b-2"
        class:text-blue-600={activeTab === "environments"}
        class:border-blue-600={activeTab === "environments"}
        class:text-gray-600={activeTab !== "environments"}
        class:border-transparent={activeTab !== "environments"}
        class:hover:text-gray-800={activeTab !== "environments"}
        class:hover:border-gray-300={activeTab !== "environments"}
        aria-current={activeTab === "environments" ? "page" : undefined}
        on:click={() => handleTabChange("environments")}
      >
        {$t.settings?.environments }
      </button>
      <button
        class="px-4 py-2 text-sm font-medium transition-colors focus:outline-none border-b-2"
        class:text-blue-600={activeTab === "logging"}
        class:border-blue-600={activeTab === "logging"}
        class:text-gray-600={activeTab !== "logging"}
        class:border-transparent={activeTab !== "logging"}
        class:hover:text-gray-800={activeTab !== "logging"}
        class:hover:border-gray-300={activeTab !== "logging"}
        aria-current={activeTab === "logging" ? "page" : undefined}
        on:click={() => handleTabChange("logging")}
      >
        {$t.settings?.logging }
      </button>
      <button
        class="px-4 py-2 text-sm font-medium transition-colors focus:outline-none border-b-2"
        class:text-blue-600={activeTab === "connections"}
        class:border-blue-600={activeTab === "connections"}
        class:text-gray-600={activeTab !== "connections"}
        class:border-transparent={activeTab !== "connections"}
        class:hover:text-gray-800={activeTab !== "connections"}
        class:hover:border-gray-300={activeTab !== "connections"}
        aria-current={activeTab === "connections" ? "page" : undefined}
        on:click={() => handleTabChange("connections")}
      >
        {$t.settings?.connections }
      </button>
      <button
        class="px-4 py-2 text-sm font-medium transition-colors focus:outline-none border-b-2"
        class:text-blue-600={activeTab === "llm"}
        class:border-blue-600={activeTab === "llm"}
        class:text-gray-600={activeTab !== "llm"}
        class:border-transparent={activeTab !== "llm"}
        class:hover:text-gray-800={activeTab !== "llm"}
        class:hover:border-gray-300={activeTab !== "llm"}
        aria-current={activeTab === "llm" ? "page" : undefined}
        on:click={() => handleTabChange("llm")}
      >
        {$t.settings?.llm }
      </button>
      <button
        class="px-4 py-2 text-sm font-medium transition-colors focus:outline-none border-b-2"
        class:text-blue-600={activeTab === "migration"}
        class:border-blue-600={activeTab === "migration"}
        class:text-gray-600={activeTab !== "migration"}
        class:border-transparent={activeTab !== "migration"}
        class:hover:text-gray-800={activeTab !== "migration"}
        class:hover:border-gray-300={activeTab !== "migration"}
        aria-current={activeTab === "migration" ? "page" : undefined}
        on:click={() => handleTabChange("migration")}
      >
        {$t.settings?.migration_sync }
      </button>
      <button
        class="px-4 py-2 text-sm font-medium transition-colors focus:outline-none border-b-2"
        class:text-blue-600={activeTab === "storage"}
        class:border-blue-600={activeTab === "storage"}
        class:text-gray-600={activeTab !== "storage"}
        class:border-transparent={activeTab !== "storage"}
        class:hover:text-gray-800={activeTab !== "storage"}
        class:hover:border-gray-300={activeTab !== "storage"}
        aria-current={activeTab === "storage" ? "page" : undefined}
        on:click={() => handleTabChange("storage")}
      >
        {$t.settings?.storage }
      </button>
    </div>

    <!-- Tab Content -->
    <div class="rounded-xl border border-slate-200 bg-white p-6 shadow-sm">
      {#if activeTab === "environments"}
        <!-- Environments Tab -->
        <div class="text-lg font-medium mb-4">
          <h2 class="text-xl font-bold mb-4">
            {$t.settings?.environments }
          </h2>
          <p class="text-gray-600 mb-6">
            {$t.settings?.env_description}
          </p>

          {#if !editingEnvId && !isAddingEnv}
            <div class="flex justify-end mb-6">
              <button
                class="bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700"
                on:click={() => {
                  isAddingEnv = true;
                  resetEnvForm();
                }}
              >
                {$t.settings?.env_add }
              </button>
            </div>
          {/if}

          {#if editingEnvId || isAddingEnv}
            <!-- Add/Edit Environment Form -->
            <div class="bg-gray-50 p-6 rounded-lg mb-6 border border-gray-200">
              <h3 class="text-lg font-medium mb-4">
                {editingEnvId
                  ? $t.settings?.env_edit 
                  : $t.settings?.env_add }
              </h3>
              <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
                <div>
                  <label
                    for="env_id"
                    class="block text-sm font-medium text-gray-700"
                    >{$t.common?.id }</label
                  >
                  <input
                    type="text"
                    id="env_id"
                    bind:value={newEnv.id}
                    disabled={!!editingEnvId}
                    class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm p-2 disabled:bg-gray-100 disabled:text-gray-500"
                  />
                </div>
                <div>
                  <label
                    for="env_name"
                    class="block text-sm font-medium text-gray-700"
                    >{$t.connections?.name }</label
                  >
                  <input
                    type="text"
                    id="env_name"
                    bind:value={newEnv.name}
                    class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm p-2"
                  />
                </div>
                <div>
                  <label
                    for="env_url"
                    class="block text-sm font-medium text-gray-700">{$t.settings?.env_url}</label
                  >
                  <input
                    type="text"
                    id="env_url"
                    bind:value={newEnv.url}
                    class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm p-2"
                  />
                </div>
                <div>
                  <label
                    for="env_user"
                    class="block text-sm font-medium text-gray-700"
                    >{$t.connections?.user }</label
                  >
                  <input
                    type="text"
                    id="env_user"
                    bind:value={newEnv.username}
                    class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm p-2"
                  />
                </div>
                <div>
                  <label
                    for="env_pass"
                    class="block text-sm font-medium text-gray-700"
                    >{$t.connections?.pass }</label
                  >
                  <input
                    type="password"
                    id="env_pass"
                    bind:value={newEnv.password}
                    class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm p-2"
                  />
                </div>
                <div class="flex items-center mt-6">
                  <input
                    type="checkbox"
                    id="env_default"
                    bind:checked={newEnv.is_default}
                    class="h-4 w-4 text-blue-600 border-gray-300 rounded"
                  />
                  <label
                    for="env_default"
                    class="ml-2 block text-sm text-gray-900"
                    >{$t.settings?.env_default }</label
                  >
                </div>
              </div>

              <h3 class="text-lg font-medium mb-4 mt-6">
                {$t.tasks?.backup_schedule }
              </h3>
              <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
                <div class="flex items-center">
                  <input
                    type="checkbox"
                    id="backup_enabled"
                    bind:checked={newEnv.backup_schedule.enabled}
                    class="h-4 w-4 text-blue-600 border-gray-300 rounded"
                  />
                  <label
                    for="backup_enabled"
                    class="ml-2 block text-sm text-gray-900"
                    >{$t.settings?.enable_auto_backups }</label
                  >
                </div>
                <div>
                  <label
                    for="cron_expression"
                    class="block text-sm font-medium text-gray-700"
                    >{$t.tasks?.cron_label }</label
                  >
                  <input
                    type="text"
                    id="cron_expression"
                    bind:value={newEnv.backup_schedule.cron_expression}
                    placeholder={$t.settings?.cron_placeholder }
                    class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm p-2"
                  />
                  <p class="text-xs text-gray-500 mt-1">
                    {$t.tasks?.cron_hint }
                  </p>
                </div>
              </div>

              <div class="mt-6 flex gap-2 justify-end">
                <button
                  on:click={() => {
                    isAddingEnv = false;
                    editingEnvId = null;
                    resetEnvForm();
                  }}
                  class="bg-gray-200 text-gray-700 px-4 py-2 rounded hover:bg-gray-300"
                >
                  {$t.common?.cancel }
                </button>
                <button
                  on:click={handleAddOrUpdateEnv}
                  class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700"
                >
                  {editingEnvId
                    ? $t.settings?.env_update 
                    : $t.settings?.env_add }
                </button>
              </div>
            </div>
          {/if}

          {#if settings.environments && settings.environments.length > 0}
            <div class="mt-6 overflow-x-auto border border-gray-200 rounded-lg">
              <table class="min-w-full divide-y divide-gray-200">
                <thead class="bg-gray-50">
                  <tr>
                    <th
                      class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
                      >{$t.connections?.name }</th
                    >
                    <th
                      class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
                      >{$t.settings?.env_url }</th
                    >
                    <th
                      class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
                      >{$t.connections?.user }</th
                    >
                    <th
                      class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
                      >{$t.settings?.default }</th
                    >
                    <th
                      class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider"
                      >{$t.settings?.env_actions }</th
                    >
                  </tr>
                </thead>
                <tbody class="bg-white divide-y divide-gray-200">
                  {#each settings.environments as env}
                    <tr>
                      <td class="px-6 py-4 whitespace-nowrap">{env.name}</td>
                      <td class="px-6 py-4 whitespace-nowrap">{env.url}</td>
                      <td class="px-6 py-4 whitespace-nowrap">{env.username}</td
                      >
                      <td class="px-6 py-4 whitespace-nowrap">
                        {#if env.is_default}
                          <span
                            class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"
                          >
                            {$t.common?.yes }
                          </span>
                        {:else}
                          <span class="text-gray-500">{$t.common?.no }</span>
                        {/if}
                      </td>
                      <td
                        class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"
                      >
                        <button
                          class="text-green-600 hover:text-green-900 mr-4"
                          on:click={() => handleTestEnv(env.id)}
                        >
                          {$t.settings?.env_test }
                        </button>
                        <button
                          class="text-indigo-600 hover:text-indigo-900 mr-4"
                          on:click={() => editEnv(env)}
                        >
                          {$t.common.edit }
                        </button>
                        <button
                          class="text-red-600 hover:text-red-900"
                          on:click={() => handleDeleteEnv(env.id)}
                        >
                          {$t.settings?.env_delete }
                        </button>
                      </td>
                    </tr>
                  {/each}
                </tbody>
              </table>
            </div>
          {:else if !isAddingEnv}
            <div
              class="mb-4 p-4 bg-yellow-100 border-l-4 border-yellow-500 text-yellow-700"
            >
              <p class="font-bold">{$t.settings?.warning }</p>
              <p>
                No Superset environments configured. You must add at least one
                environment to perform backups or migrations.
              </p>
            </div>
          {/if}
        </div>
      {:else if activeTab === "logging"}
        <!-- Logging Tab -->
        <div class="text-lg font-medium mb-4">
          <h2 class="text-xl font-bold mb-4">
            {$t.settings?.logging }
          </h2>
          <p class="text-gray-600 mb-6">
            {$t.settings?.logging_description}
          </p>

          <div class="bg-gray-50 p-6 rounded-lg border border-gray-200">
            <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
              <div>
                <label
                  for="log_level"
                  class="block text-sm font-medium text-gray-700"
                  >{$t.settings?.log_level }</label
                >
                <select
                  id="log_level"
                  bind:value={settings.logging.level}
                  class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm p-2"
                >
                  <option value="DEBUG">DEBUG</option>
                  <option value="INFO">INFO</option>
                  <option value="WARNING">WARNING</option>
                  <option value="ERROR">ERROR</option>
                  <option value="CRITICAL">CRITICAL</option>
                </select>
              </div>
              <div>
                <label
                  for="task_log_level"
                  class="block text-sm font-medium text-gray-700"
                  >{$t.settings?.task_log_level }</label
                >
                <select
                  id="task_log_level"
                  bind:value={settings.logging.task_log_level}
                  class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm p-2"
                >
                  <option value="DEBUG">DEBUG</option>
                  <option value="INFO">INFO</option>
                  <option value="WARNING">WARNING</option>
                  <option value="ERROR">ERROR</option>
                </select>
              </div>
              <div class="md:col-span-2">
                <label class="flex items-center">
                  <input
                    type="checkbox"
                    id="enable_belief_state"
                    bind:checked={settings.logging.enable_belief_state}
                    class="h-4 w-4 text-blue-600 border-gray-300 rounded"
                  />
                  <span class="ml-2 block text-sm text-gray-900"
                    >{$t.settings?.enable_belief_state }</span
                  >
                </label>
                <p class="text-xs text-gray-500 mt-1 ml-6">
                  {$t.settings?.belief_state_hint}
                </p>
              </div>
            </div>

            <div class="mt-6 flex justify-end">
              <button
                on:click={handleSave}
                class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700"
              >
                {$t.settings?.save_logging }
              </button>
            </div>
          </div>
        </div>
      {:else if activeTab === "connections"}
        <!-- Connections Tab -->
        <div class="text-lg font-medium mb-4">
          <h2 class="text-xl font-bold mb-4">
            {$t.settings?.connections }
          </h2>
          <p class="text-gray-600 mb-6">
            {$t.settings?.connections_description}
          </p>

          {#if settings.connections && settings.connections.length > 0}
            <!-- Connections list would go here -->
            <p class="text-gray-500 italic">
              No additional connections configured. Superset database
              connections are used by default.
            </p>
          {:else}
            <div
              class="text-center py-8 bg-gray-50 rounded-lg border border-dashed border-gray-300"
            >
              <p class="text-gray-500">
                {$t.settings?.no_external_connections}
              </p>
              <button
                class="mt-4 px-4 py-2 border border-blue-600 text-blue-600 rounded hover:bg-blue-50"
              >
                {$t.connections?.add_new }
              </button>
            </div>
          {/if}
        </div>
      {:else if activeTab === "llm"}
        <!-- LLM Tab -->
        <div class="text-lg font-medium mb-4">
          <h2 class="text-xl font-bold mb-4">
            {$t.settings?.llm }
          </h2>
          <p class="text-gray-600 mb-6">
            {$t.settings?.llm_description}
          </p>

          <ProviderConfig
            providers={settings.llm_providers || []}
            onSave={loadSettings}
          />

          <div class="mt-6 rounded-lg border border-gray-200 bg-white p-4">
            <h3 class="text-base font-semibold text-gray-900">
              {$t.settings?.llm_chatbot_settings_title}
            </h3>
            <p class="mt-1 text-sm text-gray-600">
              {$t.settings?.llm_chatbot_settings_description}
            </p>

            <div class="mt-4 grid grid-cols-1 gap-4 md:grid-cols-2">
              <div>
                <label
                  for="planner-provider"
                  class="block text-sm font-medium text-gray-700"
                >
                  {$t.settings?.llm_chatbot_provider }
                </label>
                <select
                  id="planner-provider"
                  bind:value={settings.llm.assistant_planner_provider}
                  class="mt-1 block w-full rounded-md border border-gray-300 p-2 text-sm"
                >
                  <option value=""
                    >{$t.dashboard?.use_default }</option
                  >
                  {#each settings.llm_providers || [] as provider}
                    <option value={provider.id}>
                      {provider.name} ({provider.default_model})
                    </option>
                  {/each}
                </select>
              </div>

              <div>
                <label
                  for="planner-model"
                  class="block text-sm font-medium text-gray-700"
                >
                  {$t.settings?.llm_chatbot_model }
                </label>
                <input
                  id="planner-model"
                  type="text"
                  bind:value={settings.llm.assistant_planner_model}
                  placeholder={$t.settings?.llm_chatbot_model_placeholder}
                  class="mt-1 block w-full rounded-md border border-gray-300 p-2 text-sm"
                />
              </div>
            </div>
          </div>

          <div class="mt-6 rounded-lg border border-gray-200 bg-white p-4">
            <h3 class="text-base font-semibold text-gray-900">
              {$t.settings?.llm_provider_bindings_title}
            </h3>
            <p class="mt-1 text-sm text-gray-600">
              {$t.settings?.llm_provider_bindings_description}
            </p>

            <div class="mt-4 grid grid-cols-1 gap-4 md:grid-cols-2">
              <div>
                <label
                  for="binding-dashboard-validation"
                  class="block text-sm font-medium text-gray-700"
                >
                  {$t.settings?.llm_binding_dashboard_validation}
                </label>
                <select
                  id="binding-dashboard-validation"
                  bind:value={
                    settings.llm.provider_bindings.dashboard_validation
                  }
                  class="mt-1 block w-full rounded-md border border-gray-300 p-2 text-sm"
                >
                  <option value=""
                    >{$t.dashboard?.use_default }</option
                  >
                  {#each settings.llm_providers || [] as provider}
                    <option value={provider.id}>
                      {provider.name} ({provider.default_model})
                    </option>
                  {/each}
                </select>
                {#if !isDashboardValidationBindingValid()}
                  <p class="mt-1 text-xs text-amber-700">
                    {$t.settings?.llm_multimodal_warning}
                  </p>
                {/if}
              </div>

              <div>
                <label
                  for="binding-documentation"
                  class="block text-sm font-medium text-gray-700"
                >
                  {$t.settings?.llm_binding_documentation}
                </label>
                <select
                  id="binding-documentation"
                  bind:value={settings.llm.provider_bindings.documentation}
                  class="mt-1 block w-full rounded-md border border-gray-300 p-2 text-sm"
                >
                  <option value=""
                    >{$t.dashboard?.use_default }</option
                  >
                  {#each settings.llm_providers || [] as provider}
                    <option value={provider.id}>
                      {provider.name} ({provider.default_model})
                    </option>
                  {/each}
                </select>
              </div>

              <div class="md:col-span-2">
                <label
                  for="binding-git-commit"
                  class="block text-sm font-medium text-gray-700"
                >
                  {$t.settings?.llm_binding_git_commit }
                </label>
                <select
                  id="binding-git-commit"
                  bind:value={settings.llm.provider_bindings.git_commit}
                  class="mt-1 block w-full rounded-md border border-gray-300 p-2 text-sm"
                >
                  <option value=""
                    >{$t.dashboard?.use_default }</option
                  >
                  {#each settings.llm_providers || [] as provider}
                    <option value={provider.id}>
                      {provider.name} ({provider.default_model})
                    </option>
                  {/each}
                </select>
              </div>
            </div>
          </div>

          <div class="mt-6 rounded-lg border border-gray-200 bg-gray-50 p-4">
            <h3 class="text-base font-semibold text-gray-900">
              {$t.settings?.llm_prompts_title }
            </h3>
            <p class="mt-1 text-sm text-gray-600">
              {$t.settings?.llm_prompts_description}
            </p>

            <div class="mt-4 space-y-4">
              <div>
                <label
                  for="documentation-prompt"
                  class="block text-sm font-medium text-gray-700"
                >
                  {$t.settings?.llm_prompt_documentation}
                </label>
                <textarea
                  id="documentation-prompt"
                  bind:value={settings.llm.prompts.documentation_prompt}
                  rows="8"
                  class="mt-1 block w-full rounded-md border border-gray-300 p-2 font-mono text-xs"
                ></textarea>
              </div>

              <div>
                <label
                  for="dashboard-validation-prompt"
                  class="block text-sm font-medium text-gray-700"
                >
                  {$t.settings?.llm_prompt_dashboard_validation}
                </label>
                <textarea
                  id="dashboard-validation-prompt"
                  bind:value={settings.llm.prompts.dashboard_validation_prompt}
                  rows="10"
                  class="mt-1 block w-full rounded-md border border-gray-300 p-2 font-mono text-xs"
                ></textarea>
              </div>

              <div>
                <label
                  for="git-commit-prompt"
                  class="block text-sm font-medium text-gray-700"
                >
                  {$t.settings?.llm_prompt_git_commit }
                </label>
                <textarea
                  id="git-commit-prompt"
                  bind:value={settings.llm.prompts.git_commit_prompt}
                  rows="8"
                  class="mt-1 block w-full rounded-md border border-gray-300 p-2 font-mono text-xs"
                ></textarea>
              </div>
            </div>

            <div class="mt-4 flex justify-end">
              <button
                class="rounded bg-blue-600 px-4 py-2 text-white hover:bg-blue-700"
                on:click={handleSave}
              >
                {$t.settings?.save_llm_prompts }
              </button>
            </div>
          </div>
        </div>
      {:else if activeTab === "migration"}
        <!-- Migration Sync Tab -->
        <div class="text-lg font-medium mb-4">
          <h2 class="text-xl font-bold mb-4">
            {$t.settings?.migration_sync_title}
          </h2>
          <p class="text-gray-600 mb-6">
            {$t.settings?.migration_sync_description}
          </p>

          <!-- Cron Configuration -->
          <div class="bg-gray-50 p-6 rounded-lg border border-gray-200 mb-6">
            <h3 class="text-lg font-medium mb-4">
              {$t.settings?.sync_schedule }
            </h3>
            <div class="flex items-end gap-4">
              <div class="flex-grow">
                <label
                  for="migration_cron"
                  class="block text-sm font-medium text-gray-700"
                  >{$t.tasks?.cron_label }</label
                >
                <input
                  type="text"
                  id="migration_cron"
                  bind:value={migrationCron}
                  placeholder={$t.settings?.migration_cron_placeholder }
                  class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm p-2 font-mono text-sm"
                />
                <p class="text-xs text-gray-500 mt-1">
                  {$t.settings?.migration_cron_hint}
                </p>
              </div>
              <button
                on:click={saveMigrationSettings}
                disabled={isSavingMigration}
                class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 h-[42px] min-w-[100px] flex items-center justify-center disabled:opacity-50"
              >
                {isSavingMigration
                  ? $t.settings?.saving 
                  : $t.common?.save }
              </button>
              <button
                on:click={triggerSyncNow}
                disabled={isSyncing}
                class="bg-green-600 text-white px-4 py-2 rounded hover:bg-green-700 h-[42px] min-w-[150px] flex items-center justify-center gap-2 disabled:opacity-50"
              >
                {#if isSyncing}
                  <svg
                    class="w-4 h-4 animate-spin"
                    fill="none"
                    stroke="currentColor"
                    viewBox="0 0 24 24"
                    ><path
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      stroke-width="2"
                      d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
                    ></path></svg
                  >
                  {$t.settings?.syncing }
                {:else}
                  <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="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
                    ></path></svg
                  >
                  {$t.settings?.sync_now }
                {/if}
              </button>
            </div>
          </div>

          <!-- Mappings Table -->
          <div class="bg-gray-50 p-6 rounded-lg border border-gray-200">
            <h3
              class="text-lg font-medium mb-4 flex items-center justify-between"
            >
              <span
                >{$t.settings?.synchronized_resources} <span
                  class="text-sm font-normal text-gray-500"
                  >({mappingsTotal})</span
                ></span
              >
              <button
                on:click={loadMigrationSettings}
                class="text-sm text-indigo-600 hover:text-indigo-800 flex items-center gap-1"
                disabled={isLoadingMigration}
              >
                <svg
                  class="w-4 h-4 {isLoadingMigration ? 'animate-spin' : ''}"
                  fill="none"
                  stroke="currentColor"
                  viewBox="0 0 24 24"
                  ><path
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    stroke-width="2"
                    d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
                  ></path></svg
                >
                {$t.common?.refresh }
              </button>
            </h3>

            <!-- Search and Filters -->
            <div class="flex flex-wrap gap-3 mb-4">
              <div class="flex-1 min-w-[200px]">
                <input
                  type="text"
                  bind:value={mappingsSearch}
                  on:input={onMappingsSearchInput}
                  placeholder={$t.settings?.search_by_name_or_uuid}
                  class="w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:ring-indigo-500 focus:border-indigo-500"
                />
              </div>
              <select
                bind:value={mappingsEnvFilter}
                on:change={onMappingsFilterChange}
                class="px-3 py-2 border border-gray-300 rounded-md text-sm bg-white focus:ring-indigo-500 focus:border-indigo-500"
              >
                <option value="">
                  {$t.settings?.all_environments }
                </option>
                <option value="ss1">ss1</option>
                <option value="ss2">ss2</option>
              </select>
              <select
                bind:value={mappingsTypeFilter}
                on:change={onMappingsFilterChange}
                class="px-3 py-2 border border-gray-300 rounded-md text-sm bg-white focus:ring-indigo-500 focus:border-indigo-500"
              >
                <option value="">{$t.settings?.all_types }</option>
                <option value="chart">{$t.settings?.type_chart }</option>
                <option value="dataset">
                  {$t.nav?.datasets }
                </option>
                <option value="dashboard">
                  {$t.nav?.dashboards }
                </option>
              </select>
            </div>

            <div class="overflow-x-auto border border-gray-200 rounded-lg">
              <table class="min-w-full divide-y divide-gray-200 text-sm">
                <thead class="bg-gray-100">
                  <tr>
                    <th
                      class="px-6 py-3 text-left font-medium text-gray-500 uppercase tracking-wider"
                      >{$t.settings?.resource_name }</th
                    >
                    <th
                      class="px-6 py-3 text-left font-medium text-gray-500 uppercase tracking-wider"
                      >{$t.settings?.type }</th
                    >
                    <th
                      class="px-6 py-3 text-left font-medium text-gray-500 uppercase tracking-wider"
                      >UUID</th
                    >
                    <th
                      class="px-6 py-3 text-left font-medium text-gray-500 uppercase tracking-wider"
                      >{$t.settings?.target_id }</th
                    >
                    <th
                      class="px-6 py-3 text-left font-medium text-gray-500 uppercase tracking-wider"
                      >{$t.dashboard?.environment }</th
                    >
                  </tr>
                </thead>
                <tbody class="bg-white divide-y divide-gray-200">
                  {#if isLoadingMigration && displayMappings.length === 0}
                    <tr
                      ><td
                        colspan="5"
                        class="px-6 py-8 text-center text-gray-500"
                        >{$t.settings?.loading_mappings }</td
                      ></tr
                    >
                  {:else if displayMappings.length === 0}
                    <tr
                      ><td
                        colspan="5"
                        class="px-6 py-8 text-center text-gray-500"
                        >{mappingsSearch ||
                        mappingsEnvFilter ||
                        mappingsTypeFilter
                          ? $t.settings?.no_matching_resources
                          : ($t.settings?.no_synchronized_resources)}</td
                      ></tr
                    >
                  {:else}
                    {#each displayMappings as mapping}
                      <tr class="hover:bg-gray-50">
                        <td
                          class="px-6 py-4 whitespace-nowrap font-medium text-gray-900"
                          >{mapping.resource_name ||
                            $t.common?.not_available}</td
                        >
                        <td class="px-6 py-4 whitespace-nowrap"
                          ><span
                            class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full {mapping.resource_type ===
                            'chart'
                              ? 'bg-blue-100 text-blue-800'
                              : mapping.resource_type === 'dataset'
                                ? 'bg-green-100 text-green-800'
                                : 'bg-purple-100 text-purple-800'}"
                            >{mapping.resource_type}</span
                          ></td
                        >
                        <td
                          class="px-6 py-4 whitespace-nowrap font-mono text-xs text-gray-500"
                          >{mapping.uuid}</td
                        >
                        <td
                          class="px-6 py-4 whitespace-nowrap font-mono text-xs font-bold text-gray-700"
                          >{mapping.remote_id}</td
                        >
                        <td class="px-6 py-4 whitespace-nowrap text-gray-500"
                          >{mapping.environment_id}</td
                        >
                      </tr>
                    {/each}
                  {/if}
                </tbody>
              </table>
            </div>

            <!-- Pagination Controls -->
            {#if mappingsTotal > mappingsPageSize}
              <div
                class="flex items-center justify-between mt-4 text-sm text-gray-600"
              >
                <span
                  >{(
                    $t.dashboard?.showing
                  )
                    .replace(
                      "{start}",
                      String(mappingsPage * mappingsPageSize + 1),
                    )
                    .replace(
                      "{end}",
                      String(
                        Math.min(
                          (mappingsPage + 1) * mappingsPageSize,
                          mappingsTotal,
                        ),
                      ),
                    )
                    .replace("{total}", String(mappingsTotal))}</span
                >
                <div class="flex items-center gap-2">
                  <button
                    on:click={() => goToMappingsPage(0)}
                    disabled={mappingsPage === 0}
                    class="px-2 py-1 rounded border {mappingsPage === 0
                      ? 'bg-gray-100 text-gray-400 cursor-not-allowed'
                      : 'bg-white hover:bg-gray-50 text-gray-700'}">«</button
                  >
                  <button
                    on:click={() => goToMappingsPage(mappingsPage - 1)}
                    disabled={mappingsPage === 0}
                    class="px-2 py-1 rounded border {mappingsPage === 0
                      ? 'bg-gray-100 text-gray-400 cursor-not-allowed'
                      : 'bg-white hover:bg-gray-50 text-gray-700'}">‹</button
                  >
                  <span class="px-3 py-1 font-medium"
                    >{mappingsPage + 1} / {mappingsTotalPages}</span
                  >
                  <button
                    on:click={() => goToMappingsPage(mappingsPage + 1)}
                    disabled={mappingsPage >= mappingsTotalPages - 1}
                    class="px-2 py-1 rounded border {mappingsPage >=
                    mappingsTotalPages - 1
                      ? 'bg-gray-100 text-gray-400 cursor-not-allowed'
                      : 'bg-white hover:bg-gray-50 text-gray-700'}">›</button
                  >
                  <button
                    on:click={() => goToMappingsPage(mappingsTotalPages - 1)}
                    disabled={mappingsPage >= mappingsTotalPages - 1}
                    class="px-2 py-1 rounded border {mappingsPage >=
                    mappingsTotalPages - 1
                      ? 'bg-gray-100 text-gray-400 cursor-not-allowed'
                      : 'bg-white hover:bg-gray-50 text-gray-700'}">»</button
                  >
                </div>
              </div>
            {/if}
          </div>
        </div>
      {:else if activeTab === "storage"}
        <!-- Storage Tab -->
        <div class="text-lg font-medium mb-4">
          <h2 class="text-xl font-bold mb-4">
            {$t.settings?.storage_title }
          </h2>
          <p class="text-gray-600 mb-6">
            {$t.settings?.storage_description}
          </p>

          <div class="bg-gray-50 p-6 rounded-lg border border-gray-200">
            <div class="grid grid-cols-1 gap-4">
              <div>
                <label
                  for="storage_path"
                  class="block text-sm font-medium text-gray-700"
                  >{$t.storage?.root }</label
                >
                <input
                  type="text"
                  id="storage_path"
                  bind:value={settings.storage.root_path}
                  class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm p-2"
                />
              </div>
              <div>
                <label
                  for="backup_path"
                  class="block text-sm font-medium text-gray-700"
                  >{$t.storage?.backups }</label
                >
                <input
                  type="text"
                  id="backup_path"
                  bind:value={settings.storage.backup_path}
                  class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm p-2"
                />
              </div>
              <div>
                <label
                  for="repo_path"
                  class="block text-sm font-medium text-gray-700"
                  >{$t.storage?.repositories }</label
                >
                <input
                  type="text"
                  id="repo_path"
                  bind:value={settings.storage.repo_path}
                  class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm p-2"
                />
              </div>
            </div>

            <div class="mt-6 flex justify-end">
              <button
                on:click={() => handleSave()}
                class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700"
              >
                {$t.settings?.save_storage_config}
              </button>
            </div>
          </div>
        </div>
      {/if}
    </div>
  {/if}
</div>

<!-- [/DEF:SettingsPage:Page] -->
