<!-- [DEF:frontend.src.routes.profile.+page:Component] -->
<script>
  /**
   * @TIER: CRITICAL
   * @PURPOSE: Manage user profile sections for read-only security access, Git identity/token configuration, and UI preferences with 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
   * @RELATION: BINDS_TO -> frontend.src.lib.stores.taskDrawer
   * @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";
  import { setTaskDrawerAutoOpenPreference } from "$lib/stores/taskDrawer.js";

  const START_PAGE_STORAGE_KEY = "ss_tools.profile.start_page";
  const DASHBOARDS_TABLE_DENSITY_STORAGE_KEY =
    "ss_tools.profile.dashboards_table_density";

  function createSecuritySummaryDefault() {
    return {
      read_only: true,
      auth_source: null,
      current_role: null,
      role_source: null,
      roles: [],
      permissions: [],
    };
  }

  function normalizeStartPage(value) {
    const normalized = String(value || "").trim().toLowerCase();
    if (normalized === "datasets") return "datasets";
    if (normalized === "reports" || normalized === "reports-logs") {
      return "reports";
    }
    return "dashboards";
  }

  function normalizeDensity(value) {
    const normalized = String(value || "").trim().toLowerCase();
    if (normalized === "compact") return "compact";
    return "comfortable";
  }

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

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

  let gitUsername = $state("");
  let gitEmail = $state("");
  let gitPersonalAccessTokenInput = $state("");
  let clearGitPersonalAccessToken = $state(false);
  let hasGitPersonalAccessToken = $state(false);
  let gitPersonalAccessTokenMasked = $state("");

  let startPage = $state("dashboards");
  let autoOpenTaskDrawer = $state(true);
  let dashboardsTableDensity = $state("comfortable");

  let telegramId = $state("");
  let emailAddress = $state("");
  let notifyOnFail = $state(true);

  let securitySummary = $state(createSecuritySummaryDefault());

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

  let validationErrors = $state([]);
  let savedSnapshot = $state({
    selectedEnvironmentId: "",
    supersetUsername: "",
    showOnlyMyDashboards: false,
    showOnlySlugDashboards: true,
    gitUsername: "",
    gitEmail: "",
    startPage: "dashboards",
    autoOpenTaskDrawer: true,
    dashboardsTableDensity: "comfortable",
    telegramId: "",
    emailAddress: "",
    notifyOnFail: true,
    hasGitPersonalAccessToken: false,
  });

  const environments = $derived($environmentContextStore?.environments || []);
  const normalizedUsername = $derived(String(supersetUsername || "").trim());
  const normalizedGitUsername = $derived(String(gitUsername || "").trim());
  const normalizedGitEmail = $derived(String(gitEmail || "").trim());
  const normalizedTokenInput = $derived(
    String(gitPersonalAccessTokenInput || "").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.",
      );
    }

    if (normalizedGitEmail) {
      const invalidGitEmail =
        normalizedGitEmail.includes(" ") ||
        !normalizedGitEmail.includes("@") ||
        normalizedGitEmail.startsWith("@") ||
        normalizedGitEmail.endsWith("@");
      if (invalidGitEmail) {
        errors.push(
          $t.profile?.invalid_git_email ||
            "Git email should be a valid email address.",
        );
      }
    }

    if (emailAddress) {
      const invalidEmail =
        emailAddress.includes(" ") ||
        !emailAddress.includes("@") ||
        emailAddress.startsWith("@") ||
        emailAddress.endsWith("@");
      if (invalidEmail) {
        errors.push(
          $t.profile?.invalid_notification_email ||
            "Notification email should be a valid email address.",
        );
      }
    }

    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 ||
        Boolean(showOnlySlugDashboards) !== savedSnapshot.showOnlySlugDashboards ||
        normalizedGitUsername !== savedSnapshot.gitUsername ||
        normalizedGitEmail !== savedSnapshot.gitEmail ||
        normalizeStartPage(startPage) !== savedSnapshot.startPage ||
        Boolean(autoOpenTaskDrawer) !== savedSnapshot.autoOpenTaskDrawer ||
        normalizeDensity(dashboardsTableDensity) !==
          savedSnapshot.dashboardsTableDensity ||
        clearGitPersonalAccessToken ||
        normalizedTokenInput.length > 0 ||
        telegramId !== savedSnapshot.telegramId ||
        emailAddress !== savedSnapshot.emailAddress ||
        notifyOnFail !== savedSnapshot.notifyOnFail),
  );

  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),
      showOnlySlugDashboards: Boolean(showOnlySlugDashboards),
      gitUsername: normalizedGitUsername || "",
      gitEmail: normalizedGitEmail || "",
      startPage: normalizeStartPage(startPage),
      autoOpenTaskDrawer: Boolean(autoOpenTaskDrawer),
      dashboardsTableDensity: normalizeDensity(dashboardsTableDensity),
      telegramId: telegramId || "",
      emailAddress: emailAddress || "",
      notifyOnFail: Boolean(notifyOnFail),
      hasGitPersonalAccessToken: Boolean(hasGitPersonalAccessToken),
    };
  }

  function syncLocalUiPreferenceCaches() {
    if (typeof window !== "undefined") {
      window.localStorage.setItem(START_PAGE_STORAGE_KEY, normalizeStartPage(startPage));
      window.localStorage.setItem(
        DASHBOARDS_TABLE_DENSITY_STORAGE_KEY,
        normalizeDensity(dashboardsTableDensity),
      );
    }
    setTaskDrawerAutoOpenPreference(Boolean(autoOpenTaskDrawer));
  }

  function applyPreferenceResponse(response) {
    const preference = response?.preference || {};
    const security = response?.security || {};

    supersetUsername = String(preference.superset_username || "");
    showOnlyMyDashboards = Boolean(preference.show_only_my_dashboards);
    showOnlySlugDashboards = preference.show_only_slug_dashboards !== false;

    gitUsername = String(preference.git_username || "");
    gitEmail = String(preference.git_email || "");
    hasGitPersonalAccessToken = Boolean(preference.has_git_personal_access_token);
    gitPersonalAccessTokenMasked = String(
      preference.git_personal_access_token_masked || "",
    );
    gitPersonalAccessTokenInput = "";
    clearGitPersonalAccessToken = false;

    startPage = normalizeStartPage(preference.start_page);
    autoOpenTaskDrawer = preference.auto_open_task_drawer !== false;
    dashboardsTableDensity = normalizeDensity(preference.dashboards_table_density);

    telegramId = String(preference.telegram_id || "");
    emailAddress = String(preference.email_address || "");
    notifyOnFail = preference.notify_on_fail !== false;

    securitySummary = {
      read_only: security?.read_only !== false,
      auth_source: security?.auth_source || null,
      current_role: security?.current_role || null,
      role_source: security?.role_source || null,
      roles: Array.isArray(security?.roles) ? security.roles : [],
      permissions: Array.isArray(security?.permissions)
        ? security.permissions
        : [],
    };

    setSavedSnapshot();
    syncLocalUiPreferenceCaches();
  }

  async function loadPreference() {
    const response = await api.getProfilePreferences();
    applyPreferenceResponse(response);
  }

  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 = [];
  }

  function handleGitTokenInput(event) {
    gitPersonalAccessTokenInput = String(event?.target?.value || "");
    if (gitPersonalAccessTokenInput.trim().length > 0) {
      clearGitPersonalAccessToken = false;
    }
  }

  function handleClearGitToken() {
    if (!hasGitPersonalAccessToken && normalizedTokenInput.length === 0) {
      return;
    }
    gitPersonalAccessTokenInput = "";
    clearGitPersonalAccessToken = true;
  }

  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 payload = {
        superset_username: normalizedUsername || null,
        show_only_my_dashboards: Boolean(showOnlyMyDashboards),
        show_only_slug_dashboards: Boolean(showOnlySlugDashboards),
        git_username: normalizedGitUsername || null,
        git_email: normalizedGitEmail || null,
        start_page: normalizeStartPage(startPage),
        auto_open_task_drawer: Boolean(autoOpenTaskDrawer),
        dashboards_table_density: normalizeDensity(dashboardsTableDensity),
        telegram_id: telegramId || null,
        email_address: emailAddress || null,
        notify_on_fail: Boolean(notifyOnFail),
      };

      if (clearGitPersonalAccessToken) {
        payload.git_personal_access_token = "";
      }
      if (normalizedTokenInput.length > 0) {
        payload.git_personal_access_token = normalizedTokenInput;
      }

      const response = await api.updateProfilePreferences(payload);
      applyPreferenceResponse(response);

      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);
    showOnlySlugDashboards = Boolean(savedSnapshot.showOnlySlugDashboards);

    gitUsername = savedSnapshot.gitUsername || "";
    gitEmail = savedSnapshot.gitEmail || "";
    startPage = savedSnapshot.startPage || "dashboards";
    autoOpenTaskDrawer = Boolean(savedSnapshot.autoOpenTaskDrawer);
    dashboardsTableDensity =
      savedSnapshot.dashboardsTableDensity || "comfortable";
    telegramId = savedSnapshot.telegramId || "";
    emailAddress = savedSnapshot.emailAddress || "";
    notifyOnFail = Boolean(savedSnapshot.notifyOnFail);
    hasGitPersonalAccessToken = Boolean(savedSnapshot.hasGitPersonalAccessToken);

    gitPersonalAccessTokenInput = "";
    clearGitPersonalAccessToken = false;
    validationErrors = [];
    lookupSearch = "";
    syncLocalUiPreferenceCaches();
    await loadLookupCandidates();
  }

  $effect(() => {
    if (validationErrors.length > 0) {
      normalizedUsername;
      showOnlyMyDashboards;
      normalizedGitEmail;
      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-5xl 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 profile preferences, Git integration, and access view."}
    </p>
  </header>

  {#if isPageLoading}
    <div class="space-y-4">
      <div class="h-24 animate-pulse rounded-xl bg-slate-200"></div>
      <div class="h-36 animate-pulse rounded-xl bg-slate-200"></div>
      <div class="h-48 animate-pulse rounded-xl bg-slate-200"></div>
    </div>
  {:else}
    <section class="rounded-xl border border-slate-200 bg-white p-5 shadow-sm">
      <div class="mb-4 flex items-center justify-between gap-3">
        <h2 class="text-lg font-semibold text-slate-900">
          {$t.profile?.security_access || "Security & Access"}
        </h2>
        <span class="rounded-full border border-slate-300 bg-slate-50 px-2.5 py-1 text-xs font-medium text-slate-600">
          {$t.profile?.read_only || "Read-only"}
        </span>
      </div>

      <p class="mb-4 text-xs text-slate-500">
        {$t.profile?.security_read_only_note ||
          "This section is read-only. Role changes are managed in Admin → Users."}
      </p>

      <div class="grid gap-4 md:grid-cols-2">
        <div class="rounded-lg border border-slate-200 p-3">
          <p class="text-xs uppercase tracking-wide text-slate-500">
            {$t.profile?.current_role || "Current Role"}
          </p>
          <p class="mt-1 text-sm font-semibold text-slate-900">
            {securitySummary.current_role ||
              $t.common?.not_available ||
              "N/A"}
          </p>
        </div>

        <div class="rounded-lg border border-slate-200 p-3">
          <p class="text-xs uppercase tracking-wide text-slate-500">
            {$t.profile?.role_source || "Role Source"}
          </p>
          <p class="mt-1 text-sm font-semibold text-slate-900">
            {securitySummary.role_source ||
              securitySummary.auth_source ||
              $t.common?.not_available ||
              "N/A"}
          </p>
        </div>
      </div>

      <div class="mt-4 space-y-2">
        <p class="text-xs uppercase tracking-wide text-slate-500">
          {$t.profile?.permissions || "Permissions"}
        </p>
        {#if securitySummary.permissions.length > 0}
          <div class="flex flex-wrap gap-2">
            {#each securitySummary.permissions as permission (permission.key)}
              <span
                class="inline-flex items-center gap-1 rounded-full border px-2.5 py-1 text-xs font-medium {permission.allowed
                  ? 'border-emerald-200 bg-emerald-50 text-emerald-700'
                  : 'border-rose-200 bg-rose-50 text-rose-700'}"
              >
                <span>{permission.allowed ? "✔" : "✖"}</span>
                <span>{permission.key}</span>
              </span>
            {/each}
          </div>
        {:else}
          <p class="text-xs text-slate-500">
            {$t.profile?.permission_none || "No permissions available"}
          </p>
        {/if}
      </div>
    </section>

    <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?.git_integration || "Git Integration (PAT)"}
      </h2>

      <div class="grid gap-4 md:grid-cols-2">
        <label class="block space-y-1">
          <span class="text-sm font-medium text-slate-700">
            {$t.profile?.git_username || "Git Username"}
          </span>
          <input
            type="text"
            class="w-full rounded-lg border border-slate-300 px-3 py-2 text-sm"
            placeholder={$t.profile?.git_username_placeholder ||
              "Enter git username"}
            bind:value={gitUsername}
          />
        </label>

        <label class="block space-y-1">
          <span class="text-sm font-medium text-slate-700">
            {$t.profile?.git_email || "Git Email"}
          </span>
          <input
            type="email"
            class="w-full rounded-lg border border-slate-300 px-3 py-2 text-sm"
            placeholder={$t.profile?.git_email_placeholder ||
              "Enter git email"}
            bind:value={gitEmail}
          />
        </label>
      </div>

      <div class="mt-4 space-y-2 rounded-lg border border-slate-200 p-3">
        <div class="flex items-center justify-between gap-3">
          <span class="text-sm font-medium text-slate-700">
            {$t.profile?.git_token || "GitLab / GitHub Token"}
          </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={handleClearGitToken}
            disabled={!hasGitPersonalAccessToken && normalizedTokenInput.length === 0}
          >
            {$t.profile?.git_token_clear || "Clear token"}
          </button>
        </div>

        <input
          type="password"
          class="w-full rounded-lg border border-slate-300 px-3 py-2 text-sm"
          placeholder={$t.profile?.git_token_placeholder ||
            "Enter new personal access token"}
          value={gitPersonalAccessTokenInput}
          oninput={handleGitTokenInput}
        />

        <p class="text-xs text-slate-500">
          {$t.profile?.git_token_hint ||
            "Token is never returned in plain text. Leave empty to keep current token."}
        </p>

        {#if hasGitPersonalAccessToken}
          <p class="text-xs text-slate-600">
            {$t.profile?.git_token_masked_label || "Current token"}:
            <span class="font-mono">
              {gitPersonalAccessTokenMasked || "***"}
            </span>
          </p>
        {:else}
          <p class="text-xs text-slate-500">
            {$t.profile?.git_token_not_set || "Token is not set"}
          </p>
        {/if}
      </div>
    </section>

    <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?.user_preferences || "User Preferences"}
      </h2>

      <div class="grid gap-4 md:grid-cols-2">
        <label class="block space-y-1">
          <span class="text-sm font-medium text-slate-700">
            {$t.profile?.start_page || "Start Page"}
          </span>
          <select
            class="w-full rounded-lg border border-slate-300 px-3 py-2 text-sm"
            bind:value={startPage}
          >
            <option value="dashboards">
              {$t.profile?.start_page_dashboards || "Dashboards"}
            </option>
            <option value="datasets">
              {$t.profile?.start_page_datasets || "Datasets"}
            </option>
            <option value="reports">
              {$t.profile?.start_page_reports || "Reports / Logs"}
            </option>
          </select>
        </label>

        <label class="block space-y-1">
          <span class="text-sm font-medium text-slate-700">
            {$t.profile?.table_density || "Table Density"}
          </span>
          <select
            class="w-full rounded-lg border border-slate-300 px-3 py-2 text-sm"
            bind:value={dashboardsTableDensity}
          >
            <option value="compact">
              {$t.profile?.table_density_compact || "Compact"}
            </option>
            <option value="comfortable">
              {$t.profile?.table_density_comfortable || "Comfortable"}
            </option>
          </select>
        </label>
      </div>

      <label class="mt-4 flex items-center gap-3">
        <input
          type="checkbox"
          class="h-4 w-4 rounded border-slate-300"
          bind:checked={autoOpenTaskDrawer}
        />
        <span class="text-sm text-slate-700">
          {$t.profile?.auto_open_task_drawer ||
            "Automatically open task drawer for long-running tasks"}
        </span>
      </label>

      <div class="mt-6 space-y-4 border-t border-slate-100 pt-6">
        <h3 class="text-sm font-semibold text-slate-900">
          {$t.profile?.notifications_title || "Smart Notifications"}
        </h3>
        <p class="text-xs text-slate-500">
          {$t.profile?.notifications_description || "Configure where you want to receive alerts for failing dashboards."}
        </p>

        <div class="grid gap-4 md:grid-cols-2">
          <label class="block space-y-1">
            <span class="text-sm font-medium text-slate-700">
              {$t.profile?.telegram_id || "Telegram ID"}
            </span>
            <input
              type="text"
              class="w-full rounded-lg border border-slate-300 px-3 py-2 text-sm"
              placeholder={$t.profile?.telegram_id_placeholder || "e.g. 123456789"}
              bind:value={telegramId}
            />
          </label>

          <label class="block space-y-1">
            <span class="text-sm font-medium text-slate-700">
              {$t.profile?.notification_email || "Notification Email (Override)"}
            </span>
            <input
              type="email"
              class="w-full rounded-lg border border-slate-300 px-3 py-2 text-sm"
              placeholder={$t.profile?.notification_email_placeholder || "Enter override email"}
              bind:value={emailAddress}
            />
          </label>
        </div>

        <label class="flex items-center gap-3">
          <input
            type="checkbox"
            class="h-4 w-4 rounded border-slate-300"
            bind:checked={notifyOnFail}
          />
          <span class="text-sm text-slate-700">
            {$t.profile?.notify_on_fail || "Notify me when my dashboards fail validation"}
          </span>
        </label>
      </div>

      <div class="mt-6 space-y-4 border-t border-slate-100 pt-6">
        <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>

        <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>

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

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

    <div class="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}
</main>

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