"use client";

import { useEffect, useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";

import { updateAdminSettingsBatch, type AdminSettingBatchItem } from "@/api/admin-settings";
import { setCachedApplyRebateToPayoutSetting } from "@/lib/admin-settlement-settings-cache";
import { useAdminSettingsData } from "@/modules/settings/admin-settings-data-context";
import { SETTLEMENT_KEYS } from "@/modules/settings/settings-keys";
import { LotteryApiBizError } from "@/types/api/errors";

export function useSettingsSection<TDraft>(options: {
  initialDraft: TDraft;
  fromKv: (kv: Record<string, unknown>) => TDraft;
  buildDirtyItems: (draft: TDraft, saved: TDraft) => AdminSettingBatchItem[];
  saveSuccessKey: string;
  saveFailedKey: string;
}) {
  const { t } = useTranslation(["config"]);
  const tRef = useRef(t);
  tRef.current = t;

  const { kv, loading, patchKv } = useAdminSettingsData();
  const [draft, setDraft] = useState(options.initialDraft);
  const [saved, setSaved] = useState(options.initialDraft);
  const [saving, setSaving] = useState(false);
  const hydratedRef = useRef(false);

  const { fromKv, buildDirtyItems, saveSuccessKey, saveFailedKey } = options;

  const dirty = useMemo(
    () => buildDirtyItems(draft, saved).length > 0,
    [draft, saved, buildDirtyItems],
  );

  useEffect(() => {
    if (kv === null) {
      return;
    }
    const next = fromKv(kv);
    setDraft(next);
    setSaved(next);
    hydratedRef.current = true;
  }, [kv, fromKv]);

  const updateField = <K extends keyof TDraft>(field: K, value: TDraft[K]) => {
    setDraft((prev) => ({ ...prev, [field]: value }));
  };

  const discard = () => {
    setDraft(saved);
  };

  const save = async (): Promise<boolean> => {
    const items = buildDirtyItems(draft, saved);
    if (items.length === 0) {
      return true;
    }

    setSaving(true);
    try {
      await updateAdminSettingsBatch(items);
      const updates: Record<string, unknown> = {};
      for (const item of items) {
        updates[item.key] = item.value;
        if (item.key === SETTLEMENT_KEYS.APPLY_REBATE_TO_PAYOUT) {
          setCachedApplyRebateToPayoutSetting(Boolean(item.value));
        }
      }
      patchKv(updates);
      setSaved(draft);
      toast.success(tRef.current(saveSuccessKey, { ns: "config" }));
      return true;
    } catch (error) {
      toast.error(
        error instanceof LotteryApiBizError
          ? error.message
          : tRef.current(saveFailedKey, { ns: "config" }),
      );
      return false;
    } finally {
      setSaving(false);
    }
  };

  const sectionLoading = loading || (kv !== null && !hydratedRef.current);

  return {
    draft,
    saved,
    loading: sectionLoading,
    saving,
    dirty,
    updateField,
    discard,
    save,
  };
}
