"use client";

import * as React from "react";
import { useActionState } from "react";
import { useRouter } from "next/navigation";
import { Decimal } from "decimal.js";
import { toast } from "sonner";
import { Calculator, TriangleAlert } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { NativeSelect, NativeSelectOption } from "@/components/ui/native-select";
import { Textarea } from "@/components/ui/textarea";
import { saveServiceAction } from "@/lib/actions/admin-services";
import { adminTexts } from "@/lib/i18n/admin";
import { adminServicesTexts as t } from "@/lib/i18n/admin-services";
import { money } from "@/lib/serialize";
import { cn } from "@/lib/utils";
import {
  SERVICE_TYPE_OPTIONS,
  type AdminActionState,
  type CatalogueOption,
  type CategoryOption,
  type ProviderOption,
  type ServiceFormValues,
} from "./types";

const d = t.dialog;
const MAX_PICKER_OPTIONS = 800;

type SaveState = AdminActionState<{ id: number; warning?: string }>;

function dec(value: string): Decimal {
  try {
    const clean = String(value ?? "").replace(",", ".").trim();
    if (!clean) return new Decimal(0);
    const n = new Decimal(clean);
    return n.isFinite() ? n : new Decimal(0);
  } catch {
    return new Decimal(0);
  }
}

function Field({
  label,
  htmlFor,
  hint,
  error,
  className,
  children,
}: {
  label: string;
  htmlFor?: string;
  hint?: string;
  error?: string;
  className?: string;
  children: React.ReactNode;
}) {
  return (
    <div className={cn("space-y-1.5", className)}>
      <Label htmlFor={htmlFor} className="text-xs font-medium">
        {label}
      </Label>
      {children}
      {error ? (
        <p className="text-[11px] font-medium text-rose-600 dark:text-rose-400">{error}</p>
      ) : hint ? (
        <p className="text-[11px] text-muted-foreground">{hint}</p>
      ) : null}
    </div>
  );
}

function Section({ title, children }: { title: string; children: React.ReactNode }) {
  return (
    <section className="space-y-3 rounded-xl border bg-muted/20 p-3">
      <h3 className="text-[11px] font-semibold tracking-wider text-muted-foreground uppercase">
        {title}
      </h3>
      {children}
    </section>
  );
}

function Toggle({
  name,
  label,
  checked,
  onChange,
}: {
  name: string;
  label: string;
  checked: boolean;
  onChange: (next: boolean) => void;
}) {
  const id = `svc-${name}`;
  return (
    <div className="flex items-center gap-2">
      <Checkbox id={id} checked={checked} onCheckedChange={(v) => onChange(v === true)} />
      <input type="hidden" name={name} value={checked ? "1" : "0"} />
      <Label htmlFor={id} className="cursor-pointer text-xs font-medium">
        {label}
      </Label>
    </div>
  );
}

export function ServiceDialog({
  title,
  initial,
  categories,
  providers,
  catalogue,
  priceDecimals,
  closeHref,
}: {
  title: string;
  initial: ServiceFormValues;
  categories: CategoryOption[];
  providers: ProviderOption[];
  catalogue: CatalogueOption[];
  priceDecimals: number;
  closeHref: string;
}) {
  const router = useRouter();
  const [values, setValues] = React.useState<ServiceFormValues>(initial);
  const [state, formAction, pending] = useActionState<SaveState, FormData>(
    saveServiceAction,
    null,
  );

  const set = React.useCallback(
    <K extends keyof ServiceFormValues>(key: K, value: ServiceFormValues[K]) => {
      setValues((prev) => ({ ...prev, [key]: value }));
    },
    [],
  );

  const close = React.useCallback(() => {
    router.push(closeHref, { scroll: false });
  }, [closeHref, router]);

  React.useEffect(() => {
    if (!state) return;
    if (state.ok) {
      const warning = state.data?.warning;
      if (warning) toast.warning(warning);
      else toast.success(d.savedService);
      router.push(closeHref, { scroll: false });
      router.refresh();
    } else {
      toast.error(state.error);
    }
  }, [state, closeHref, router]);

  const errors = state && state.ok === false ? (state.fieldErrors ?? {}) : {};

  const rate = dec(values.rate);
  const cost = values.cost === "" ? null : dec(values.cost);
  const profit = cost ? rate.minus(cost) : null;
  const margin =
    cost && rate.greaterThan(0) ? rate.minus(cost).div(rate).times(100).toDecimalPlaces(2) : null;
  const belowCost = cost !== null && cost.greaterThan(0) && rate.lessThanOrEqualTo(cost);
  const isPackage = values.type === "PACKAGE";

  const providerPicks = React.useMemo(
    () =>
      values.providerId
        ? catalogue
            .filter((c) => c.providerId === values.providerId)
            .slice(0, MAX_PICKER_OPTIONS)
        : [],
    [catalogue, values.providerId],
  );

  const recalculate = React.useCallback(() => {
    setValues((prev) => {
      if (prev.cost === "") return prev;
      const next = dec(prev.cost)
        .times(new Decimal(1).plus(dec(prev.markupPercent).div(100)))
        .toDecimalPlaces(priceDecimals, Decimal.ROUND_UP);
      return { ...prev, rate: next.toString() };
    });
  }, [priceDecimals]);

  const applyPick = React.useCallback(
    (providerServiceId: string) => {
      const pick = providerPicks.find((c) => c.providerServiceId === providerServiceId);
      if (!pick) {
        set("providerServiceId", providerServiceId);
        return;
      }
      setValues((prev) => {
        const nextRate = dec(pick.rate)
          .times(new Decimal(1).plus(dec(prev.markupPercent).div(100)))
          .toDecimalPlaces(priceDecimals, Decimal.ROUND_UP);
        const type = mapPickType(pick.type, prev.type);
        return {
          ...prev,
          providerServiceId,
          cost: pick.rate,
          rate: nextRate.toString(),
          type,
          min: type === "PACKAGE" ? "1" : String(pick.min),
          max: type === "PACKAGE" ? "1" : String(pick.max),
          refillEnabled: pick.refill,
          cancelEnabled: pick.cancel,
          name: prev.name.trim() === "" ? pick.name : prev.name,
        };
      });
    },
    [priceDecimals, providerPicks, set],
  );

  return (
    <Dialog open onOpenChange={(next) => (next ? null : close())}>
      <DialogContent className="max-h-[90vh] gap-0 overflow-y-auto sm:max-w-3xl">
        <DialogHeader className="pb-3">
          <DialogTitle className="text-base">{title}</DialogTitle>
          <DialogDescription className="text-xs">
            {t.subtitle}
          </DialogDescription>
        </DialogHeader>

        <form action={formAction} className="space-y-3">
          <input type="hidden" name="id" value={values.id} />

          <Section title={d.sectionBasics}>
            <div className="grid gap-3 sm:grid-cols-2">
              <Field
                label={d.name}
                htmlFor="svc-name"
                error={errors.name}
                className="sm:col-span-2"
              >
                <Input
                  id="svc-name"
                  name="name"
                  required
                  maxLength={300}
                  placeholder={d.namePlaceholder}
                  value={values.name}
                  onChange={(e) => set("name", e.target.value)}
                  className="h-8 text-sm"
                />
              </Field>

              <Field label={d.category} htmlFor="svc-category" error={errors.categoryId}>
                <NativeSelect
                  id="svc-category"
                  name="categoryId"
                  required
                  className="w-full"
                  value={values.categoryId}
                  onChange={(e) => set("categoryId", e.target.value)}
                >
                  <NativeSelectOption value="">—</NativeSelectOption>
                  {categories.map((c) => (
                    <NativeSelectOption key={c.id} value={c.id}>
                      {c.name}
                    </NativeSelectOption>
                  ))}
                </NativeSelect>
              </Field>

              <Field label={d.type} htmlFor="svc-type" error={errors.type}>
                <NativeSelect
                  id="svc-type"
                  name="type"
                  className="w-full"
                  value={values.type}
                  onChange={(e) => set("type", e.target.value)}
                >
                  {SERVICE_TYPE_OPTIONS.map((o) => (
                    <NativeSelectOption key={o.value} value={o.value}>
                      {o.label}
                    </NativeSelectOption>
                  ))}
                </NativeSelect>
              </Field>

              <Field label={d.mode} htmlFor="svc-mode" error={errors.mode}>
                <NativeSelect
                  id="svc-mode"
                  name="mode"
                  className="w-full"
                  value={values.mode}
                  onChange={(e) => set("mode", e.target.value)}
                >
                  <NativeSelectOption value="AUTO">{d.modeAuto}</NativeSelectOption>
                  <NativeSelectOption value="MANUAL">{d.modeManual}</NativeSelectOption>
                </NativeSelect>
              </Field>

              <Field label={d.position} htmlFor="svc-position" error={errors.position}>
                <Input
                  id="svc-position"
                  name="position"
                  type="number"
                  min={0}
                  value={values.position}
                  onChange={(e) => set("position", e.target.value)}
                  className="h-8 text-sm"
                />
              </Field>

              <Field
                label={d.description}
                htmlFor="svc-description"
                className="sm:col-span-2"
                error={errors.description}
              >
                <Textarea
                  id="svc-description"
                  name="description"
                  rows={3}
                  maxLength={5000}
                  placeholder={d.descriptionPlaceholder}
                  value={values.description}
                  onChange={(e) => set("description", e.target.value)}
                  className="text-sm"
                />
              </Field>
            </div>
          </Section>

          <Section title={d.sectionProvider}>
            <div className="grid gap-3 sm:grid-cols-2">
              <Field label={d.provider} htmlFor="svc-provider" error={errors.providerId}>
                <NativeSelect
                  id="svc-provider"
                  name="providerId"
                  className="w-full"
                  value={values.providerId}
                  onChange={(e) => set("providerId", e.target.value)}
                >
                  <NativeSelectOption value="">{d.providerNone}</NativeSelectOption>
                  {providers.map((p) => (
                    <NativeSelectOption key={p.id} value={p.id}>
                      {p.name}
                    </NativeSelectOption>
                  ))}
                </NativeSelect>
              </Field>

              <Field
                label={d.providerService}
                htmlFor="svc-pick"
                hint={d.providerServiceHint}
              >
                <NativeSelect
                  id="svc-pick"
                  className="w-full"
                  disabled={!values.providerId || providerPicks.length === 0}
                  value={
                    providerPicks.some((p) => p.providerServiceId === values.providerServiceId)
                      ? values.providerServiceId
                      : ""
                  }
                  onChange={(e) => applyPick(e.target.value)}
                >
                  <NativeSelectOption value="">{d.providerServicePick}</NativeSelectOption>
                  {providerPicks.map((p) => (
                    <NativeSelectOption
                      key={p.providerServiceId}
                      value={p.providerServiceId}
                    >
                      {p.providerServiceId} — {p.name}
                    </NativeSelectOption>
                  ))}
                </NativeSelect>
              </Field>

              <Field
                label={d.providerServiceId}
                htmlFor="svc-psid"
                error={errors.providerServiceId}
              >
                <Input
                  id="svc-psid"
                  name="providerServiceId"
                  maxLength={120}
                  disabled={!values.providerId}
                  value={values.providerServiceId}
                  onChange={(e) => set("providerServiceId", e.target.value)}
                  className="h-8 font-mono text-sm"
                />
              </Field>
            </div>
          </Section>

          <Section title={d.sectionPricing}>
            <div className="grid gap-3 sm:grid-cols-3">
              <Field label={d.cost} htmlFor="svc-cost" error={errors.cost}>
                <Input
                  id="svc-cost"
                  name="cost"
                  inputMode="decimal"
                  placeholder="0.00000"
                  value={values.cost}
                  onChange={(e) => set("cost", e.target.value)}
                  className="h-8 font-mono text-sm"
                />
              </Field>

              <Field label={d.markupPercent} htmlFor="svc-markup" error={errors.markupPercent}>
                <Input
                  id="svc-markup"
                  name="markupPercent"
                  inputMode="decimal"
                  value={values.markupPercent}
                  onChange={(e) => set("markupPercent", e.target.value)}
                  className="h-8 font-mono text-sm"
                />
              </Field>

              <Field label={d.rate} htmlFor="svc-rate" error={errors.rate}>
                <Input
                  id="svc-rate"
                  name="rate"
                  required
                  inputMode="decimal"
                  placeholder="0.00000"
                  value={values.rate}
                  onChange={(e) => set("rate", e.target.value)}
                  className="h-8 font-mono text-sm"
                />
              </Field>
            </div>

            <div className="flex flex-wrap items-center gap-x-5 gap-y-2">
              <Button type="button" size="sm" variant="outline" onClick={recalculate}>
                <Calculator className="size-3.5" />
                {d.recalculate}
              </Button>

              <Toggle
                name="autoUpdatePrice"
                label={d.autoUpdatePrice}
                checked={values.autoUpdatePrice}
                onChange={(v) => set("autoUpdatePrice", v)}
              />

              {profit ? (
                <span className="text-xs text-muted-foreground">
                  {d.profit}{" "}
                  <span
                    className={cn(
                      "font-mono font-medium tabular-nums",
                      profit.greaterThan(0)
                        ? "text-emerald-600 dark:text-emerald-400"
                        : "text-rose-600 dark:text-rose-400",
                    )}
                  >
                    {money(profit.toString())}
                  </span>
                  {margin ? (
                    <span className="ml-2">
                      {d.margin}{" "}
                      <span className="font-mono tabular-nums">{margin.toString()}%</span>
                    </span>
                  ) : null}
                </span>
              ) : null}
            </div>

            {belowCost ? (
              <p className="flex items-center gap-1.5 rounded-lg bg-amber-100 px-2 py-1.5 text-[11px] font-medium text-amber-800 dark:bg-amber-500/15 dark:text-amber-300">
                <TriangleAlert className="size-3.5 shrink-0" />
                {d.belowCostWarning}
              </p>
            ) : null}
          </Section>

          <Section title={d.sectionLimits}>
            <div className="grid gap-3 sm:grid-cols-4">
              <Field label={d.min} htmlFor="svc-min" error={errors.min}>
                <Input
                  id="svc-min"
                  name="min"
                  type="number"
                  min={1}
                  disabled={isPackage}
                  value={isPackage ? "1" : values.min}
                  onChange={(e) => set("min", e.target.value)}
                  className="h-8 font-mono text-sm"
                />
              </Field>
              <Field label={d.max} htmlFor="svc-max" error={errors.max}>
                <Input
                  id="svc-max"
                  name="max"
                  type="number"
                  min={1}
                  disabled={isPackage}
                  value={isPackage ? "1" : values.max}
                  onChange={(e) => set("max", e.target.value)}
                  className="h-8 font-mono text-sm"
                />
              </Field>
              <Field label={d.increment} htmlFor="svc-increment" error={errors.increment}>
                <Input
                  id="svc-increment"
                  name="increment"
                  type="number"
                  min={1}
                  value={values.increment}
                  onChange={(e) => set("increment", e.target.value)}
                  className="h-8 font-mono text-sm"
                />
              </Field>
              <Field
                label={d.overflowPercent}
                htmlFor="svc-overflow"
                error={errors.overflowPercent}
              >
                <Input
                  id="svc-overflow"
                  name="overflowPercent"
                  inputMode="decimal"
                  value={values.overflowPercent}
                  onChange={(e) => set("overflowPercent", e.target.value)}
                  className="h-8 font-mono text-sm"
                />
              </Field>
            </div>
            {isPackage ? (
              <p className="text-[11px] text-muted-foreground">{d.packageHint}</p>
            ) : (
              <p className="text-[11px] text-muted-foreground">{d.incrementHint}</p>
            )}
            {/* Package min/max are locked in the UI but still submitted. */}
            {isPackage ? (
              <>
                <input type="hidden" name="min" value="1" />
                <input type="hidden" name="max" value="1" />
              </>
            ) : null}
          </Section>

          <Section title={d.sectionFeatures}>
            <div className="grid gap-2.5 sm:grid-cols-3">
              <Toggle
                name="dripfeedEnabled"
                label={d.dripfeedEnabled}
                checked={values.dripfeedEnabled}
                onChange={(v) => set("dripfeedEnabled", v)}
              />
              <Toggle
                name="cancelEnabled"
                label={d.cancelEnabled}
                checked={values.cancelEnabled}
                onChange={(v) => set("cancelEnabled", v)}
              />
              <Toggle
                name="refillEnabled"
                label={d.refillEnabled}
                checked={values.refillEnabled}
                onChange={(v) => set("refillEnabled", v)}
              />
              <Toggle
                name="denyLinkDuplicates"
                label={d.denyLinkDuplicates}
                checked={values.denyLinkDuplicates}
                onChange={(v) => set("denyLinkDuplicates", v)}
              />
              <Toggle
                name="startCountParsing"
                label={d.startCountParsing}
                checked={values.startCountParsing}
                onChange={(v) => set("startCountParsing", v)}
              />
              <Toggle
                name="active"
                label={d.active}
                checked={values.active}
                onChange={(v) => set("active", v)}
              />
            </div>
          </Section>

          <Section title={d.sectionAdvanced}>
            <div className="grid gap-3 sm:grid-cols-2">
              <Field label={d.refillDays} htmlFor="svc-refill-days" error={errors.refillDays}>
                <Input
                  id="svc-refill-days"
                  name="refillDays"
                  type="number"
                  min={0}
                  value={values.refillDays}
                  onChange={(e) => set("refillDays", e.target.value)}
                  className="h-8 font-mono text-sm"
                />
              </Field>
              <Field
                label={d.averageTimeMinutes}
                htmlFor="svc-average"
                error={errors.averageTimeMinutes}
              >
                <Input
                  id="svc-average"
                  name="averageTimeMinutes"
                  type="number"
                  min={0}
                  value={values.averageTimeMinutes}
                  onChange={(e) => set("averageTimeMinutes", e.target.value)}
                  className="h-8 font-mono text-sm"
                />
              </Field>
            </div>
          </Section>

          <DialogFooter className="pt-1">
            <Button type="button" variant="outline" size="lg" onClick={close}>
              {adminTexts.common.cancel}
            </Button>
            <Button type="submit" size="lg" disabled={pending}>
              {pending ? d.saving : values.id ? d.save : d.create}
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  );
}

/** Provider type strings are free text; keep the current type when unknown. */
function mapPickType(providerType: string, current: string): string {
  const key = String(providerType ?? "").trim().toLowerCase();
  const table: Record<string, string> = {
    default: "DEFAULT",
    package: "PACKAGE",
    "custom comments": "CUSTOM_COMMENTS",
    "custom comments package": "CUSTOM_COMMENTS",
    mentions: "MENTIONS",
    "mentions with hashtags": "MENTIONS_HASHTAGS",
    "mentions hashtags": "MENTIONS_HASHTAGS",
    "mentions custom list": "MENTIONS_CUSTOM_LIST",
    "mentions hashtag": "MENTIONS_HASHTAG",
    "mentions user followers": "MENTIONS_USER_FOLLOWERS",
    "mentions media likers": "MENTIONS_MEDIA_LIKERS",
    subscriptions: "SUBSCRIPTIONS",
    subscription: "SUBSCRIPTIONS",
  };
  const mapped = table[key];
  if (!mapped) return current;
  return SERVICE_TYPE_OPTIONS.some((o) => o.value === mapped) ? mapped : current;
}

export default ServiceDialog;
