"use client";

import { invoke } from "@tauri-apps/api/core";
import { listen } from "@tauri-apps/api/event";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { FaApple, FaLinux, FaWindows } from "react-icons/fa";
import {
  LuChevronRight,
  LuClipboard,
  LuClipboardCheck,
  LuCookie,
  LuCopy,
  LuFingerprint,
  LuGlobe,
  LuGroup,
  LuKey,
  LuLink,
  LuLockOpen,
  LuPlus,
  LuPuzzle,
  LuRefreshCw,
  LuSettings,
  LuShield,
  LuShieldCheck,
  LuTrash2,
  LuUsers,
  LuX,
} from "react-icons/lu";
import { SharedCamoufoxConfigForm } from "@/components/shared-camoufox-config-form";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { ScrollArea } from "@/components/ui/scroll-area";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { WayfernConfigForm } from "@/components/wayfern-config-form";
import { translateBackendError } from "@/lib/backend-errors";
import { getProfileIcon } from "@/lib/browser-utils";
import { formatRelativeTime } from "@/lib/flag-utils";
import { showErrorToast, showSuccessToast } from "@/lib/toast-utils";
import { cn } from "@/lib/utils";
import type {
  BrowserProfile,
  CamoufoxConfig,
  ProfileGroup,
  StoredProxy,
  VpnConfig,
  WayfernConfig,
} from "@/types";

interface ProfileInfoDialogProps {
  isOpen: boolean;
  onClose: () => void;
  profile: BrowserProfile | null;
  storedProxies: StoredProxy[];
  vpnConfigs: VpnConfig[];
  onOpenTrafficDialog?: (profileId: string) => void;
  onOpenProfileSyncDialog?: (profile: BrowserProfile) => void;
  onAssignProfilesToGroup?: (profileIds: string[]) => void;
  onConfigureCamoufox?: (profile: BrowserProfile) => void;
  onCopyCookiesToProfile?: (profile: BrowserProfile) => void;
  onOpenCookieManagement?: (profile: BrowserProfile) => void;
  onAssignExtensionGroup?: (profileIds: string[]) => void;
  onOpenBypassRules?: (profile: BrowserProfile) => void;
  onOpenDnsBlocklist?: (profile: BrowserProfile) => void;
  onOpenLaunchHook?: (profile: BrowserProfile) => void;
  onCloneProfile?: (profile: BrowserProfile) => void;
  onDeleteProfile?: (profile: BrowserProfile) => void;
  onLaunchWithSync?: (profile: BrowserProfile) => void;
  onSetPassword?: (profile: BrowserProfile) => void;
  onChangePassword?: (profile: BrowserProfile) => void;
  onRemovePassword?: (profile: BrowserProfile) => void;
  crossOsUnlocked?: boolean;
  isRunning?: boolean;
  isDisabled?: boolean;
  isCrossOs?: boolean;
  syncStatuses: Record<string, { status: string; error?: string }>;
}

function _OSIcon({ os }: { os: string }) {
  switch (os) {
    case "macos":
      return <FaApple className="size-3.5" />;
    case "windows":
      return <FaWindows className="size-3.5" />;
    case "linux":
      return <FaLinux className="size-3.5" />;
    default:
      return null;
  }
}

function InfoCard({ label, value }: { label: string; value: string }) {
  return (
    <div className="rounded-md bg-muted/50 border px-3 py-2.5">
      <p className="text-xs text-muted-foreground">{label}</p>
      <p className="text-sm mt-0.5 truncate">{value}</p>
    </div>
  );
}

function formatBytes(bytes: number): string {
  if (!Number.isFinite(bytes) || bytes <= 0) return "0 B";
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
  if (bytes < 1024 * 1024 * 1024)
    return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
  return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
}

/**
 * Shows the total bytes routed through Donut's local proxy worker for this
 * profile. Only counts traffic flowing through the donut-proxy binary — not
 * the browser's full network usage, hence the "Local" qualifier.
 */
function LocalDataTransferCard({
  profileId,
  t,
}: {
  profileId: string;
  t: (key: string, options?: Record<string, unknown>) => string;
}) {
  type Snapshot = {
    total_bytes_sent: number;
    total_bytes_received: number;
  };
  const [value, setValue] = React.useState<string>("—");

  React.useEffect(() => {
    let mounted = true;
    const fetchSnapshot = async () => {
      try {
        const snap = await invoke<Snapshot | null>(
          "get_profile_traffic_snapshot",
          { profileId },
        );
        if (!mounted) return;
        if (!snap) {
          setValue("0 B");
          return;
        }
        setValue(
          formatBytes(snap.total_bytes_sent + snap.total_bytes_received),
        );
      } catch {
        if (mounted) setValue("—");
      }
    };
    void fetchSnapshot();
    const interval = window.setInterval(fetchSnapshot, 5000);
    return () => {
      mounted = false;
      window.clearInterval(interval);
    };
  }, [profileId]);

  return (
    <InfoCard label={t("profileInfo.fields.localDataTransfer")} value={value} />
  );
}

export function ProfileInfoDialog({
  isOpen,
  onClose,
  profile,
  storedProxies,
  vpnConfigs,
  onOpenTrafficDialog,
  onOpenProfileSyncDialog,
  onAssignProfilesToGroup,
  onConfigureCamoufox,
  onCopyCookiesToProfile,
  onOpenCookieManagement,
  onAssignExtensionGroup,
  onOpenBypassRules,
  onOpenDnsBlocklist,
  onOpenLaunchHook,
  onCloneProfile,
  onDeleteProfile,
  onLaunchWithSync,
  onSetPassword,
  onChangePassword,
  onRemovePassword,
  crossOsUnlocked = false,
  isRunning = false,
  isDisabled = false,
  isCrossOs = false,
  syncStatuses,
}: ProfileInfoDialogProps) {
  const { t } = useTranslation();
  const [copied, setCopied] = React.useState(false);
  const [groupName, setGroupName] = React.useState<string | null>(null);
  const [extensionGroupName, setExtensionGroupName] = React.useState<
    string | null
  >(null);

  React.useEffect(() => {
    if (!isOpen || !profile?.group_id) {
      setGroupName(null);
      return;
    }
    void (async () => {
      try {
        const groups = await invoke<ProfileGroup[]>("get_groups");
        const group = groups.find((g) => g.id === profile.group_id);
        setGroupName(group?.name ?? null);
      } catch {
        setGroupName(null);
      }
    })();
  }, [isOpen, profile?.group_id]);

  React.useEffect(() => {
    if (!isOpen || !profile?.extension_group_id) {
      setExtensionGroupName(null);
      return;
    }
    void (async () => {
      try {
        const group = await invoke<{ name: string } | null>(
          "get_extension_group_for_profile",
          { profileId: profile.id },
        );
        setExtensionGroupName(group?.name ?? null);
      } catch {
        setExtensionGroupName(null);
      }
    })();
  }, [isOpen, profile?.extension_group_id, profile?.id]);

  React.useEffect(() => {
    if (!isOpen) {
      setCopied(false);
    }
  }, [isOpen]);

  if (!profile) return null;

  const ProfileIcon = getProfileIcon(profile);
  const isCamoufoxOrWayfern =
    profile.browser === "camoufox" || profile.browser === "wayfern";
  const isDeleteDisabled = isRunning;

  const proxyName = profile.proxy_id
    ? storedProxies.find((p) => p.id === profile.proxy_id)?.name
    : null;
  const vpnName = profile.vpn_id
    ? vpnConfigs.find((v) => v.id === profile.vpn_id)?.name
    : null;
  const networkLabel = vpnName
    ? `VPN: ${vpnName}`
    : proxyName
      ? `Proxy: ${proxyName}`
      : t("profileInfo.values.none");

  const syncStatus = syncStatuses[profile.id];
  const syncMode = profile.sync_mode ?? "Disabled";

  const handleCopyId = async () => {
    try {
      await navigator.clipboard.writeText(profile.id);
      setCopied(true);
      setTimeout(() => {
        setCopied(false);
      }, 2000);
    } catch {
      // ignore
    }
  };

  const handleAction = (action: () => void) => {
    onClose();
    action();
  };

  const hasTags = profile.tags && profile.tags.length > 0;
  const hasNote = !!profile.note;

  // Items in the settings tab `actions` list MUST only open another dialog
  // (or trigger a navigation/action that closes this one). Do NOT put inline
  // settings UI — inputs, toggles, save buttons — directly in this dialog's
  // settings tab. Each setting belongs in its own focused dialog (see
  // `ProfileLaunchHookDialog`, `ProfileBypassRulesDialog`,
  // `ProfileDnsBlocklistDialog` for the pattern). The settings tab is purely
  // a navigation hub.
  interface ActionItem {
    icon: React.ReactNode;
    label: string;
    onClick: () => void;
    disabled?: boolean;
    destructive?: boolean;
    proBadge?: boolean;
    runningBadge?: boolean;
    hidden?: boolean;
  }

  const actions: ActionItem[] = [
    {
      icon: <LuGlobe className="size-4" />,
      label: t("profiles.actions.viewNetwork"),
      onClick: () => {
        handleAction(() => onOpenTrafficDialog?.(profile.id));
      },
      disabled: isCrossOs,
    },
    {
      icon: <LuRefreshCw className="size-4" />,
      label: t("profiles.actions.syncSettings"),
      onClick: () => {
        handleAction(() => onOpenProfileSyncDialog?.(profile));
      },
      disabled: isCrossOs,
      hidden: profile.ephemeral === true,
    },
    {
      icon: <LuGroup className="size-4" />,
      label: t("profiles.actions.assignToGroup"),
      onClick: () => {
        handleAction(() => onAssignProfilesToGroup?.([profile.id]));
      },
      disabled: isDisabled,
      runningBadge: isRunning,
    },
    {
      icon: <LuFingerprint className="size-4" />,
      label: t("profiles.actions.changeFingerprint"),
      onClick: () => {
        handleAction(() => onConfigureCamoufox?.(profile));
      },
      disabled: isDisabled,
      runningBadge: isRunning,
      hidden: !isCamoufoxOrWayfern || !onConfigureCamoufox,
    },
    {
      icon: <LuUsers className="size-4" />,
      label: t("profiles.synchronizer.launchWithSync"),
      onClick: () => {
        handleAction(() => onLaunchWithSync?.(profile));
      },
      disabled: isDisabled || isRunning || !crossOsUnlocked,
      proBadge: !crossOsUnlocked,
      hidden: profile.browser !== "wayfern" || !onLaunchWithSync,
    },
    {
      icon: <LuCopy className="size-4" />,
      label: t("profiles.actions.copyCookiesToProfile"),
      onClick: () => {
        handleAction(() => onCopyCookiesToProfile?.(profile));
      },
      disabled: isDisabled,
      runningBadge: isRunning,
      hidden:
        !isCamoufoxOrWayfern ||
        profile.ephemeral === true ||
        !onCopyCookiesToProfile,
    },
    {
      icon: <LuCookie className="size-4" />,
      label: t("profileInfo.actions.manageCookies"),
      onClick: () => {
        handleAction(() => onOpenCookieManagement?.(profile));
      },
      disabled: isDisabled,
      runningBadge: isRunning,
      hidden:
        !isCamoufoxOrWayfern ||
        profile.ephemeral === true ||
        !onOpenCookieManagement,
    },
    {
      icon: <LuSettings className="size-4" />,
      label: t("profiles.actions.clone"),
      onClick: () => {
        handleAction(() => onCloneProfile?.(profile));
      },
      disabled: isDisabled,
      runningBadge: isRunning,
      hidden: profile.ephemeral === true,
    },
    {
      icon: <LuPuzzle className="size-4" />,
      label: t("profileInfo.actions.assignExtensionGroup"),
      onClick: () => {
        handleAction(() => onAssignExtensionGroup?.([profile.id]));
      },
      disabled: isDisabled,
      runningBadge: isRunning,
      hidden: profile.ephemeral === true,
    },
    {
      icon: <LuShieldCheck className="size-4" />,
      label: t("profileInfo.network.bypassRulesTitle"),
      onClick: () => {
        handleAction(() => onOpenBypassRules?.(profile));
      },
    },
    {
      icon: <LuShield className="size-4" />,
      label: t("dnsBlocklist.title"),
      onClick: () => {
        handleAction(() => onOpenDnsBlocklist?.(profile));
      },
    },
    {
      icon: <LuLink className="size-4" />,
      label: t("profiles.actions.launchHook"),
      onClick: () => {
        handleAction(() => onOpenLaunchHook?.(profile));
      },
      hidden: !onOpenLaunchHook,
    },
    {
      icon: <LuKey className="size-4" />,
      label: t("profiles.actions.setPassword"),
      onClick: () => {
        handleAction(() => onSetPassword?.(profile));
      },
      disabled: isDisabled || isRunning,
      runningBadge: isRunning,
      hidden:
        profile.password_protected === true ||
        profile.ephemeral === true ||
        !onSetPassword,
    },
    {
      icon: <LuKey className="size-4" />,
      label: t("profiles.actions.changePassword"),
      onClick: () => {
        handleAction(() => onChangePassword?.(profile));
      },
      disabled: isDisabled || isRunning,
      runningBadge: isRunning,
      hidden: profile.password_protected !== true || !onChangePassword,
    },
    {
      icon: <LuLockOpen className="size-4" />,
      label: t("profiles.actions.removePassword"),
      onClick: () => {
        handleAction(() => onRemovePassword?.(profile));
      },
      disabled: isDisabled || isRunning,
      runningBadge: isRunning,
      hidden: profile.password_protected !== true || !onRemovePassword,
      destructive: true,
    },
    {
      icon: <LuTrash2 className="size-4" />,
      label: t("profiles.actions.delete"),
      onClick: () => {
        handleAction(() => onDeleteProfile?.(profile));
      },
      disabled: isDeleteDisabled,
      destructive: true,
    },
  ];

  const visibleActions = actions.filter((a) => !a.hidden);

  return (
    <Dialog
      open={isOpen}
      onOpenChange={(open) => {
        if (!open) onClose();
      }}
    >
      <DialogContent
        hideClose
        className="sm:max-w-3xl w-[720px] max-w-[720px] h-[480px] max-h-[480px] flex flex-col p-0 gap-0 overflow-hidden"
      >
        <ProfileInfoLayout
          profile={profile}
          ProfileIcon={ProfileIcon}
          isRunning={isRunning}
          isDisabled={isDisabled}
          networkLabel={networkLabel}
          groupName={groupName}
          extensionGroupName={extensionGroupName}
          syncMode={syncMode}
          syncStatus={syncStatus}
          storedProxies={storedProxies}
          vpnConfigs={vpnConfigs}
          hasTags={hasTags}
          hasNote={hasNote}
          copied={copied}
          handleCopyId={handleCopyId}
          onClose={onClose}
          onCloneProfile={onCloneProfile}
          onKillProfile={undefined}
          visibleActions={visibleActions}
          t={t}
        />
      </DialogContent>
    </Dialog>
  );
}

interface ProfileInfoLayoutProps {
  profile: BrowserProfile;
  ProfileIcon: React.ComponentType<{ className?: string }>;
  isRunning: boolean;
  isDisabled: boolean;
  networkLabel: string;
  groupName: string | null;
  extensionGroupName: string | null;
  syncMode: string;
  syncStatus: { status: string; error?: string } | undefined;
  hasTags: boolean | undefined;
  hasNote: boolean;
  copied: boolean;
  storedProxies: StoredProxy[];
  vpnConfigs: VpnConfig[];
  handleCopyId: () => Promise<void>;
  onClose: () => void;
  onCloneProfile?: (profile: BrowserProfile) => void;
  onKillProfile?: (profile: BrowserProfile) => void;
  visibleActions: {
    icon: React.ReactNode;
    label: string;
    onClick: () => void;
    disabled?: boolean;
    destructive?: boolean;
    proBadge?: boolean;
    runningBadge?: boolean;
  }[];
  t: (key: string, options?: Record<string, unknown>) => string;
}

type ProfileSection =
  | "overview"
  | "fingerprint"
  | "network"
  | "cookies"
  | "extensions"
  | "sync"
  | "automation"
  | "security"
  | "delete";

function ProfileInfoLayout({
  profile,
  ProfileIcon,
  isRunning,
  isDisabled,
  networkLabel,
  groupName,
  extensionGroupName,
  syncMode,
  syncStatus,
  storedProxies,
  vpnConfigs,
  hasTags,
  hasNote,
  copied,
  handleCopyId,
  onClose,
  onCloneProfile,
  visibleActions,
  t,
}: ProfileInfoLayoutProps) {
  const [section, setSection] = React.useState<ProfileSection>("overview");

  // Map sidebar items to existing action labels, so clicking a section
  // simply triggers the existing dialog handler.
  const findAction = React.useCallback(
    (substr: string) =>
      visibleActions.find((a) => a.label.toLowerCase().includes(substr)),
    [visibleActions],
  );

  const deleteAction = findAction("delete");
  const fingerprintAction = findAction("fingerprint");
  const cookiesAction =
    findAction("manage cookies") ?? findAction("copy cookies");
  const extensionAction = findAction("extension");
  const syncAction = findAction("sync");
  const _launchHookAction = findAction("hook") ?? findAction("launch hook");
  const _networkAction = findAction("network");
  // Password actions are no longer routed via the legacy action handlers —
  // SecuritySectionInline writes directly to the backend instead.

  // Cookie count is fetched at the layout level so the sidebar badge can
  // surface it without waiting for the user to open the Cookies section.
  // The effect deps must be primitive — `cookiesAction` is a new object
  // every render and using it directly here caused an infinite re-render
  // loop that froze the entire app when the dialog opened.
  // Skipped while running: the cookie DB is held by the browser and we
  // don't want to compete for its lock from the badge fetch.
  const cookiesSupported = !!cookiesAction;
  const [cookieCount, setCookieCount] = React.useState<number | null>(null);
  React.useEffect(() => {
    if (!cookiesSupported || isRunning) {
      setCookieCount(null);
      return;
    }
    let mounted = true;
    void (async () => {
      try {
        const data = await invoke<{ total_count: number }>(
          "get_profile_cookie_stats",
          { profileId: profile.id },
        );
        if (mounted) setCookieCount(data.total_count);
      } catch {
        if (mounted) setCookieCount(null);
      }
    })();
    return () => {
      mounted = false;
    };
  }, [profile.id, cookiesSupported, isRunning]);

  const sidebarItems: {
    id: ProfileSection;
    icon: React.ReactNode;
    label: string;
    badge?: string;
    destructive?: boolean;
    hidden?: boolean;
  }[] = [
    {
      id: "overview",
      icon: <LuClipboard className="size-3.5" />,
      label: t("profileInfo.sections.overview"),
    },
    {
      id: "fingerprint",
      icon: <LuFingerprint className="size-3.5" />,
      label: t("profileInfo.sections.fingerprint"),
      badge: profile.password_protected
        ? t("profileInfo.badges.locked")
        : undefined,
      hidden: !fingerprintAction,
    },
    {
      id: "network",
      icon: <LuGlobe className="size-3.5" />,
      label: t("profileInfo.sections.network"),
      badge: profile.proxy_id || profile.vpn_id ? networkLabel : undefined,
    },
    {
      id: "cookies",
      icon: <LuCookie className="size-3.5" />,
      label: t("profileInfo.sections.cookies"),
      badge:
        cookieCount !== null && cookieCount > 0
          ? cookieCount.toLocaleString()
          : undefined,
      hidden: !cookiesAction,
    },
    {
      id: "extensions",
      icon: <LuPuzzle className="size-3.5" />,
      label: t("profileInfo.sections.extensions"),
      badge: extensionGroupName ?? undefined,
      hidden: !extensionAction,
    },
    {
      id: "sync",
      icon: <LuRefreshCw className="size-3.5" />,
      label: t("profileInfo.sections.sync"),
      hidden: !syncAction,
    },
    {
      id: "automation",
      icon: <LuLink className="size-3.5" />,
      label: t("profileInfo.sections.launchHook"),
      badge: profile.launch_hook ? t("profileInfo.badges.active") : undefined,
    },
    {
      id: "security",
      icon: <LuKey className="size-3.5" />,
      label: t("profileInfo.sections.security"),
    },
  ];

  return (
    <>
      {/* Top bar */}
      <div className="flex items-center gap-2 h-11 px-3 border-b border-border shrink-0">
        <LuUsers className="size-3.5 text-muted-foreground shrink-0" />
        <div className="flex items-center gap-1.5 text-xs min-w-0 flex-1">
          <span className="font-semibold">
            {t("profileInfo.breadcrumbRoot")}
          </span>
          <span className="text-muted-foreground">/</span>
          <span className="text-muted-foreground truncate">{profile.name}</span>
        </div>
        {onCloneProfile && (
          <Button
            variant="ghost"
            size="sm"
            className="h-7 px-2 text-xs gap-1.5"
            disabled={isDisabled}
            onClick={() => onCloneProfile(profile)}
          >
            <LuCopy className="size-3" />
            {t("profileInfo.duplicate")}
          </Button>
        )}
        <button
          type="button"
          aria-label={t("common.buttons.close")}
          onClick={onClose}
          className="grid place-items-center size-7 rounded-md text-muted-foreground hover:text-foreground hover:bg-accent/50 transition-colors duration-100"
        >
          <LuX className="size-3.5" />
        </button>
      </div>

      {/* Body */}
      <div className="flex flex-1 min-h-0">
        {/* Sidebar */}
        <nav className="w-44 shrink-0 border-r border-border p-2 flex flex-col gap-0.5 overflow-y-auto">
          {sidebarItems
            .filter((it) => !it.hidden)
            .map((it) => {
              const active = section === it.id;
              return (
                <button
                  key={it.id}
                  type="button"
                  onClick={() => setSection(it.id)}
                  className={cn(
                    "flex items-center gap-2 h-7 px-2 rounded-md text-xs transition-colors duration-100 text-left",
                    active
                      ? "bg-accent text-accent-foreground"
                      : "text-muted-foreground hover:text-foreground hover:bg-accent/50",
                  )}
                >
                  <span className="shrink-0">{it.icon}</span>
                  <span className="flex-1 truncate">{it.label}</span>
                  {it.badge && (
                    <span className="text-[9px] uppercase text-muted-foreground tracking-wide truncate max-w-[60px]">
                      {it.badge}
                    </span>
                  )}
                </button>
              );
            })}
          {deleteAction && (
            <>
              <div className="my-1 h-px bg-border" />
              <button
                type="button"
                onClick={deleteAction.onClick}
                disabled={deleteAction.disabled}
                className="flex items-center gap-2 h-7 px-2 rounded-md text-xs transition-colors duration-100 text-destructive hover:bg-destructive/10 disabled:opacity-50 disabled:pointer-events-none"
              >
                <LuTrash2 className="size-3.5 shrink-0" />
                <span className="flex-1 text-left">
                  {t("profileInfo.sections.delete")}
                </span>
              </button>
            </>
          )}
        </nav>

        {/* Main */}
        <div className="flex-1 min-w-0 overflow-y-auto scroll-fade p-4">
          {section === "overview" && (
            <div className="flex flex-col gap-3">
              {/* Hero */}
              <div className="flex items-center gap-3">
                <div className="rounded-lg bg-muted p-2.5 shrink-0">
                  <ProfileIcon className="size-7 text-foreground" />
                </div>
                <div className="min-w-0 flex-1">
                  <div className="flex items-center gap-1.5">
                    <h3 className="text-base font-semibold truncate">
                      {profile.name}
                    </h3>
                  </div>
                  <div className="flex flex-wrap items-center gap-1.5 mt-1 text-[11px]">
                    <span className="font-mono text-muted-foreground">
                      {profile.version}
                    </span>
                  </div>
                </div>
              </div>

              {/* ID */}
              <div className="flex items-center gap-2 rounded-md bg-muted/40 px-3 py-2 border border-border">
                <span className="text-[10px] uppercase tracking-wide text-muted-foreground shrink-0">
                  ID
                </span>
                <span className="font-mono text-xs truncate flex-1">
                  {profile.id}
                </span>
                <button
                  type="button"
                  onClick={() => void handleCopyId()}
                  className="text-muted-foreground hover:text-foreground transition-colors shrink-0"
                  aria-label={t("common.buttons.copy")}
                >
                  {copied ? (
                    <LuClipboardCheck className="size-3.5" />
                  ) : (
                    <LuClipboard className="size-3.5" />
                  )}
                </button>
              </div>

              {/* 2x2 cards */}
              <div className="grid grid-cols-2 gap-2">
                <InfoCard
                  label={t("profileInfo.fields.group")}
                  value={groupName ?? t("profileInfo.values.none")}
                />
                <InfoCard
                  label={t("profileInfo.fields.proxyVpn")}
                  value={networkLabel}
                />
                <InfoCard
                  label={t("profileInfo.fields.tags")}
                  value={
                    hasTags
                      ? (profile.tags ?? []).join(", ")
                      : t("profileInfo.values.none")
                  }
                />
                <InfoCard
                  label={t("profileInfo.fields.note")}
                  value={
                    hasNote
                      ? (profile.note ?? "")
                      : t("profileInfo.values.none")
                  }
                />
              </div>

              {/* Activity */}
              <div className="mt-1 flex flex-col gap-1.5">
                <span className="text-[10px] uppercase tracking-wide text-muted-foreground">
                  {t("profileInfo.sections.activity")}
                </span>
                <div className="grid grid-cols-2 gap-2">
                  <InfoCard
                    label={t("profileInfo.fields.lastLaunched")}
                    value={
                      isRunning
                        ? t("profileInfo.values.activeNow")
                        : profile.last_launch
                          ? formatRelativeTime(profile.last_launch)
                          : t("profileInfo.values.never")
                    }
                  />
                  <LocalDataTransferCard profileId={profile.id} t={t} />
                </div>
              </div>

              {profile.created_by_email && (
                <div className="rounded-md bg-muted/40 border border-border px-3 py-2">
                  <p className="text-[10px] uppercase tracking-wide text-muted-foreground">
                    {t("sync.team.title")}
                  </p>
                  <p className="text-sm mt-0.5">
                    {t("sync.team.createdBy", {
                      email: profile.created_by_email,
                    })}
                  </p>
                </div>
              )}
            </div>
          )}

          {section === "fingerprint" && (
            <FingerprintSectionInline
              profile={profile}
              isDisabled={isDisabled}
              crossOsUnlocked={Boolean(
                // Re-derive: parent passes crossOsUnlocked but the layout
                // doesn't get it; we get it implicitly via fingerprintAction's
                // proBadge state. Default to false if action missing.
                fingerprintAction && !fingerprintAction.proBadge,
              )}
              t={t}
            />
          )}

          {section === "network" && (
            <NetworkSectionInline
              profile={profile}
              storedProxies={storedProxies}
              vpnConfigs={vpnConfigs}
              isDisabled={isDisabled}
              t={t}
            />
          )}

          {section === "cookies" && (
            <CookiesSectionInline
              profile={profile}
              isRunning={isRunning}
              isDisabled={isDisabled}
              t={t}
            />
          )}

          {section === "extensions" && (
            <ExtensionsSectionInline
              profile={profile}
              isDisabled={isDisabled}
              t={t}
            />
          )}

          {section === "sync" && (
            <SyncSectionInline
              profile={profile}
              syncMode={syncMode}
              syncStatus={syncStatus}
              isDisabled={isDisabled}
              t={t}
            />
          )}

          {section === "automation" && (
            <LaunchHookEditor profile={profile} t={t} />
          )}

          {section === "security" && (
            <SecuritySectionInline
              profile={profile}
              isRunning={isRunning}
              t={t}
            />
          )}
        </div>
      </div>
    </>
  );
}

function _SectionPlaceholder({
  icon,
  title,
  description,
  actionLabel,
  onAction,
  disabled,
  hint,
}: {
  icon: React.ReactNode;
  title: string;
  description: string;
  actionLabel: string;
  onAction: () => void;
  disabled?: boolean;
  hint?: string;
}) {
  return (
    <div className="flex flex-col gap-3">
      <div className="flex items-center gap-2 text-sm font-semibold">
        {icon}
        {title}
      </div>
      <p className="text-xs text-muted-foreground">{description}</p>
      {hint && (
        <div className="rounded-md bg-muted/40 border border-border px-3 py-2 text-xs">
          {hint}
        </div>
      )}
      <Button
        size="sm"
        onClick={onAction}
        disabled={disabled}
        className="self-start h-7 text-xs"
      >
        {actionLabel}
      </Button>
    </div>
  );
}

function _SectionAction({
  icon,
  label,
  onClick,
  disabled,
  destructive,
}: {
  icon: React.ReactNode;
  label: string;
  onClick: () => void;
  disabled?: boolean;
  destructive?: boolean;
}) {
  return (
    <button
      type="button"
      disabled={disabled}
      onClick={onClick}
      className={cn(
        "flex items-center gap-2 h-9 px-3 rounded-md text-xs transition-colors text-left",
        destructive
          ? "text-destructive hover:bg-destructive/10"
          : "hover:bg-accent",
        "disabled:opacity-50 disabled:pointer-events-none",
      )}
    >
      {icon}
      <span className="flex-1">{label}</span>
      <LuChevronRight className="size-3.5 text-muted-foreground" />
    </button>
  );
}

function isValidHttpUrl(value: string): boolean {
  const trimmed = value.trim();
  if (!trimmed) return false;
  try {
    const u = new URL(trimmed);
    return u.protocol === "http:" || u.protocol === "https:";
  } catch {
    return false;
  }
}

function LaunchHookEditor({
  profile,
  t,
}: {
  profile: BrowserProfile;
  t: (key: string, options?: Record<string, unknown>) => string;
}) {
  const { t: tFn } = useTranslation();
  const [value, setValue] = React.useState(profile.launch_hook ?? "");
  const [isSaving, setIsSaving] = React.useState(false);
  const [error, setError] = React.useState<string | null>(null);
  const initial = profile.launch_hook ?? "";
  const dirty = value !== initial;
  const trimmed = value.trim();
  const showInvalidHint = trimmed.length > 0 && !isValidHttpUrl(trimmed);

  const onSave = async () => {
    setIsSaving(true);
    setError(null);
    try {
      await invoke("update_profile_launch_hook", {
        profileId: profile.id,
        launchHook: trimmed ? trimmed : null,
      });
    } catch (e) {
      setError(translateBackendError(tFn, e));
    } finally {
      setIsSaving(false);
    }
  };

  return (
    <div className="flex flex-col gap-3">
      <div className="flex items-center gap-2 text-sm font-semibold">
        <LuLink className="size-4" />
        {t("profileInfo.sections.launchHook")}
      </div>
      <p className="text-xs text-muted-foreground">
        {t("profileInfo.sectionDesc.launchHook")}
      </p>
      <Input
        type="url"
        value={value}
        onChange={(e) => {
          setValue(e.target.value);
        }}
        placeholder={t("profiles.launchHook.placeholder")}
        className="text-xs font-mono"
      />
      {showInvalidHint && (
        <p className="text-xs text-warning">
          {t("profileInfo.launchHook.invalidUrlHint")}
        </p>
      )}
      {error && <p className="text-xs text-destructive">{error}</p>}
      <div className="flex items-center gap-2">
        <Button
          size="sm"
          className="h-7 text-xs"
          disabled={!dirty || isSaving || showInvalidHint}
          onClick={() => {
            void onSave();
          }}
        >
          {isSaving ? t("common.buttons.saving") : t("common.buttons.save")}
        </Button>
        {dirty && (
          <Button
            size="sm"
            variant="ghost"
            className="h-7 text-xs"
            onClick={() => {
              setValue(initial);
              setError(null);
            }}
          >
            {t("common.buttons.cancel")}
          </Button>
        )}
      </div>
    </div>
  );
}

function SyncSectionInline({
  profile,
  syncMode,
  syncStatus,
  isDisabled,
  t,
}: {
  profile: BrowserProfile;
  syncMode: string;
  syncStatus: { status: string; error?: string } | undefined;
  isDisabled: boolean;
  t: (key: string, options?: Record<string, unknown>) => string;
}) {
  const [isSaving, setIsSaving] = React.useState(false);
  const [error, setError] = React.useState<string | null>(null);

  const onChangeMode = async (mode: string) => {
    setIsSaving(true);
    setError(null);
    try {
      await invoke("set_profile_sync_mode", {
        profileId: profile.id,
        syncMode: mode,
      });
    } catch (e) {
      setError(String(e));
    } finally {
      setIsSaving(false);
    }
  };

  return (
    <div className="flex flex-col gap-3">
      <div className="flex items-center gap-2 text-sm font-semibold">
        <LuRefreshCw className="size-4" />
        {t("profileInfo.sections.sync")}
      </div>
      <p className="text-xs text-muted-foreground">
        {t("profileInfo.sectionDesc.sync")}
      </p>
      <div className="flex items-center gap-2">
        <span className="text-[10px] uppercase tracking-wide text-muted-foreground shrink-0">
          {t("profileInfo.fields.syncMode")}
        </span>
        <Select
          value={syncMode}
          disabled={isDisabled || isSaving}
          onValueChange={(v) => {
            void onChangeMode(v);
          }}
        >
          <SelectTrigger className="h-7 text-xs flex-1">
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="Disabled">{t("sync.mode.disabled")}</SelectItem>
            <SelectItem value="Regular">{t("sync.mode.regular")}</SelectItem>
            <SelectItem value="Encrypted">
              {t("sync.mode.encrypted")}
            </SelectItem>
          </SelectContent>
        </Select>
      </div>
      {syncStatus && (
        <div className="rounded-md bg-muted/40 border border-border px-3 py-2">
          <p className="text-[10px] uppercase tracking-wide text-muted-foreground">
            {t("profileInfo.fields.syncStatus")}
          </p>
          <p className="text-sm mt-0.5">{syncStatus.status}</p>
          {syncStatus.error && (
            <p className="text-xs text-destructive mt-1">{syncStatus.error}</p>
          )}
        </div>
      )}
      {error && <p className="text-xs text-destructive">{error}</p>}
    </div>
  );
}

function NetworkSectionInline({
  profile,
  storedProxies,
  vpnConfigs,
  isDisabled,
  t,
}: {
  profile: BrowserProfile;
  storedProxies: StoredProxy[];
  vpnConfigs: VpnConfig[];
  isDisabled: boolean;
  t: (key: string, options?: Record<string, unknown>) => string;
}) {
  const [isSaving, setIsSaving] = React.useState(false);
  const [error, setError] = React.useState<string | null>(null);
  // Track the effective selection so the dropdown reflects the last save
  // even before the parent `profile` prop refreshes from a backend event.
  const [proxyId, setProxyId] = React.useState<string | null>(
    profile.proxy_id ?? null,
  );
  const [vpnId, setVpnId] = React.useState<string | null>(
    profile.vpn_id ?? null,
  );

  React.useEffect(() => {
    setProxyId(profile.proxy_id ?? null);
    setVpnId(profile.vpn_id ?? null);
  }, [profile.proxy_id, profile.vpn_id]);

  const onProxyChange = async (value: string) => {
    const nextId = value === "__none__" ? null : value;
    setIsSaving(true);
    setError(null);
    try {
      await invoke("update_profile_proxy", {
        profileId: profile.id,
        proxyId: nextId,
      });
      // Clearing the proxy implicitly clears any VPN binding too on the
      // backend, but we mirror it locally for an immediate visual.
      setProxyId(nextId);
      if (nextId !== null) setVpnId(null);
    } catch (e) {
      setError(String(e));
    } finally {
      setIsSaving(false);
    }
  };

  const onVpnChange = async (value: string) => {
    const nextId = value === "__none__" ? null : value;
    setIsSaving(true);
    setError(null);
    try {
      await invoke("update_profile_vpn", {
        profileId: profile.id,
        vpnId: nextId,
      });
      setVpnId(nextId);
      if (nextId !== null) setProxyId(null);
    } catch (e) {
      setError(String(e));
    } finally {
      setIsSaving(false);
    }
  };

  return (
    <div className="flex flex-col gap-3">
      <div className="flex items-center gap-2 text-sm font-semibold">
        <LuGlobe className="size-4" />
        {t("profileInfo.sections.network")}
      </div>
      <p className="text-xs text-muted-foreground">
        {t("profileInfo.sectionDesc.network")}
      </p>

      <div className="flex items-center gap-2">
        <span className="text-[10px] uppercase tracking-wide text-muted-foreground shrink-0 w-12">
          {t("profileInfo.fields.proxy")}
        </span>
        <Select
          value={proxyId ?? "__none__"}
          disabled={isDisabled || isSaving}
          onValueChange={(v) => {
            void onProxyChange(v);
          }}
        >
          <SelectTrigger className="h-7 text-xs flex-1">
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="__none__">
              {t("profileInfo.values.none")}
            </SelectItem>
            {storedProxies.map((p) => (
              <SelectItem key={p.id} value={p.id}>
                {p.name}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
      </div>

      <div className="flex items-center gap-2">
        <span className="text-[10px] uppercase tracking-wide text-muted-foreground shrink-0 w-12">
          {t("profileInfo.fields.vpn")}
        </span>
        <Select
          value={vpnId ?? "__none__"}
          disabled={isDisabled || isSaving}
          onValueChange={(v) => {
            void onVpnChange(v);
          }}
        >
          <SelectTrigger className="h-7 text-xs flex-1">
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="__none__">
              {t("profileInfo.values.none")}
            </SelectItem>
            {vpnConfigs.map((v) => (
              <SelectItem key={v.id} value={v.id}>
                {v.name}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
      </div>

      {error && <p className="text-xs text-destructive">{error}</p>}
    </div>
  );
}

function ExtensionsSectionInline({
  profile,
  isDisabled,
  t,
}: {
  profile: BrowserProfile;
  isDisabled: boolean;
  t: (key: string, options?: Record<string, unknown>) => string;
}) {
  type ExtensionGroupOption = { id: string; name: string };
  const [groups, setGroups] = React.useState<ExtensionGroupOption[]>([]);
  const [groupId, setGroupId] = React.useState<string | null>(
    profile.extension_group_id ?? null,
  );
  const [isSaving, setIsSaving] = React.useState(false);
  const [error, setError] = React.useState<string | null>(null);

  React.useEffect(() => {
    setGroupId(profile.extension_group_id ?? null);
  }, [profile.extension_group_id]);

  React.useEffect(() => {
    let mounted = true;
    let unlisten: (() => void) | undefined;
    const load = async () => {
      try {
        const data = await invoke<ExtensionGroupOption[]>(
          "list_extension_groups",
        );
        if (mounted) setGroups(data);
      } catch (e) {
        if (mounted) setError(String(e));
      }
    };
    void load();
    void listen("extensions-changed", () => {
      void load();
    }).then((u) => {
      if (mounted) unlisten = u;
      else u();
    });
    return () => {
      mounted = false;
      unlisten?.();
    };
  }, []);

  const onChange = async (value: string) => {
    const next = value === "__none__" ? null : value;
    setIsSaving(true);
    setError(null);
    try {
      await invoke("assign_extension_group_to_profile", {
        profileId: profile.id,
        extensionGroupId: next,
      });
      setGroupId(next);
    } catch (e) {
      setError(String(e));
    } finally {
      setIsSaving(false);
    }
  };

  return (
    <div className="flex flex-col gap-3">
      <div className="flex items-center gap-2 text-sm font-semibold">
        <LuPuzzle className="size-4" />
        {t("profileInfo.sections.extensions")}
      </div>
      <p className="text-xs text-muted-foreground">
        {t("profileInfo.sectionDesc.extensions")}
      </p>
      <div className="flex items-center gap-2">
        <span className="text-[10px] uppercase tracking-wide text-muted-foreground shrink-0 w-16">
          {t("profileInfo.fields.extensionGroup")}
        </span>
        <Select
          value={groupId ?? "__none__"}
          disabled={isDisabled || isSaving}
          onValueChange={(v) => {
            void onChange(v);
          }}
        >
          <SelectTrigger className="h-7 text-xs flex-1">
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="__none__">
              {t("profileInfo.values.none")}
            </SelectItem>
            {groups.map((g) => (
              <SelectItem key={g.id} value={g.id}>
                {g.name}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
      </div>
      {error && <p className="text-xs text-destructive">{error}</p>}
    </div>
  );
}

function CookiesSectionInline({
  profile,
  isRunning,
  t,
}: {
  profile: BrowserProfile;
  isRunning: boolean;
  isDisabled: boolean;
  t: (key: string, options?: Record<string, unknown>) => string;
}) {
  type CookieStats = {
    profile_id: string;
    browser_type: string;
    total_count: number;
    domains: { domain: string; count: number }[];
  };
  const [stats, setStats] = React.useState<CookieStats | null>(null);
  const [isLoading, setIsLoading] = React.useState(!isRunning);
  const [error, setError] = React.useState<string | null>(null);

  React.useEffect(() => {
    if (isRunning) {
      setStats(null);
      setIsLoading(false);
      setError(null);
      return;
    }
    let mounted = true;
    setIsLoading(true);
    setError(null);
    void (async () => {
      try {
        const data = await invoke<CookieStats>("get_profile_cookie_stats", {
          profileId: profile.id,
        });
        if (mounted) setStats(data);
      } catch (e) {
        if (mounted) setError(translateBackendError(t as never, e));
      } finally {
        if (mounted) setIsLoading(false);
      }
    })();
    return () => {
      mounted = false;
    };
  }, [profile.id, isRunning, t]);

  const domains = stats?.domains ?? [];

  return (
    <div className="flex flex-col gap-3 min-h-0 flex-1">
      <div className="flex items-center gap-2 text-sm font-semibold">
        <LuCookie className="size-4" />
        {t("profileInfo.sections.cookies")}
      </div>
      <p className="text-xs text-muted-foreground">
        {t("profileInfo.sectionDesc.cookies")}
      </p>
      {isRunning ? (
        <div className="rounded-md bg-muted/40 border border-border px-3 py-2">
          <p className="text-xs text-muted-foreground">
            {t("profileInfo.cookies.runningNotice")}
          </p>
        </div>
      ) : (
        <>
          <div className="rounded-md bg-muted/40 border border-border px-3 py-2">
            <p className="text-[10px] uppercase tracking-wide text-muted-foreground">
              {t("profileInfo.fields.cookieCount")}
            </p>
            <p className="text-sm mt-0.5">
              {isLoading
                ? t("profileInfo.values.loading")
                : stats
                  ? stats.total_count.toLocaleString()
                  : "—"}
            </p>
          </div>
          {domains.length > 0 && (
            <div className="rounded-md bg-muted/40 border border-border flex flex-col min-h-0 flex-1 overflow-hidden">
              <p className="text-[10px] uppercase tracking-wide text-muted-foreground px-3 py-2 border-b border-border shrink-0">
                {t("profileInfo.cookies.domainsHeader", {
                  count: domains.length,
                })}
              </p>
              <ul className="text-xs px-3 py-2 overflow-y-auto flex-1 space-y-1">
                {domains.map((d) => (
                  <li
                    key={d.domain}
                    className="flex items-center justify-between gap-2"
                  >
                    <span className="truncate font-mono">{d.domain}</span>
                    <span className="text-muted-foreground tabular-nums">
                      {d.count}
                    </span>
                  </li>
                ))}
              </ul>
            </div>
          )}
          {error && <p className="text-xs text-destructive">{error}</p>}
        </>
      )}
    </div>
  );
}

// Inline password set / change / remove form. Replaces three separate
// nested modal dialogs with one in-page form that branches on the current
// `password_protected` state of the profile.
// Inline fingerprint editor. Reuses SharedCamoufoxConfigForm (Camoufox/Firefox
// engine) and WayfernConfigForm (Chromium engine) so the same field set as
// the standalone dialog is available without opening a nested modal.
function FingerprintSectionInline({
  profile,
  isDisabled,
  crossOsUnlocked,
  t,
}: {
  profile: BrowserProfile;
  isDisabled: boolean;
  crossOsUnlocked: boolean;
  t: (key: string, options?: Record<string, unknown>) => string;
}) {
  const [camoufoxConfig, setCamoufoxConfig] = React.useState<CamoufoxConfig>(
    () => profile.camoufox_config ?? {},
  );
  const [wayfernConfig, setWayfernConfig] = React.useState<WayfernConfig>(
    () => profile.wayfern_config ?? {},
  );
  const [isSaving, setIsSaving] = React.useState(false);
  const [error, setError] = React.useState<string | null>(null);
  const [success, setSuccess] = React.useState<string | null>(null);

  // When the underlying profile changes (e.g. a different profile is opened
  // in the dialog) reset the local form state to match.
  React.useEffect(() => {
    setCamoufoxConfig(profile.camoufox_config ?? {});
    setWayfernConfig(profile.wayfern_config ?? {});
    setError(null);
    setSuccess(null);
  }, [profile.camoufox_config, profile.wayfern_config]);

  const isCamoufox = profile.browser === "camoufox";
  const isWayfern = profile.browser === "wayfern";

  if (!isCamoufox && !isWayfern) {
    return (
      <div className="flex flex-col gap-3">
        <div className="flex items-center gap-2 text-sm font-semibold">
          <LuFingerprint className="size-4" />
          {t("profileInfo.sections.fingerprint")}
        </div>
        <p className="text-xs text-muted-foreground">
          {t("profileInfo.fingerprint.notSupported")}
        </p>
      </div>
    );
  }

  const onCamoufoxChange = (key: keyof CamoufoxConfig, value: unknown) => {
    setCamoufoxConfig((prev) => ({ ...prev, [key]: value }));
    setSuccess(null);
  };
  const onWayfernChange = (key: keyof WayfernConfig, value: unknown) => {
    setWayfernConfig((prev) => ({ ...prev, [key]: value }));
    setSuccess(null);
  };

  const onSave = async () => {
    setIsSaving(true);
    setError(null);
    setSuccess(null);
    try {
      if (isCamoufox) {
        await invoke("update_camoufox_config", {
          profileId: profile.id,
          config: camoufoxConfig,
        });
      } else {
        await invoke("update_wayfern_config", {
          profileId: profile.id,
          config: wayfernConfig,
        });
      }
      setSuccess(t("common.buttons.saved"));
    } catch (e) {
      setError(String(e));
    } finally {
      setIsSaving(false);
    }
  };

  const initial = isCamoufox
    ? JSON.stringify(profile.camoufox_config ?? {})
    : JSON.stringify(profile.wayfern_config ?? {});
  const current = isCamoufox
    ? JSON.stringify(camoufoxConfig)
    : JSON.stringify(wayfernConfig);
  const dirty = current !== initial;

  return (
    <div className="flex flex-col gap-3">
      <div className="flex items-center gap-2 text-sm font-semibold">
        <LuFingerprint className="size-4" />
        {t("profileInfo.sections.fingerprint")}
      </div>
      <p className="text-xs text-muted-foreground">
        {t("profileInfo.sectionDesc.fingerprint")}
      </p>

      {isCamoufox && (
        <SharedCamoufoxConfigForm
          config={camoufoxConfig}
          onConfigChange={onCamoufoxChange}
          forceAdvanced={true}
          readOnly={isDisabled}
          browserType="camoufox"
          crossOsUnlocked={crossOsUnlocked}
          limitedMode={false}
          profileVersion={profile.version}
          profileBrowser={profile.browser}
        />
      )}
      {isWayfern && (
        <WayfernConfigForm
          config={wayfernConfig}
          onConfigChange={onWayfernChange}
          forceAdvanced={true}
          readOnly={isDisabled}
          crossOsUnlocked={crossOsUnlocked}
          profileVersion={profile.version}
          profileBrowser={profile.browser}
        />
      )}

      {error && <p className="text-xs text-destructive">{error}</p>}
      {success && !error && <p className="text-xs text-success">{success}</p>}

      <div className="flex items-center gap-2 mt-3 pt-3 border-t border-border">
        <Button
          size="sm"
          className="h-7 text-xs"
          disabled={!dirty || isSaving || isDisabled}
          onClick={() => {
            void onSave();
          }}
        >
          {isSaving ? t("common.buttons.saving") : t("common.buttons.save")}
        </Button>
        {dirty && (
          <Button
            size="sm"
            variant="ghost"
            className="h-7 text-xs"
            onClick={() => {
              setCamoufoxConfig(profile.camoufox_config ?? {});
              setWayfernConfig(profile.wayfern_config ?? {});
              setError(null);
              setSuccess(null);
            }}
          >
            {t("common.buttons.cancel")}
          </Button>
        )}
      </div>
    </div>
  );
}

function SecuritySectionInline({
  profile,
  isRunning,
  t,
}: {
  profile: BrowserProfile;
  isRunning: boolean;
  t: (key: string, options?: Record<string, unknown>) => string;
}) {
  // Mode is implied by current state: unprotected → "set"; protected →
  // "change" by default, with a "remove" alternative.
  type Mode = "set" | "change" | "remove";
  const initialMode: Mode = profile.password_protected ? "change" : "set";
  const [mode, setMode] = React.useState<Mode>(initialMode);
  const [oldPassword, setOldPassword] = React.useState("");
  const [password, setPassword] = React.useState("");
  const [confirm, setConfirm] = React.useState("");
  const [isSubmitting, setIsSubmitting] = React.useState(false);
  const [error, setError] = React.useState<string | null>(null);
  const [success, setSuccess] = React.useState<string | null>(null);
  const [isVerifyOpen, setIsVerifyOpen] = React.useState(false);
  const [verifyPassword, setVerifyPassword] = React.useState("");
  const [isVerifying, setIsVerifying] = React.useState(false);

  const onVerify = async () => {
    setIsVerifying(true);
    try {
      await invoke("verify_profile_password", {
        profileId: profile.id,
        password: verifyPassword,
      });
      showSuccessToast(t("profilePassword.verifyDialog.matchToast"));
      setIsVerifyOpen(false);
      setVerifyPassword("");
    } catch (e) {
      const message = translateBackendError(
        t as unknown as Parameters<typeof translateBackendError>[0],
        e,
      );
      showErrorToast(message);
    } finally {
      setIsVerifying(false);
    }
  };

  // Reset the form whenever the underlying profile state changes (e.g. the
  // user just set a password — flip to "change" mode and clear fields).
  React.useEffect(() => {
    setMode(profile.password_protected ? "change" : "set");
    setOldPassword("");
    setPassword("");
    setConfirm("");
    setError(null);
    setSuccess(null);
  }, [profile.password_protected]);

  const reset = () => {
    setOldPassword("");
    setPassword("");
    setConfirm("");
    setError(null);
  };

  const validate = (): string | null => {
    if (mode === "change" || mode === "remove") {
      if (!oldPassword) return t("profilePassword.errors.passwordRequired");
    }
    if (mode === "set" || mode === "change") {
      if (password.length < 8) return t("profilePassword.errors.tooShort");
      if (password !== confirm)
        return t("profilePassword.errors.passwordMismatch");
    }
    return null;
  };

  const onSubmit = async () => {
    if (isRunning) return;
    const v = validate();
    if (v) {
      setError(v);
      return;
    }
    setIsSubmitting(true);
    setError(null);
    setSuccess(null);
    try {
      if (mode === "set") {
        await invoke("set_profile_password", {
          profileId: profile.id,
          password,
        });
        showSuccessToast(t("profilePassword.toasts.set"));
      } else if (mode === "change") {
        await invoke("change_profile_password", {
          profileId: profile.id,
          oldPassword,
          newPassword: password,
        });
        showSuccessToast(t("profilePassword.toasts.changed"));
      } else {
        await invoke("remove_profile_password", {
          profileId: profile.id,
          password: oldPassword,
        });
        showSuccessToast(t("profilePassword.toasts.removed"));
      }
      reset();
    } catch (e) {
      const message = translateBackendError(
        t as unknown as Parameters<typeof translateBackendError>[0],
        e,
      );
      setError(message);
      showErrorToast(message);
    } finally {
      setIsSubmitting(false);
    }
  };

  return (
    <div className="flex flex-col gap-3">
      <div className="flex items-center gap-2 text-sm font-semibold">
        <LuKey className="size-4" />
        {t("profileInfo.sections.security")}
      </div>
      <p className="text-xs text-muted-foreground">
        {profile.password_protected
          ? t("profileInfo.security.protected")
          : t("profileInfo.security.unprotected")}
      </p>

      {profile.password_protected && (
        <div className="flex gap-1.5">
          <button
            type="button"
            onClick={() => {
              setVerifyPassword("");
              setIsVerifyOpen(true);
            }}
            className={cn(
              "flex-1 h-7 px-2 text-xs rounded-md border transition-colors",
              "border-border text-muted-foreground hover:text-foreground hover:bg-accent/50",
            )}
          >
            {t("profilePassword.modes.validate")}
          </button>
          <button
            type="button"
            onClick={() => {
              setMode("change");
              reset();
            }}
            className={cn(
              "flex-1 h-7 px-2 text-xs rounded-md border transition-colors",
              mode === "change"
                ? "bg-accent text-accent-foreground border-transparent"
                : "border-border text-muted-foreground hover:text-foreground hover:bg-accent/50",
            )}
          >
            {t("profilePassword.modes.change")}
          </button>
          <button
            type="button"
            onClick={() => {
              setMode("remove");
              reset();
            }}
            className={cn(
              "flex-1 h-7 px-2 text-xs rounded-md border transition-colors",
              mode === "remove"
                ? "bg-destructive/10 text-destructive border-transparent"
                : "border-border text-muted-foreground hover:text-foreground hover:bg-accent/50",
            )}
          >
            {t("profilePassword.modes.remove")}
          </button>
        </div>
      )}

      <div className="flex flex-col gap-2">
        {(mode === "change" || mode === "remove") && (
          <Input
            type="password"
            value={oldPassword}
            onChange={(e) => {
              setOldPassword(e.target.value);
              setError(null);
            }}
            placeholder={t("profilePassword.fields.currentPassword")}
            disabled={isRunning || isSubmitting}
            className="h-8 text-xs"
          />
        )}
        {(mode === "set" || mode === "change") && (
          <>
            <Input
              type="password"
              value={password}
              onChange={(e) => {
                setPassword(e.target.value);
                setError(null);
              }}
              placeholder={t("profilePassword.fields.newPassword")}
              disabled={isRunning || isSubmitting}
              className="h-8 text-xs"
            />
            <Input
              type="password"
              value={confirm}
              onChange={(e) => {
                setConfirm(e.target.value);
                setError(null);
              }}
              placeholder={t("profilePassword.fields.confirmPassword")}
              disabled={isRunning || isSubmitting}
              className="h-8 text-xs"
            />
          </>
        )}
      </div>

      {error && <p className="text-xs text-destructive">{error}</p>}
      {success && !error && <p className="text-xs text-success">{success}</p>}

      {isRunning && (
        <p className="text-xs text-muted-foreground">
          {t("profileInfo.security.cannotWhileRunning")}
        </p>
      )}

      <Button
        size="sm"
        variant={mode === "remove" ? "destructive" : "default"}
        className="self-start h-7 text-xs"
        disabled={isRunning || isSubmitting}
        onClick={() => {
          void onSubmit();
        }}
      >
        {mode === "set"
          ? t("profilePassword.modes.set")
          : mode === "change"
            ? t("profilePassword.modes.change")
            : t("profilePassword.modes.remove")}
      </Button>

      <Dialog
        open={isVerifyOpen}
        onOpenChange={(open) => {
          if (!isVerifying) {
            setIsVerifyOpen(open);
            if (!open) setVerifyPassword("");
          }
        }}
      >
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>{t("profilePassword.verifyDialog.title")}</DialogTitle>
            <DialogDescription>
              {t("profilePassword.verifyDialog.description")}
            </DialogDescription>
          </DialogHeader>
          <Input
            type="password"
            placeholder={t("profilePassword.fields.currentPassword")}
            value={verifyPassword}
            autoFocus
            onChange={(e) => setVerifyPassword(e.target.value)}
            onKeyDown={(e) => {
              if (e.key === "Enter" && verifyPassword.length > 0) {
                e.preventDefault();
                void onVerify();
              }
            }}
          />
          <DialogFooter>
            <Button
              variant="outline"
              disabled={isVerifying}
              onClick={() => {
                setIsVerifyOpen(false);
                setVerifyPassword("");
              }}
            >
              {t("common.buttons.cancel")}
            </Button>
            <Button
              disabled={isVerifying || verifyPassword.length === 0}
              onClick={() => void onVerify()}
            >
              {isVerifying
                ? t("common.buttons.loading")
                : t("profilePassword.verifyDialog.submit")}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}

interface ProfileLaunchHookDialogProps {
  isOpen: boolean;
  onClose: () => void;
  profileId: string | null;
  currentLaunchHook: string | null;
}

export function ProfileLaunchHookDialog({
  isOpen,
  onClose,
  profileId,
  currentLaunchHook,
}: ProfileLaunchHookDialogProps) {
  const { t } = useTranslation();
  const [value, setValue] = React.useState(currentLaunchHook ?? "");
  const [isSaving, setIsSaving] = React.useState(false);

  React.useEffect(() => {
    if (isOpen) {
      setValue(currentLaunchHook ?? "");
    }
  }, [isOpen, currentLaunchHook]);

  const trimmed = value.trim();
  const saved = currentLaunchHook ?? "";
  const isDirty = trimmed !== saved;

  const handleSave = async () => {
    if (!profileId) return;
    setIsSaving(true);
    try {
      await invoke("update_profile_launch_hook", {
        profileId,
        launchHook: trimmed || null,
      });
      onClose();
    } catch (err) {
      console.error("Failed to update launch hook:", err);
    } finally {
      setIsSaving(false);
    }
  };

  return (
    <Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>
      <DialogContent className="sm:max-w-md">
        <DialogHeader>
          <DialogTitle>{t("profileInfo.launchHook.title")}</DialogTitle>
        </DialogHeader>
        <p className="text-xs text-muted-foreground">
          {t("profileInfo.launchHook.description")}
        </p>
        <Input
          value={value}
          onChange={(e) => {
            setValue(e.target.value);
          }}
          placeholder={t("profileInfo.launchHook.placeholder")}
          disabled={isSaving}
        />
        <DialogFooter>
          <Button
            onClick={() => void handleSave()}
            disabled={isSaving || !isDirty}
            className="w-full"
          >
            {t("common.buttons.save")}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

interface ProfileDnsBlocklistDialogProps {
  isOpen: boolean;
  onClose: () => void;
  profileId: string | null;
  currentLevel: string | null;
}

export function ProfileDnsBlocklistDialog({
  isOpen,
  onClose,
  profileId,
  currentLevel,
}: ProfileDnsBlocklistDialogProps) {
  const { t } = useTranslation();
  const [level, setLevel] = React.useState(currentLevel ?? "");
  const [isSaving, setIsSaving] = React.useState(false);

  React.useEffect(() => {
    if (isOpen) {
      setLevel(currentLevel ?? "");
    }
  }, [isOpen, currentLevel]);

  const handleSave = async () => {
    if (!profileId) return;
    setIsSaving(true);
    try {
      await invoke("update_profile_dns_blocklist", {
        profileId,
        dnsBlocklist: level || null,
      });
      onClose();
    } catch (err) {
      console.error("Failed to update DNS blocklist:", err);
    } finally {
      setIsSaving(false);
    }
  };

  const options = [
    { value: "", label: t("dnsBlocklist.none") },
    { value: "light", label: t("dnsBlocklist.light") },
    { value: "normal", label: t("dnsBlocklist.normal") },
    { value: "pro", label: t("dnsBlocklist.pro") },
    { value: "pro_plus", label: t("dnsBlocklist.proPlus") },
    { value: "ultimate", label: t("dnsBlocklist.ultimate") },
  ];

  return (
    <Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>
      <DialogContent className="max-w-xs">
        <DialogHeader>
          <DialogTitle>{t("dnsBlocklist.title")}</DialogTitle>
        </DialogHeader>
        <p className="text-xs text-muted-foreground">
          {t("dnsBlocklist.settingsDescription")}{" "}
          <a
            href="https://github.com/hagezi/dns-blocklists"
            target="_blank"
            rel="noopener noreferrer"
            className="text-primary hover:underline"
          >
            {t("common.buttons.moreInfo")}
          </a>
        </p>
        <div className="space-y-1">
          {options.map((option) => (
            <button
              key={option.value}
              type="button"
              onClick={() => setLevel(option.value)}
              className={`w-full text-left px-3 py-2 rounded-md text-sm transition-colors ${
                level === option.value
                  ? "bg-primary/10 text-primary border border-primary/30"
                  : "hover:bg-accent border border-transparent"
              }`}
            >
              {option.label}
            </button>
          ))}
        </div>
        <Button
          onClick={() => void handleSave()}
          disabled={isSaving || level === (currentLevel ?? "")}
          className="w-full"
        >
          {t("common.buttons.save")}
        </Button>
      </DialogContent>
    </Dialog>
  );
}

interface ProfileBypassRulesDialogProps {
  isOpen: boolean;
  onClose: () => void;
  profileId: string | null;
  initialRules?: string[];
}

export function ProfileBypassRulesDialog({
  isOpen,
  onClose,
  profileId,
  initialRules,
}: ProfileBypassRulesDialogProps) {
  const { t } = useTranslation();
  const [bypassRules, setBypassRules] = React.useState<string[]>([]);
  const [newRule, setNewRule] = React.useState("");

  React.useEffect(() => {
    if (isOpen) {
      setBypassRules(initialRules ?? []);
      setNewRule("");
    }
  }, [isOpen, initialRules]);

  const updateBypassRules = async (rules: string[]) => {
    if (!profileId) return;
    try {
      await invoke("update_profile_proxy_bypass_rules", {
        profileId,
        rules,
      });
      setBypassRules(rules);
    } catch {
      // ignore
    }
  };

  const handleAddRule = () => {
    const trimmed = newRule.trim();
    if (!trimmed || bypassRules.includes(trimmed)) return;
    const updated = [...bypassRules, trimmed];
    setNewRule("");
    void updateBypassRules(updated);
  };

  const handleRemoveRule = (rule: string) => {
    void updateBypassRules(bypassRules.filter((r) => r !== rule));
  };

  return (
    <Dialog
      open={isOpen}
      onOpenChange={(open) => {
        if (!open) onClose();
      }}
    >
      <DialogContent className="sm:max-w-lg max-h-[80vh] flex flex-col">
        <DialogHeader className="shrink-0">
          <DialogTitle>{t("profileInfo.network.bypassRulesTitle")}</DialogTitle>
        </DialogHeader>
        <ScrollArea className="flex-1 min-h-0">
          <div className="flex flex-col gap-3 py-2">
            <p className="text-sm text-muted-foreground">
              {t("profileInfo.network.bypassRulesDescription")}
            </p>
            <div className="flex gap-2">
              <Input
                value={newRule}
                onChange={(e) => {
                  setNewRule(e.target.value);
                }}
                onKeyDown={(e) => {
                  if (e.key === "Enter") handleAddRule();
                }}
                placeholder={t("profileInfo.network.rulePlaceholder")}
                className="flex-1 text-sm"
              />
              <Button
                size="sm"
                onClick={handleAddRule}
                disabled={!newRule.trim()}
              >
                <LuPlus className="size-4 mr-1" />
                {t("profileInfo.network.addRule")}
              </Button>
            </div>
            {bypassRules.length === 0 ? (
              <p className="text-sm text-muted-foreground py-2">
                {t("profileInfo.network.noRules")}
              </p>
            ) : (
              <div className="flex flex-col gap-1.5">
                {bypassRules.map((rule) => (
                  <div
                    key={rule}
                    className="flex items-center justify-between gap-2 px-3 py-1.5 rounded-md bg-muted text-sm"
                  >
                    <span className="font-mono text-xs truncate">{rule}</span>
                    <button
                      type="button"
                      onClick={() => {
                        handleRemoveRule(rule);
                      }}
                      className="text-muted-foreground hover:text-destructive transition-colors shrink-0"
                    >
                      <LuX className="size-3.5" />
                    </button>
                  </div>
                ))}
              </div>
            )}
            <p className="text-xs text-muted-foreground">
              {t("profileInfo.network.ruleTypes")}
            </p>
          </div>
        </ScrollArea>
        <DialogFooter className="shrink-0">
          <Button variant="outline" onClick={onClose}>
            {t("common.buttons.close")}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
