"use client";

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

import { getAdminSettings, updateAdminSettingsBatch } from "@/api/admin-settings";
import { useOptionalAdminSettingsData } from "@/modules/settings/admin-settings-data-context";
import { WALLET_GROUP, WALLET_KEYS } from "@/modules/settings/settings-keys";
import { useConfirmAction } from "@/hooks/use-confirm-action";
import { Button } from "@/components/ui/button";
import { ConfigDocPage } from "@/modules/config/config-doc-page";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { adminHasAnyPermission } from "@/lib/admin-permissions";
import { PRD_WALLET_ADJUST_MANAGE, PRD_WALLET_RECONCILE_MANAGE } from "@/lib/admin-prd";
import { useAdminProfile } from "@/stores/admin-session";
import { LotteryApiBizError } from "@/types/api/errors";

function minorUnitsToDisplay(n: unknown, decimals = 2): string {
  const num = Number(n);
  if (!Number.isFinite(num)) return "";
  return (num / 100).toFixed(decimals);
}

function displayToMinorUnits(s: string): number | null {
  const normalized = s.trim();
  if (normalized === "") return null;
  const n = Number(normalized);
  if (!Number.isFinite(n)) return null;
  return Math.round(n * 100);
}

interface Draft {
  inMin: string;
  inMax: string;
  outMin: string;
  outMax: string;
}

function draftFromKv(kv: Record<string, unknown>): Draft {
  return {
    inMin: minorUnitsToDisplay(kv[WALLET_KEYS.IN_MIN] ?? 100),
    inMax: minorUnitsToDisplay(kv[WALLET_KEYS.IN_MAX] ?? 0),
    outMin: minorUnitsToDisplay(kv[WALLET_KEYS.OUT_MIN] ?? 100),
    outMax: minorUnitsToDisplay(kv[WALLET_KEYS.OUT_MAX] ?? 0),
  };
}

type WalletConfigDocScreenProps = {
  embedded?: boolean;
};

function validateDraft(draft: Draft, t: ReturnType<typeof useTranslation<["config", "adminUsers", "common"]>>["t"]): string[] {
  const errors: string[] = [];
  const values = {
    inMin: displayToMinorUnits(draft.inMin),
    inMax: displayToMinorUnits(draft.inMax),
    outMin: displayToMinorUnits(draft.outMin),
    outMax: displayToMinorUnits(draft.outMax),
  };

  for (const field of ["inMin", "inMax", "outMin", "outMax"] as const) {
    if (values[field] === null || values[field] < 1) {
      errors.push(t("wallet.validation.amountAtLeastMinorUnit", {
        ns: "config",
        field: t(`wallet.fields.${field}`, { ns: "config" }),
      }));
    }
  }

  if (values.inMin !== null && values.inMax !== null && values.inMax < values.inMin) {
    errors.push(t("wallet.validation.inRangeInvalid", { ns: "config" }));
  }
  if (values.outMin !== null && values.outMax !== null && values.outMax < values.outMin) {
    errors.push(t("wallet.validation.outRangeInvalid", { ns: "config" }));
  }

  return [...new Set(errors)];
}

export function WalletConfigDocScreen({ embedded = false }: WalletConfigDocScreenProps) {
  const { t } = useTranslation(["config", "adminUsers", "common"]);
  const tRef = useRef(t);
  tRef.current = t;
  const shared = useOptionalAdminSettingsData();
  const profile = useAdminProfile();
  const canManage = adminHasAnyPermission(profile?.permissions, [
    PRD_WALLET_RECONCILE_MANAGE,
    PRD_WALLET_ADJUST_MANAGE,
  ]);
  const { request: requestConfirm, ConfirmDialog } = useConfirmAction();
  const [draft, setDraft] = useState<Draft>({
    inMin: "",
    inMax: "",
    outMin: "",
    outMax: "",
  });
  const [saved, setSaved] = useState<Draft>({ inMin: "", inMax: "", outMin: "", outMax: "" });
  const [standaloneLoading, setStandaloneLoading] = useState(!embedded);
  const [saving, setSaving] = useState(false);
  const dirty =
    draft.inMin !== saved.inMin ||
    draft.inMax !== saved.inMax ||
    draft.outMin !== saved.outMin ||
    draft.outMax !== saved.outMax;
  const validationErrors = validateDraft(draft, t);
  const hasValidationError = validationErrors.length > 0;

  const loading = embedded ? (shared?.loading ?? true) : standaloneLoading;

  const loadStandalone = useCallback(async () => {
    setStandaloneLoading(true);
    try {
      const res = await getAdminSettings(WALLET_GROUP);
      const kv: Record<string, unknown> = {};
      for (const item of res.items) {
        kv[item.key] = item.value;
      }
      const d = draftFromKv(kv);
      setDraft(d);
      setSaved(d);
    } catch {
      toast.error(tRef.current("wallet.loadFailed", { ns: "config" }));
    } finally {
      setStandaloneLoading(false);
    }
  }, []);

  useEffect(() => {
    if (!embedded) {
      void loadStandalone();
    }
  }, [embedded, loadStandalone]);

  useEffect(() => {
    if (!embedded || shared?.kv === null || shared?.kv === undefined) {
      return;
    }
    const d = draftFromKv(shared.kv);
    setDraft(d);
    setSaved(d);
  }, [embedded, shared?.kv]);

  const handleChange = (field: keyof Draft, value: string) => {
    setDraft((prev) => ({ ...prev, [field]: value }));
  };

  const handleSave = async () => {
    if (hasValidationError) {
      toast.error(validationErrors[0]);
      return;
    }

    const items = [];
    if (draft.inMin !== saved.inMin) {
      items.push({ key: WALLET_KEYS.IN_MIN, value: displayToMinorUnits(draft.inMin) });
    }
    if (draft.inMax !== saved.inMax) {
      items.push({ key: WALLET_KEYS.IN_MAX, value: displayToMinorUnits(draft.inMax) });
    }
    if (draft.outMin !== saved.outMin) {
      items.push({ key: WALLET_KEYS.OUT_MIN, value: displayToMinorUnits(draft.outMin) });
    }
    if (draft.outMax !== saved.outMax) {
      items.push({ key: WALLET_KEYS.OUT_MAX, value: displayToMinorUnits(draft.outMax) });
    }
    if (items.length === 0) {
      return;
    }

    setSaving(true);
    try {
      await updateAdminSettingsBatch(items);
      const updates: Record<string, unknown> = {};
      for (const item of items) {
        updates[item.key] = item.value;
      }
      shared?.patchKv(updates);
      toast.success(t("wallet.saveSuccess", { ns: "config" }));
      setSaved(draft);
    } catch (error) {
      toast.error(
        error instanceof LotteryApiBizError ? error.message : t("wallet.saveFailed", { ns: "config" }),
      );
    } finally {
      setSaving(false);
    }
  };

  const content = (
    <>
      <div className="grid gap-5 sm:grid-cols-2">
        <div className="space-y-2">
          <Label htmlFor="in-min">{t("wallet.fields.inMin", { ns: "config" })}</Label>
          <Input
            id="in-min"
            type="number"
            min="0"
            step="0.01"
            placeholder={t("wallet.placeholders.min", { ns: "config" })}
            value={draft.inMin}
            onChange={(e) => handleChange("inMin", e.target.value)}
            disabled={!canManage || loading || saving}
            aria-invalid={hasValidationError}
          />
        </div>
        <div className="space-y-2">
          <Label htmlFor="in-max">{t("wallet.fields.inMax", { ns: "config" })}</Label>
          <Input
            id="in-max"
            type="number"
            min="0"
            step="0.01"
            placeholder={t("wallet.placeholders.max", { ns: "config" })}
            value={draft.inMax}
            onChange={(e) => handleChange("inMax", e.target.value)}
            disabled={!canManage || loading || saving}
            aria-invalid={hasValidationError}
          />
        </div>
        <div className="space-y-2">
          <Label htmlFor="out-min">{t("wallet.fields.outMin", { ns: "config" })}</Label>
          <Input
            id="out-min"
            type="number"
            min="0"
            step="0.01"
            placeholder={t("wallet.placeholders.min", { ns: "config" })}
            value={draft.outMin}
            onChange={(e) => handleChange("outMin", e.target.value)}
            disabled={!canManage || loading || saving}
            aria-invalid={hasValidationError}
          />
        </div>
        <div className="space-y-2">
          <Label htmlFor="out-max">{t("wallet.fields.outMax", { ns: "config" })}</Label>
          <Input
            id="out-max"
            type="number"
            min="0"
            step="0.01"
            placeholder={t("wallet.placeholders.max", { ns: "config" })}
            value={draft.outMax}
            onChange={(e) => handleChange("outMax", e.target.value)}
            disabled={!canManage || loading || saving}
            aria-invalid={hasValidationError}
          />
        </div>
      </div>
      {validationErrors.length > 0 && (
        <div className="space-y-1 text-xs text-destructive" role="alert">
          {validationErrors.map((error) => (
            <p key={error}>{error}</p>
          ))}
        </div>
      )}
      <div className="flex items-center gap-4 pt-2">
        <Button
          onClick={() =>
            requestConfirm({
              title: t("wallet.confirmSaveTitle", { ns: "config" }),
              description: t("wallet.confirmSaveDescription", { ns: "config" }),
              confirmLabel: t("confirm.confirmSave", { ns: "common" }),
              onConfirm: () => handleSave(),
            })
          }
          disabled={!canManage || !dirty || hasValidationError || loading || saving}
        >
          {saving ? t("saving", { ns: "adminUsers" }) : t("actions.save", { ns: "adminUsers" })}
        </Button>
        {dirty && (
          <Button variant="outline" onClick={() => setDraft(saved)} disabled={saving}>
            {t("wallet.discard", { ns: "config" })}
          </Button>
        )}
      </div>
      <ConfirmDialog />
    </>
  );

  if (embedded) {
    return content;
  }

  return (
    <ConfigDocPage title={t("wallet.title", { ns: "config" })}>{content}</ConfigDocPage>
  );
}
