<!-- [DEF:frontend.src.routes.profile.+page:Component] -->
<script>
  /**
   * @TIER: CRITICAL
   * @PURPOSE: Manage self-scoped profile preference binding with environment-based Superset account lookup and resilient save/cancel UX.
   * @LAYER: UI
   * @RELATION: BINDS_TO -> frontend.src.lib.i18n
   * @RELATION: BINDS_TO -> frontend.src.lib.api
   * @RELATION: BINDS_TO -> frontend.src.lib.stores.environmentContext
   * @INVARIANT: Save operations mutate only current user's preference payload via profile API.
   *
   * @UX_STATE: Default -> Form is preloaded with persisted preference and editable controls.
   * @UX_STATE: LookupLoading -> Account candidate lookup for selected environment is in progress.
   * @UX_STATE: LookupError -> Lookup warning is shown while manual username entry remains available.
   * @UX_STATE: Saving -> Save button is disabled and shows progress text.
   * @UX_STATE: SaveSuccess -> Success toast confirms persisted preference.
   * @UX_STATE: SaveError -> Inline validation and/or toast error feedback is shown.
   * @UX_FEEDBACK: Inline warning and validation messages guide user actions without navigation loss.
   * @UX_RECOVERY: Cancel restores last saved values and rehydrates lookup context.
   * @UX_REATIVITY: State: $state, Derived: $derived.
   */

  import { onMount } from "svelte";
  import { t } from "$lib/i18n";
  import { api } from "$lib/api.js";
  import { addToast } from "$lib/toasts";
  import {
    environmentContextStore,
    initializeEnvironmentContext,
  } from "$lib/stores/environmentContext.js";

  let isPageLoading = $state(true);
  let isSaving = $state(false);

  let selectedEnvironmentId = $state("");
  let supersetUsername = $state("");
  let showOnlyMyDashboards = $state(false);

  let lookupSearch = $state("");
  let lookupItems = $state([]);
  let isLookupLoading = $state(false);
  let lookupWarning = $state("");

  let validationErrors = $state([]);
  let savedSnapshot = $state({
    selectedEnvironmentId: "",
    supersetUsername: "",
    showOnlyMyDashboards: false,
  });

  const environments = $derived($environmentContextStore?.environments || []);
  const normalizedUsername = $derived(String(supersetUsername || "").trim());

  const inlineValidationErrors = $derived.by(() => {
    const errors = [];
    if (normalizedUsername && /\s/.test(normalizedUsername)) {
      errors.push(
        $t.profile?.invalid_username ||
          "Username should not contain spaces. Please enter a valid Apache Superset username.",
      );
    }
    if (showOnlyMyDashboards && !normalizedUsername) {
      errors.push(
        $t.profile?.username_required ||
          "Superset username is required when default filter is enabled.",
      );
    }
    return errors;
  });

  const visibleValidationErrors = $derived.by(() => {
    const merged = [...inlineValidationErrors];
    for (const serverError of validationErrors) {
      if (!merged.includes(serverError)) {
        merged.push(serverError);
      }
    }
    return merged;
  });

  const canSave = $derived(
    !isPageLoading &&
      !isSaving &&
      visibleValidationErrors.length === 0 &&
      (normalizedUsername !== savedSnapshot.supersetUsername ||
        showOnlyMyDashboards !== savedSnapshot.showOnlyMyDashboards),
  );

  function parseValidationErrorsFromError(error) {
    const fallback = String(error?.message || "").trim();
    if (!fallback) return [];
    try {
      const parsed = JSON.parse(fallback);
      if (Array.isArray(parsed)) {
        return parsed.map((item) => String(item || "").trim()).filter(Boolean);
      }
    } catch (_error) {
      // keep fallback below
    }
    return [fallback];
  }

  function setSavedSnapshot() {
    savedSnapshot = {
      selectedEnvironmentId: selectedEnvironmentId || "",
      supersetUsername: normalizedUsername || "",
      showOnlyMyDashboards: Boolean(showOnlyMyDashboards),
    };
  }

  async function loadPreference() {
    const response = await api.getProfilePreferences();
    const preference = response?.preference || {};
    supersetUsername = String(preference.superset_username || "");
    showOnlyMyDashboards = Boolean(preference.show_only_my_dashboards);
    setSavedSnapshot();
  }

  async function loadLookupCandidates() {
    const environmentId = String(selectedEnvironmentId || "").trim();
    if (!environmentId) {
      lookupItems = [];
      lookupWarning = "";
      return;
    }

    isLookupLoading = true;
    lookupWarning = "";
    try {
      const response = await api.lookupSupersetAccounts(environmentId, {
        search: lookupSearch.trim() || undefined,
        page_index: 0,
        page_size: 20,
        sort_column: "username",
        sort_order: "asc",
      });

      lookupItems = Array.isArray(response?.items) ? response.items : [];
      if (response?.status === "degraded" && response?.warning) {
        lookupWarning = String(response.warning);
      } else {
        lookupWarning = "";
      }
    } catch (_error) {
      lookupItems = [];
      lookupWarning =
        $t.profile?.lookup_error ||
        "Cannot load Superset accounts for this environment right now. You can enter username manually.";
    } finally {
      isLookupLoading = false;
    }
  }

  function handleSelectCandidate(username) {
    supersetUsername = String(username || "");
    validationErrors = [];
  }

  async function handleEnvironmentChange(event) {
    selectedEnvironmentId = String(event?.target?.value || "");
    lookupSearch = "";
    validationErrors = [];
    await loadLookupCandidates();
  }

  async function handleSave() {
    if (inlineValidationErrors.length > 0) {
      validationErrors = [...inlineValidationErrors];
      return;
    }

    isSaving = true;
    validationErrors = [];
    try {
      const response = await api.updateProfilePreferences({
        superset_username: normalizedUsername || null,
        show_only_my_dashboards: Boolean(showOnlyMyDashboards),
      });

      const persistedPreference = response?.preference || {};
      supersetUsername = String(
        persistedPreference.superset_username || normalizedUsername || "",
      );
      showOnlyMyDashboards = Boolean(
        persistedPreference.show_only_my_dashboards ?? showOnlyMyDashboards,
      );

      setSavedSnapshot();
      addToast(
        $t.profile?.save_success || "Preferences saved",
        "success",
      );
    } catch (error) {
      if (error?.status === 422) {
        validationErrors = parseValidationErrorsFromError(error);
      } else {
        addToast(
          $t.profile?.save_error ||
            "Failed to save preferences. Please try again.",
          "error",
        );
      }
    } finally {
      isSaving = false;
    }
  }

  async function handleCancel() {
    selectedEnvironmentId = savedSnapshot.selectedEnvironmentId || "";
    supersetUsername = savedSnapshot.supersetUsername || "";
    showOnlyMyDashboards = Boolean(savedSnapshot.showOnlyMyDashboards);
    validationErrors = [];
    lookupSearch = "";
    await loadLookupCandidates();
  }

  $effect(() => {
    if (validationErrors.length > 0) {
      normalizedUsername;
      showOnlyMyDashboards;
      validationErrors = [];
    }
  });

  $effect(() => {
    const contextSelected = $environmentContextStore?.selectedEnvId || "";
    if (!selectedEnvironmentId && contextSelected) {
      selectedEnvironmentId = contextSelected;
    } else if (!selectedEnvironmentId && environments.length > 0) {
      selectedEnvironmentId = environments[0].id;
    }
  });

  onMount(async () => {
    try {
      await initializeEnvironmentContext();

      if (!selectedEnvironmentId) {
        selectedEnvironmentId =
          $environmentContextStore?.selectedEnvId ||
          environments[0]?.id ||
          "";
      }

      await loadPreference();
      await loadLookupCandidates();
    } catch (_error) {
      addToast(
        $t.profile?.save_error ||
          "Failed to save preferences. Please try again.",
        "error",
      );
    } finally {
      isPageLoading = false;
    }
  });
</script>

<main class="mx-auto w-full max-w-3xl space-y-6 px-4 py-6 lg:px-8">
  <header class="space-y-2">
    <h1 class="text-2xl font-semibold text-slate-900">
      {$t.profile?.title || "Profile"}
    </h1>
    <p class="text-sm text-slate-600">
      {$t.profile?.description ||
        "Manage your dashboard filter preferences."}
    </p>
  </header>

  <section class="rounded-xl border border-slate-200 bg-white p-5 shadow-sm">
    <h2 class="mb-4 text-lg font-semibold text-slate-900">
      {$t.profile?.dashboard_preferences || "Dashboard Preferences"}
    </h2>

    {#if isPageLoading}
      <div class="space-y-3">
        <div class="h-9 animate-pulse rounded bg-slate-200"></div>
        <div class="h-9 animate-pulse rounded bg-slate-200"></div>
        <div class="h-9 animate-pulse rounded bg-slate-200"></div>
      </div>
    {:else}
      <div class="space-y-4">
        <label class="block space-y-1">
          <span class="text-sm font-medium text-slate-700">
            {$t.profile?.superset_environment || "Superset Environment"}
          </span>
          <select
            class="w-full rounded-lg border border-slate-300 px-3 py-2 text-sm"
            bind:value={selectedEnvironmentId}
            onchange={handleEnvironmentChange}
          >
            <option value="">
              {$t.profile?.superset_environment_placeholder || "Select environment"}
            </option>
            {#each environments as env}
              <option value={env.id}>{env.name || env.id}</option>
            {/each}
          </select>
        </label>

        <div class="space-y-2 rounded-lg border border-slate-200 p-3">
          <div class="flex items-center justify-between gap-2">
            <span class="text-sm font-medium text-slate-700">
              {$t.profile?.superset_account || "Your Apache Superset Account"}
            </span>
            <button
              type="button"
              class="rounded-md border border-slate-300 px-2.5 py-1 text-xs font-medium text-slate-700 hover:bg-slate-50 disabled:cursor-not-allowed disabled:opacity-60"
              onclick={loadLookupCandidates}
              disabled={!selectedEnvironmentId || isLookupLoading}
            >
              {$t.profile?.lookup_button || "Lookup"}
            </button>
          </div>

          <input
            type="text"
            class="w-full rounded-lg border border-slate-300 px-3 py-2 text-sm"
            placeholder={$t.profile?.lookup_search_placeholder || "Search account candidates"}
            bind:value={lookupSearch}
            onkeydown={(event) => event.key === "Enter" && loadLookupCandidates()}
          />

          {#if isLookupLoading}
            <p class="text-xs text-slate-500">
              {$t.profile?.lookup_loading || "Loading Superset accounts..."}
            </p>
          {/if}

          {#if lookupWarning}
            <p class="rounded-md border border-amber-200 bg-amber-50 px-2.5 py-2 text-xs text-amber-800">
              {lookupWarning}
            </p>
          {/if}

          {#if !isLookupLoading && lookupItems.length > 0}
            <div class="max-h-44 space-y-1 overflow-auto rounded-md border border-slate-200 p-2">
              {#each lookupItems as item}
                <button
                  type="button"
                  class="flex w-full items-center justify-between rounded px-2 py-1 text-left text-xs text-slate-700 hover:bg-slate-100"
                  onclick={() => handleSelectCandidate(item.username)}
                >
                  <span class="truncate">
                    {item.display_name || item.username}
                  </span>
                  <span class="ml-3 shrink-0 text-slate-500">{item.username}</span>
                </button>
              {/each}
            </div>
          {:else if !isLookupLoading && selectedEnvironmentId && !lookupWarning}
            <p class="text-xs text-slate-500">
              {$t.profile?.lookup_no_results || "No account candidates found. You can enter username manually."}
            </p>
          {/if}
        </div>

        <label class="block space-y-1">
          <span class="text-sm font-medium text-slate-700">
            {$t.profile?.superset_account || "Your Apache Superset Account"}
          </span>
          <input
            type="text"
            class="w-full rounded-lg border px-3 py-2 text-sm {visibleValidationErrors.length > 0 ? 'border-red-300 focus:border-red-400' : 'border-slate-300'}"
            placeholder={$t.profile?.superset_account_placeholder ||
              "Enter your Apache Superset username"}
            bind:value={supersetUsername}
          />
        </label>

        {#if visibleValidationErrors.length > 0}
          <div class="space-y-1">
            {#each visibleValidationErrors as errorText}
              <p class="text-xs text-red-600">{errorText}</p>
            {/each}
          </div>
        {/if}

        <label class="flex items-center gap-3">
          <input
            type="checkbox"
            class="h-4 w-4 rounded border-slate-300"
            bind:checked={showOnlyMyDashboards}
          />
          <span class="text-sm text-slate-700">
            {$t.profile?.show_only_my_dashboards ||
              "Show only my dashboards by default"}
          </span>
        </label>
      </div>

      <div class="mt-6 flex items-center gap-3">
        <button
          type="button"
          class="rounded-lg bg-primary px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-primary-hover disabled:cursor-not-allowed disabled:opacity-60"
          disabled={!canSave}
          onclick={handleSave}
        >
          {#if isSaving}
            {$t.profile?.saving || "Saving..."}
          {:else}
            {$t.profile?.save_preferences || "Save Preferences"}
          {/if}
        </button>
        <button
          type="button"
          class="rounded-lg border border-slate-300 px-4 py-2 text-sm font-medium text-slate-700 transition-colors hover:bg-slate-50"
          onclick={handleCancel}
          disabled={isSaving}
        >
          {$t.common?.cancel || "Cancel"}
        </button>
      </div>
    {/if}
  </section>
</main>

<!-- [/DEF:frontend.src.routes.profile.+page:Component] -->