import { useEffect, useMemo, useState } from "react";
import { apiGet, apiPost, uploadHomescreenDb } from "../../api";
import { Empty, Loading, PageHead, formatNZ, timeAgo } from "../../components/ui";
import {
  IconCheck,
  IconEmby,
  IconLayers,
  IconRefresh,
  IconSearch,
  IconTrash,
  IconUser,
} from "../../components/icons";
import { useToast } from "../../lib/toast";

interface HomescreenSettings {
  homescreen_db_path: string;
  tmdb_api_key: string;
}

interface UploadedDb {
  upload_id: string;
  filename: string;
  size_bytes: number;
  uploaded_at: string | null;
  sha256: string;
  path: string;
}

interface HomescreenEnums {
  section_types: { value: string; label: string }[];
  collection_types: { value: string; label: string }[];
  item_types: string[];
  sort_options: { value: string; label: string }[];
  image_types: { value: string; label: string }[];
}

interface HomescreenUser {
  id: string | number;
  name: string;
  dbName?: string;
  guid?: string;
  embyGuid?: string;
  embyName?: string | null;
  sections: Record<string, any>[];
  details?: {
    sourceTable?: string | null;
    lastLoginDate?: string | null;
    lastActivityDate?: string | null;
    importedCollectionsCount?: number;
  };
  match?: {
    ok?: boolean;
    mismatchedSectionUserIds?: string[];
    missingSectionUserIds?: number;
  };
}

interface DbReadPayload {
  users: HomescreenUser[];
  validation: {
    userSource: string | null;
    userCount: number;
    settingsCount: number;
    matchedUsers: number;
    mismatchedUsers: number;
    normalizedUsers: number;
    missingSectionUserIds: number;
    orphanedSettingsUserIds: string[];
    embyCacheMatchedUsers?: number;
    embyCacheUserCount?: number;
    embyCacheLastSyncedAt?: string | null;
  };
  source?: {
    mode: "upload" | "path";
    db_path: string;
    upload?: UploadedDb | null;
  };
}

interface EmbyUsersPayload {
  users: { embyGuid: string; name: string }[];
  source: "live" | "cache";
  lastSyncedAt: string | null;
  message?: string;
}

interface UserContextPayload {
  views: { id: string; name: string; type: string }[];
  recentlyPlayed: { id: string; name: string; type: string; seriesName?: string | null; datePlayed?: string | null }[];
  excludedFolderLookup: Record<string, { name: string; type: string }>;
  source: "live" | "cache";
  lastSyncedAt?: string | null;
  message?: string;
}

function makeId() {
  return crypto.randomUUID().replace(/-/g, "").slice(0, 32);
}

function createEmptySection(userId: string) {
  return {
    UserId: userId,
    Name: "New Section",
    CustomName: "New Section",
    Id: makeId(),
    SectionType: "items",
    ImageType: "Thumb",
    CollectionType: "movies",
    SortBy: "Random",
    SortOrder: "Descending",
    Monitor: [],
    ItemTypes: ["Movie"],
    ExcludedFolders: [],
    CardSizeOffset: 0,
    IncludeNextUpInResume: true,
    Query: {
      StudioIds: [],
      TagIds: [],
      GenreIds: [],
      CollectionTypes: [],
      IsPlayed: false,
    },
  };
}

function createRecentlyWatchedSection(userId: string, userName = "") {
  const label = userName ? `Recently Watched - ${userName}` : "Recently Watched";
  return {
    UserId: userId,
    Name: label,
    CustomName: label,
    Id: makeId(),
    SectionType: "items",
    ImageType: "Thumb",
    CollectionType: "",
    SortBy: "DatePlayed",
    SortOrder: "Descending",
    Monitor: [],
    ItemTypes: ["Movie", "Series"],
    ExcludedFolders: [],
    CardSizeOffset: 0,
    IncludeNextUpInResume: true,
    Query: {
      StudioIds: [],
      TagIds: [],
      GenreIds: [],
      CollectionTypes: [],
      IsPlayed: true,
    },
  };
}

function createCollectionSection(userId: string) {
  return {
    UserId: userId,
    Name: "New Collection",
    CustomName: "New Collection",
    Id: makeId(),
    SectionType: "boxset",
    ImageType: "Thumb",
    ItemTypes: [],
    SortBy: "Random",
    SortOrder: "Descending",
    Monitor: [],
    ExcludedFolders: [],
    CardSizeOffset: 0,
    IncludeNextUpInResume: true,
    ParentItem: {
      Name: "New Collection",
      Id: "",
    },
    ParentId: "",
  };
}

function cloneSectionsForTarget(sections: Record<string, any>[], targetGuid: string, mode: "append" | "replace", existing: Record<string, any>[]) {
  const cloned = sections.map((section) => ({
    ...JSON.parse(JSON.stringify(section)),
    UserId: targetGuid,
    Id: makeId(),
  }));
  return mode === "replace" ? cloned : [...existing, ...cloned];
}

export default function HomescreenEditor() {
  const toast = useToast();
  const [settings, setSettings] = useState<HomescreenSettings | null>(null);
  const [enums, setEnums] = useState<HomescreenEnums | null>(null);
  const [users, setUsers] = useState<HomescreenUser[]>([]);
  const [originalUsers, setOriginalUsers] = useState<HomescreenUser[]>([]);
  const [validation, setValidation] = useState<DbReadPayload["validation"] | null>(null);
  const [selectedUserId, setSelectedUserId] = useState<string>("");
  const [selectedSectionIndex, setSelectedSectionIndex] = useState(0);
  const [sectionJson, setSectionJson] = useState("");
  const [sqlPreview, setSqlPreview] = useState("");
  const [search, setSearch] = useState("");
  const [loading, setLoading] = useState(true);
  const [busy, setBusy] = useState(false);
  const [savingSettings, setSavingSettings] = useState(false);
  const [userContext, setUserContext] = useState<UserContextPayload | null>(null);
  const [contextBusy, setContextBusy] = useState(false);
  const [syncSourceId, setSyncSourceId] = useState("");
  const [syncTargetIds, setSyncTargetIds] = useState<string[]>([]);
  const [syncMode, setSyncMode] = useState<"append" | "replace">("append");
  const [uploadedDb, setUploadedDb] = useState<UploadedDb | null>(null);
  const [uploadingDb, setUploadingDb] = useState(false);

  useEffect(() => {
    async function load() {
      setLoading(true);
      try {
        const [allSettings, enumPayload, dbSource] = await Promise.all([
          apiGet<any>("/api/settings"),
          apiGet<HomescreenEnums>("/api/homescreen/enums"),
          apiGet<{ upload: UploadedDb | null }>("/api/homescreen/db-source"),
        ]);
        setSettings({
          homescreen_db_path: allSettings.homescreen_db_path || "",
          tmdb_api_key: allSettings.tmdb_api_key || "",
        });
        setEnums(enumPayload);
        setUploadedDb(dbSource.upload || null);
      } catch (e: any) {
        toast(e.message, "err");
      } finally {
        setLoading(false);
      }
    }
    load();
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  const selectedUser = useMemo(
    () => users.find((user) => String(user.id) === selectedUserId) || null,
    [users, selectedUserId]
  );
  const selectedSection = selectedUser?.sections?.[selectedSectionIndex] || null;
  const filteredUsers = useMemo(() => {
    const needle = search.trim().toLowerCase();
    if (!needle) return users;
    return users.filter((user) =>
      [user.name, user.dbName, user.embyName, user.embyGuid].some((value) => String(value || "").toLowerCase().includes(needle))
    );
  }, [users, search]);
  const changes = useMemo(() => {
    const originalLookup = new Map(originalUsers.map((user) => [String(user.id), user]));
    return users
      .filter((user) => JSON.stringify(user.sections || []) !== JSON.stringify(originalLookup.get(String(user.id))?.sections || []))
      .map((user) => ({ userId: user.id, sections: user.sections, name: user.name }));
  }, [originalUsers, users]);

  useEffect(() => {
    if (!selectedUser) return;
    if (!selectedUser.sections.length) {
      setSelectedSectionIndex(0);
      setSectionJson("");
      return;
    }
    if (selectedSectionIndex >= selectedUser.sections.length) {
      setSelectedSectionIndex(0);
    }
  }, [selectedSectionIndex, selectedUser]);

  useEffect(() => {
    setSectionJson(selectedSection ? JSON.stringify(selectedSection, null, 2) : "");
  }, [selectedSection]);

  useEffect(() => {
    async function loadContext() {
      if (!selectedUser?.embyGuid) {
        setUserContext(null);
        return;
      }
      const excludedIds = ((selectedSection?.ExcludedFolders as string[]) || []).join(",");
      setContextBusy(true);
      try {
        const payload = await apiGet<UserContextPayload>(
          `/api/homescreen/user-context?embyGuid=${encodeURIComponent(selectedUser.embyGuid)}${excludedIds ? `&excludedIds=${encodeURIComponent(excludedIds)}` : ""}`
        );
        setUserContext(payload);
      } catch (e: any) {
        setUserContext({
          views: [],
          recentlyPlayed: [],
          excludedFolderLookup: {},
          source: "cache",
          message: e.message,
        });
      } finally {
        setContextBusy(false);
      }
    }
    loadContext();
  }, [selectedSection?.ExcludedFolders, selectedUser?.embyGuid]);

  function patchSettings<K extends keyof HomescreenSettings>(key: K, value: HomescreenSettings[K]) {
    setSettings((current) => (current ? { ...current, [key]: value } : current));
  }

  async function saveEditorSettings() {
    if (!settings) return;
    setSavingSettings(true);
    try {
      await apiPost("/api/settings", settings);
      toast("Homescreen editor settings saved", "ok");
    } catch (e: any) {
      toast(e.message, "err");
    } finally {
      setSavingSettings(false);
    }
  }

  async function loadFromDb() {
    if (!uploadedDb && !settings?.homescreen_db_path) {
      toast("Upload a users.db extract or set a fallback path first", "err");
      return;
    }
    setBusy(true);
    try {
      const payload = await apiPost<DbReadPayload>("/api/homescreen/db-read", {
        dbPath: settings?.homescreen_db_path,
        uploadId: uploadedDb?.upload_id || null,
      });
      setUsers(payload.users);
      setOriginalUsers(JSON.parse(JSON.stringify(payload.users)));
      setValidation(payload.validation);
      setUploadedDb(payload.source?.upload || uploadedDb || null);
      const firstUser = payload.users.find((user) => user.sections?.length > 0) || payload.users[0];
      setSelectedUserId(firstUser ? String(firstUser.id) : "");
      setSelectedSectionIndex(0);
      setSyncSourceId(firstUser ? String(firstUser.id) : "");
      toast(`Loaded ${payload.users.length} user(s) from ${payload.source?.mode === "upload" ? "the uploaded users.db" : "users.db path"}`, "ok");
    } catch (e: any) {
      toast(e.message, "err");
    } finally {
      setBusy(false);
    }
  }

  async function handleDbUpload(file: File | null) {
    if (!file) return;
    setUploadingDb(true);
    try {
      const payload = await uploadHomescreenDb(file);
      setUploadedDb(payload.upload);
      toast(`Uploaded ${payload.upload.filename}`, "ok");
    } catch (e: any) {
      toast(e.message, "err");
    } finally {
      setUploadingDb(false);
    }
  }

  async function refreshEmbyNames() {
    setBusy(true);
    try {
      const payload = await apiGet<EmbyUsersPayload>("/api/homescreen/emby-users");
      const nameMap = new Map(payload.users.map((user) => [user.embyGuid, user.name]));
      setUsers((current) =>
        current.map((user) => {
          const name = user.embyGuid ? nameMap.get(String(user.embyGuid).toLowerCase()) : null;
          return name ? { ...user, name, embyName: name } : user;
        })
      );
      setOriginalUsers((current) =>
        current.map((user) => {
          const name = user.embyGuid ? nameMap.get(String(user.embyGuid).toLowerCase()) : null;
          return name ? { ...user, name, embyName: name } : user;
        })
      );
      toast(payload.message || `Loaded ${payload.users.length} Emby user name(s) from ${payload.source}`, "ok");
    } catch (e: any) {
      toast(e.message, "err");
    } finally {
      setBusy(false);
    }
  }

  function replaceSelectedUser(nextUser: HomescreenUser) {
    setUsers((current) => current.map((user) => (String(user.id) === String(nextUser.id) ? nextUser : user)));
  }

  function updateSelectedSection(mutator: (section: Record<string, any>) => Record<string, any>) {
    if (!selectedUser || !selectedSection) return;
    const nextSections = selectedUser.sections.map((section, index) => (index === selectedSectionIndex ? mutator(JSON.parse(JSON.stringify(section))) : section));
    replaceSelectedUser({ ...selectedUser, sections: nextSections });
  }

  function addSection(kind: "empty" | "recent" | "collection") {
    if (!selectedUser) return;
    const userGuid = selectedUser.embyGuid || "";
    const next =
      kind === "recent"
        ? createRecentlyWatchedSection(userGuid, selectedUser.name)
        : kind === "collection"
          ? createCollectionSection(userGuid)
          : createEmptySection(userGuid);
    const nextSections = [...(selectedUser.sections || []), next];
    replaceSelectedUser({ ...selectedUser, sections: nextSections });
    setSelectedSectionIndex(nextSections.length - 1);
  }

  function moveSection(direction: -1 | 1) {
    if (!selectedUser || !selectedSection) return;
    const nextIndex = selectedSectionIndex + direction;
    if (nextIndex < 0 || nextIndex >= selectedUser.sections.length) return;
    const nextSections = [...selectedUser.sections];
    [nextSections[selectedSectionIndex], nextSections[nextIndex]] = [nextSections[nextIndex], nextSections[selectedSectionIndex]];
    replaceSelectedUser({ ...selectedUser, sections: nextSections });
    setSelectedSectionIndex(nextIndex);
  }

  function removeSection() {
    if (!selectedUser || !selectedSection) return;
    const nextSections = selectedUser.sections.filter((_, index) => index !== selectedSectionIndex);
    replaceSelectedUser({ ...selectedUser, sections: nextSections });
    setSelectedSectionIndex(Math.max(0, selectedSectionIndex - 1));
  }

  function applySectionJson() {
    if (!selectedUser) return;
    try {
      const parsed = JSON.parse(sectionJson);
      if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("Section JSON must be an object.");
      updateSelectedSection(() => parsed);
      toast("Section JSON applied", "ok");
    } catch (e: any) {
      toast(e.message, "err");
    }
  }

  function toggleItemType(itemType: string) {
    updateSelectedSection((section) => {
      const current = Array.isArray(section.ItemTypes) ? section.ItemTypes : [];
      return {
        ...section,
        ItemTypes: current.includes(itemType) ? current.filter((value: string) => value !== itemType) : [...current, itemType],
      };
    });
  }

  async function previewSql() {
    try {
      const payload = await apiPost<{ sql: string }>("/api/homescreen/sql-preview", { users, originalUsers });
      setSqlPreview(payload.sql);
    } catch (e: any) {
      toast(e.message, "err");
    }
  }

  async function writeToDb() {
    if ((!uploadedDb && !settings?.homescreen_db_path) || !changes.length) return;
    if (!window.confirm(`Write homescreen changes for ${changes.length} user(s) directly to the Emby database?\n\nStop Emby first for safety.`)) return;
    setBusy(true);
    try {
      const payload = await apiPost<{ count: number; normalizedSections: number; source?: { upload?: UploadedDb | null } }>("/api/homescreen/db-write", {
        dbPath: settings?.homescreen_db_path,
        uploadId: uploadedDb?.upload_id || null,
        changes,
      });
      setOriginalUsers(JSON.parse(JSON.stringify(users)));
      setValidation((current) => current ? { ...current, normalizedUsers: payload.normalizedSections } : current);
      setUploadedDb(payload.source?.upload || uploadedDb || null);
      toast(`Wrote ${payload.count} user(s) to ${uploadedDb ? "the uploaded users.db" : "users.db"}`, "ok");
    } catch (e: any) {
      toast(e.message, "err");
    } finally {
      setBusy(false);
    }
  }

  function performSync() {
    if (!syncSourceId || !syncTargetIds.length) return;
    const source = users.find((user) => String(user.id) === syncSourceId);
    if (!source) return;
    setUsers((current) =>
      current.map((user) => {
        if (!syncTargetIds.includes(String(user.id)) || !user.embyGuid) return user;
        return {
          ...user,
          sections: cloneSectionsForTarget(source.sections || [], user.embyGuid || "", syncMode, user.sections || []),
        };
      })
    );
    toast(`Synced ${source.sections.length} section(s) to ${syncTargetIds.length} user(s)`, "ok");
  }

  if (loading || !settings || !enums) return <Loading label="Loading homescreen editor…" />;

  return (
    <>
      <div className="row between" style={{ alignItems: "flex-start" }}>
        <PageHead title="Homescreen Editor" icon={<IconEmby />} />
        <div className="row gap-sm" style={{ flexWrap: "wrap" }}>
          <button className="btn btn-sm" onClick={refreshEmbyNames} disabled={busy}>
            <IconRefresh /> Refresh Emby names
          </button>
          <button className="btn btn-sm" onClick={loadFromDb} disabled={busy || uploadingDb}>
            <IconLayers /> Load from DB
          </button>
          <button className="btn btn-sm" onClick={previewSql} disabled={!users.length}>
            <IconSearch /> Preview SQL
          </button>
          <button className="btn btn-primary" onClick={writeToDb} disabled={busy || uploadingDb || !changes.length}>
            {busy ? <span className="spinner" /> : <IconCheck />} Write to DB
          </button>
        </div>
      </div>

      <div className="workbench" style={{ gridTemplateColumns: "320px 1fr" }}>
        <div className="col">
          <div className="panel">
            <div className="panel-head">
              <h3 className="grow">Editor Settings</h3>
            </div>
            <div className="panel-body col" style={{ gap: 12 }}>
              <div className="field">
                <label className="field-label">Upload users.db extract</label>
                <input
                  className="input"
                  type="file"
                  accept=".db,.sqlite,.sqlite3,application/octet-stream"
                  onChange={(e) => handleDbUpload(e.target.files?.[0] || null)}
                />
              </div>
              {uploadedDb ? (
                <div className="row wrap" style={{ gap: 8 }}>
                  <span className="badge badge-ok">Uploaded source</span>
                  <span className="badge">{uploadedDb.filename}</span>
                  <span className="badge">{Math.round(uploadedDb.size_bytes / 1024)} KB</span>
                  {uploadedDb.uploaded_at ? <span className="badge">Uploaded {uploadedDb.uploaded_at}</span> : null}
                </div>
              ) : null}
              <div className="field">
                <label className="field-label">Fallback users.db path</label>
                <input
                  className="input"
                  value={settings.homescreen_db_path}
                  onChange={(e) => patchSettings("homescreen_db_path", e.target.value)}
                  placeholder="Optional if the app host can read the file directly"
                />
              </div>
              <div className="field">
                <label className="field-label">TMDB API key</label>
                <input className="input" type="password" value={settings.tmdb_api_key} onChange={(e) => patchSettings("tmdb_api_key", e.target.value)} />
              </div>
              <button className="btn btn-sm" onClick={saveEditorSettings} disabled={savingSettings}>
                {savingSettings ? <span className="spinner" /> : <IconCheck />} Save editor settings
              </button>
              <p className="hint" style={{ margin: 0 }}>
                Uploading a <code>users.db</code> extract is the portable Docker-safe flow and works anywhere the browser can reach this app. The fallback path is only for direct host filesystem access.
              </p>
              <p className="hint" style={{ margin: 0 }}>
                Stop Emby before writing to <code>users.db</code>. Typical Windows path: <code>C:\ProgramData\Emby-Server\data\users.db</code>
              </p>
            </div>
          </div>

          <div className="panel">
            <div className="panel-head">
              <h3 className="grow">Users</h3>
              <span className="sub">{filteredUsers.length}</span>
            </div>
            <div className="panel-body col" style={{ gap: 10 }}>
              <div className="field">
                <label className="field-label">Search</label>
                <input className="input" value={search} onChange={(e) => setSearch(e.target.value)} placeholder="Search users or Emby GUID" />
              </div>
              {!filteredUsers.length ? (
                <Empty icon={<IconUser />}>Load the Emby users database to begin.</Empty>
              ) : (
                <div style={{ maxHeight: 520, overflow: "auto" }}>
                  {filteredUsers.map((user) => {
                    const selected = String(user.id) === selectedUserId;
                    return (
                      <button
                        key={String(user.id)}
                        className={`nav-item ${selected ? "active" : ""}`}
                        style={{ width: "100%", justifyContent: "space-between", marginBottom: 6 }}
                        onClick={() => {
                          setSelectedUserId(String(user.id));
                          setSelectedSectionIndex(0);
                        }}
                      >
                        <span style={{ display: "flex", alignItems: "center", gap: 10 }}>
                          <IconUser />
                          <span style={{ textAlign: "left" }}>
                            <div>{user.name}</div>
                            <div className="hint">{user.sections?.length || 0} sections</div>
                          </span>
                        </span>
                        <span className={`badge ${user.match?.ok ? "badge-ok" : "badge-warn"}`}>{user.match?.ok ? "ok" : "fixes"}</span>
                      </button>
                    );
                  })}
                </div>
              )}
            </div>
          </div>
        </div>

        <div className="col">
          {!selectedUser ? (
            <Empty icon={<IconEmby />}>Load a homescreen database and select a user to edit.</Empty>
          ) : (
            <>
              <div className="panel">
                <div className="panel-head">
                  <h3 className="grow">{selectedUser.name}</h3>
                  {selectedUser.details?.lastActivityDate ? <span className="badge">Active {timeAgo(selectedUser.details.lastActivityDate)}</span> : null}
                  {selectedUser.embyGuid ? <span className="badge badge-ok">Linked to Emby</span> : <span className="badge">Unlinked</span>}
                </div>
                <div className="panel-body col" style={{ gap: 12 }}>
                  <div className="row gap-sm" style={{ flexWrap: "wrap" }}>
                    <span className="badge">DB name: {selectedUser.dbName || selectedUser.name}</span>
                    {selectedUser.embyGuid ? <span className="badge">Emby GUID: {selectedUser.embyGuid}</span> : null}
                    {selectedUser.details?.lastLoginDate ? <span className="badge">Last login: {formatNZ(selectedUser.details.lastLoginDate)}</span> : null}
                    {selectedUser.match?.mismatchedSectionUserIds?.length ? <span className="badge badge-warn">Mismatched IDs: {selectedUser.match.mismatchedSectionUserIds.length}</span> : null}
                  </div>
                  <div className="row gap-sm" style={{ flexWrap: "wrap" }}>
                    <button className="btn btn-sm" onClick={() => addSection("empty")}><IconLayers /> Add section</button>
                    <button className="btn btn-sm" onClick={() => addSection("collection")}><IconLayers /> Add collection row</button>
                    <button className="btn btn-sm" onClick={() => addSection("recent")}><IconRefresh /> Add recently watched</button>
                  </div>
                </div>
              </div>

              <div className="workbench" style={{ gridTemplateColumns: "340px 1fr" }}>
                <div className="col">
                  <div className="panel">
                    <div className="panel-head">
                      <h3 className="grow">Sections</h3>
                      <span className="sub">{selectedUser.sections.length}</span>
                    </div>
                    <div className="panel-body col" style={{ gap: 8 }}>
                      {!selectedUser.sections.length ? (
                        <Empty icon={<IconLayers />}>No homescreen sections for this user yet.</Empty>
                      ) : (
                        selectedUser.sections.map((section, index) => (
                          <button
                            key={String(section.Id || index)}
                            className={`nav-item ${index === selectedSectionIndex ? "active" : ""}`}
                            style={{ width: "100%", justifyContent: "space-between" }}
                            onClick={() => setSelectedSectionIndex(index)}
                          >
                            <span style={{ textAlign: "left" }}>
                              <div>{section.CustomName || section.Name || "Unnamed section"}</div>
                              <div className="hint">{section.SectionType || "items"}{section.SortBy ? ` · ${section.SortBy}` : ""}</div>
                            </span>
                            <span className="badge">{index + 1}</span>
                          </button>
                        ))
                      )}
                    </div>
                  </div>

                  <div className="panel">
                    <div className="panel-head">
                      <h3 className="grow">Sync Sections</h3>
                    </div>
                    <div className="panel-body col" style={{ gap: 12 }}>
                      <div className="field">
                        <label className="field-label">Source user</label>
                        <select className="input" value={syncSourceId} onChange={(e) => setSyncSourceId(e.target.value)}>
                          <option value="">Choose source…</option>
                          {users.filter((user) => user.sections?.length).map((user) => (
                            <option key={String(user.id)} value={String(user.id)}>{user.name}</option>
                          ))}
                        </select>
                      </div>
                      <div className="field">
                        <label className="field-label">Mode</label>
                        <select className="input" value={syncMode} onChange={(e) => setSyncMode(e.target.value as "append" | "replace")}>
                          <option value="append">Append</option>
                          <option value="replace">Replace</option>
                        </select>
                      </div>
                      <div className="field">
                        <label className="field-label">Targets</label>
                        <div style={{ maxHeight: 180, overflow: "auto", display: "grid", gap: 8 }}>
                          {users.filter((user) => String(user.id) !== syncSourceId).map((user) => (
                            <label key={String(user.id)} className="chip" style={{ justifyContent: "flex-start", cursor: "pointer" }}>
                              <input
                                type="checkbox"
                                checked={syncTargetIds.includes(String(user.id))}
                                onChange={(e) =>
                                  setSyncTargetIds((current) =>
                                    e.target.checked ? [...current, String(user.id)] : current.filter((id) => id !== String(user.id))
                                  )
                                }
                              />{" "}
                              {user.name}
                            </label>
                          ))}
                        </div>
                      </div>
                      <button className="btn btn-sm" onClick={performSync} disabled={!syncSourceId || !syncTargetIds.length}>
                        <IconCheck /> Sync sections
                      </button>
                    </div>
                  </div>
                </div>

                <div className="col">
                  {!selectedSection ? (
                    <Empty icon={<IconLayers />}>Select a section to edit.</Empty>
                  ) : (
                    <>
                      <div className="panel">
                        <div className="panel-head">
                          <h3 className="grow">{selectedSection.CustomName || selectedSection.Name || "Section"}</h3>
                          <button className="btn btn-sm" onClick={() => moveSection(-1)} disabled={selectedSectionIndex === 0}>Up</button>
                          <button className="btn btn-sm" onClick={() => moveSection(1)} disabled={selectedSectionIndex >= selectedUser.sections.length - 1}>Down</button>
                          <button className="btn btn-sm btn-danger" onClick={removeSection}><IconTrash /> Remove</button>
                        </div>
                        <div className="panel-body col" style={{ gap: 14 }}>
                          <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(220px, 1fr))", gap: 14 }}>
                            <div className="field">
                              <label className="field-label">Name</label>
                              <input className="input" value={selectedSection.Name || ""} onChange={(e) => updateSelectedSection((section) => ({ ...section, Name: e.target.value }))} />
                            </div>
                            <div className="field">
                              <label className="field-label">Custom name</label>
                              <input className="input" value={selectedSection.CustomName || ""} onChange={(e) => updateSelectedSection((section) => ({ ...section, CustomName: e.target.value }))} />
                            </div>
                            <div className="field">
                              <label className="field-label">Section type</label>
                              <select className="input" value={selectedSection.SectionType || ""} onChange={(e) => updateSelectedSection((section) => ({ ...section, SectionType: e.target.value }))}>
                                {enums.section_types.map((item) => <option key={item.value} value={item.value}>{item.label}</option>)}
                              </select>
                            </div>
                            <div className="field">
                              <label className="field-label">Image type</label>
                              <select className="input" value={selectedSection.ImageType || ""} onChange={(e) => updateSelectedSection((section) => ({ ...section, ImageType: e.target.value }))}>
                                {enums.image_types.map((item) => <option key={item.value} value={item.value}>{item.label}</option>)}
                              </select>
                            </div>
                            <div className="field">
                              <label className="field-label">Collection type</label>
                              <select className="input" value={selectedSection.CollectionType || ""} onChange={(e) => updateSelectedSection((section) => ({ ...section, CollectionType: e.target.value }))}>
                                {enums.collection_types.map((item) => <option key={item.value} value={item.value}>{item.label}</option>)}
                              </select>
                            </div>
                            <div className="field">
                              <label className="field-label">Sort by</label>
                              <select className="input" value={selectedSection.SortBy || ""} onChange={(e) => updateSelectedSection((section) => ({ ...section, SortBy: e.target.value }))}>
                                {enums.sort_options.map((item) => <option key={item.value} value={item.value}>{item.label}</option>)}
                              </select>
                            </div>
                          </div>

                          <div className="field">
                            <label className="field-label">Item types</label>
                            <div className="row wrap" style={{ gap: 8 }}>
                              {enums.item_types.map((itemType) => (
                                <label key={itemType} className="chip" style={{ cursor: "pointer" }}>
                                  <input type="checkbox" checked={(selectedSection.ItemTypes || []).includes(itemType)} onChange={() => toggleItemType(itemType)} /> {itemType}
                                </label>
                              ))}
                            </div>
                          </div>

                          <div className="row gap-sm" style={{ flexWrap: "wrap" }}>
                            <label className="chip" style={{ cursor: "pointer" }}>
                              <input
                                type="checkbox"
                                checked={!!selectedSection.IncludeNextUpInResume}
                                onChange={(e) => updateSelectedSection((section) => ({ ...section, IncludeNextUpInResume: e.target.checked }))}
                              />{" "}
                              Include Next Up in resume
                            </label>
                            <label className="chip" style={{ cursor: "pointer" }}>
                              <input
                                type="checkbox"
                                checked={!!selectedSection.Query?.IsPlayed}
                                onChange={(e) => updateSelectedSection((section) => ({ ...section, Query: { ...(section.Query || {}), IsPlayed: e.target.checked } }))}
                              />{" "}
                              Played items only
                            </label>
                          </div>

                          {selectedSection.SectionType === "boxset" ? (
                            <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(220px, 1fr))", gap: 14 }}>
                              <div className="field">
                                <label className="field-label">Parent item name</label>
                                <input
                                  className="input"
                                  value={selectedSection.ParentItem?.Name || ""}
                                  onChange={(e) =>
                                    updateSelectedSection((section) => ({
                                      ...section,
                                      ParentItem: { ...(section.ParentItem || {}), Name: e.target.value },
                                    }))
                                  }
                                />
                              </div>
                              <div className="field">
                                <label className="field-label">Parent item / collection ID</label>
                                <input
                                  className="input"
                                  value={selectedSection.ParentId || selectedSection.ParentItem?.Id || ""}
                                  onChange={(e) =>
                                    updateSelectedSection((section) => ({
                                      ...section,
                                      ParentId: e.target.value,
                                      ParentItem: { ...(section.ParentItem || {}), Id: e.target.value },
                                    }))
                                  }
                                />
                              </div>
                            </div>
                          ) : null}

                          <div className="field">
                            <label className="field-label">Section JSON</label>
                            <textarea
                              className="input"
                              value={sectionJson}
                              onChange={(e) => setSectionJson(e.target.value)}
                              style={{ minHeight: 300, fontFamily: "ui-monospace, SFMono-Regular, monospace", resize: "vertical" }}
                            />
                            <div className="row gap-sm" style={{ marginTop: 10 }}>
                              <button className="btn btn-sm" onClick={applySectionJson}><IconCheck /> Apply JSON</button>
                            </div>
                          </div>
                        </div>
                      </div>

                      <div className="panel">
                        <div className="panel-head">
                          <h3 className="grow">Emby Context</h3>
                          {contextBusy ? <span className="spinner" /> : userContext?.source ? <span className="badge">{userContext.source}</span> : null}
                        </div>
                        <div className="panel-body col" style={{ gap: 14 }}>
                          {userContext?.message ? <p className="hint" style={{ margin: 0 }}>{userContext.message}</p> : null}
                          <div>
                            <div className="section-label" style={{ margin: "0 0 8px" }}>Libraries / views</div>
                            <div className="row wrap" style={{ gap: 8 }}>
                              {userContext?.views?.length ? userContext.views.map((view) => <span key={view.id} className="badge">{view.name}</span>) : <span className="hint">No views loaded.</span>}
                            </div>
                          </div>
                          <div>
                            <div className="section-label" style={{ margin: "0 0 8px" }}>Excluded folders in this section</div>
                            <div className="row wrap" style={{ gap: 8 }}>
                              {Object.entries(userContext?.excludedFolderLookup || {}).length ? Object.entries(userContext?.excludedFolderLookup || {}).map(([id, item]) => (
                                <span key={id} className="badge">{item.name}</span>
                              )) : <span className="hint">No excluded folder metadata for this section.</span>}
                            </div>
                          </div>
                          <div>
                            <div className="section-label" style={{ margin: "0 0 8px" }}>Recently played</div>
                            {userContext?.recentlyPlayed?.length ? (
                              <div style={{ maxHeight: 220, overflow: "auto" }}>
                                <table className="data-table">
                                  <thead>
                                    <tr>
                                      <th>Item</th>
                                      <th>Type</th>
                                      <th>Played</th>
                                    </tr>
                                  </thead>
                                  <tbody>
                                    {userContext.recentlyPlayed.slice(0, 20).map((item) => (
                                      <tr key={item.id}>
                                        <td>
                                          <div className="cell-strong">{item.name}</div>
                                          {item.seriesName ? <div className="cell-sub">{item.seriesName}</div> : null}
                                        </td>
                                        <td>{item.type}</td>
                                        <td>{item.datePlayed ? formatNZ(item.datePlayed) : "—"}</td>
                                      </tr>
                                    ))}
                                  </tbody>
                                </table>
                              </div>
                            ) : (
                              <span className="hint">No recently played items loaded.</span>
                            )}
                          </div>
                        </div>
                      </div>
                    </>
                  )}
                </div>
              </div>
            </>
          )}

          {validation ? (
            <div className="panel">
              <div className="panel-head">
                <h3 className="grow">Database Validation</h3>
              </div>
              <div className="panel-body">
                <div className="mini-grid">
                  <div className="mini-stat"><div className="stat-meta"><div className="stat-value">{validation.userCount}</div><div className="stat-label">Users</div></div></div>
                  <div className="mini-stat"><div className="stat-meta"><div className="stat-value">{validation.settingsCount}</div><div className="stat-label">Settings rows</div></div></div>
                  <div className="mini-stat"><div className="stat-meta"><div className="stat-value">{validation.mismatchedUsers}</div><div className="stat-label">Mismatched users</div></div></div>
                  <div className="mini-stat"><div className="stat-meta"><div className="stat-value">{changes.length}</div><div className="stat-label">Pending changes</div></div></div>
                </div>
              </div>
            </div>
          ) : null}

          {sqlPreview ? (
            <div className="panel">
              <div className="panel-head">
                <h3 className="grow">SQL Preview</h3>
              </div>
              <div className="panel-body">
                <div className="console" style={{ maxHeight: 360 }}>
                  <pre style={{ margin: 0, whiteSpace: "pre-wrap" }}>{sqlPreview}</pre>
                </div>
              </div>
            </div>
          ) : null}
        </div>
      </div>
    </>
  );
}
