"use client";

import * as React from "react";
import { useActionState } from "react";
import { Info, Repeat, RotateCcw, Search, ShieldCheck, Tag, X, Zap } from "lucide-react";
import { toast } from "sonner";
import { EmptyState } from "@/components/shared/empty-state";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { createNewOrder, type NewOrderState, type NewOrderSuccess } from "@/lib/actions/order";
import { formatMinutes, formatNumber } from "@/lib/format";
import { newOrderTexts as tx } from "@/lib/i18n/neworder";
import { money } from "@/lib/serialize";
import { cn } from "@/lib/utils";
import {
  computeCharge,
  effectiveQuantity,
  isOverBalance,
  needsLink,
  needsQuantity,
  quantityIssue,
  toInt,
} from "./charge";
import { ChargePanel } from "./charge-panel";
import { DynamicFields, EMPTY_VALUES, type OrderFormValues } from "./dynamic-fields";
import { PlatformIcon, platformTint } from "./platform-icon";
import { WelcomeCards } from "./welcome-cards";
import {
  platformBucket,
  type CategoryDTO,
  type NewOrderConfig,
  type NewOrderUserDTO,
  type PlatformFilter,
  type ServiceDTO,
} from "./types";

const PLATFORMS: { key: PlatformFilter; label: string }[] = [
  { key: "ALL", label: tx.platformAll },
  { key: "INSTAGRAM", label: tx.platformInstagram },
  { key: "TIKTOK", label: tx.platformTiktok },
  { key: "YOUTUBE", label: tx.platformYoutube },
  { key: "FACEBOOK", label: tx.platformFacebook },
  { key: "TELEGRAM", label: tx.platformTelegram },
  { key: "OTHER", label: tx.platformOther },
];

function defaultsFor(service: ServiceDTO | null, minInterval: number): OrderFormValues {
  if (!service) {
    return { ...EMPTY_VALUES, interval: String(minInterval) };
  }
  return {
    ...EMPTY_VALUES,
    interval: String(minInterval),
    quantity: needsQuantity(service.type) ? String(service.min) : "",
    sub_min: String(service.min),
    sub_max: String(service.min),
    sub_posts: service.type === "SUBSCRIPTIONS" ? "1" : "",
    sub_delay: "0",
  };
}

export function NewOrderScreen({
  user,
  totalOrders,
  services,
  categories,
  config,
  initialServiceId,
}: {
  user: NewOrderUserDTO;
  totalOrders: number;
  services: ServiceDTO[];
  categories: CategoryDTO[];
  config: NewOrderConfig;
  initialServiceId: number | null;
}) {
  const initialService = React.useMemo(
    () => (initialServiceId ? (services.find((s) => s.id === initialServiceId) ?? null) : null),
    [initialServiceId, services],
  );

  const [platform, setPlatform] = React.useState<PlatformFilter>("ALL");
  const [query, setQuery] = React.useState("");
  const [categoryId, setCategoryId] = React.useState<string>(
    initialService?.categoryId ?? categories[0]?.id ?? "",
  );
  const [serviceId, setServiceId] = React.useState<number | null>(initialService?.id ?? null);
  const [values, setValues] = React.useState<OrderFormValues>(() =>
    defaultsFor(initialService, config.minDripIntervalMinutes),
  );
  const [drip, setDrip] = React.useState(false);
  const [lastOrder, setLastOrder] = React.useState<NewOrderSuccess | null>(null);

  const [state, formAction, pending] = useActionState<NewOrderState, FormData>(
    createNewOrder,
    null,
  );

  // ------------------------------------------------------------- filtering
  const filtered = React.useMemo(() => {
    const q = query.trim().toLowerCase();
    return services.filter((s) => {
      if (platform !== "ALL" && platformBucket(s.platform) !== platform) return false;
      if (!q) return true;
      return s.search.includes(q);
    });
  }, [services, platform, query]);

  const visibleCategories = React.useMemo(() => {
    const counts = new Map<string, number>();
    for (const s of filtered) counts.set(s.categoryId, (counts.get(s.categoryId) ?? 0) + 1);
    return categories
      .filter((c) => counts.has(c.id))
      .map((c) => ({ ...c, serviceCount: counts.get(c.id) ?? 0 }));
  }, [categories, filtered]);

  const categoryServices = React.useMemo(
    () => filtered.filter((s) => s.categoryId === categoryId),
    [filtered, categoryId],
  );

  React.useEffect(() => {
    if (visibleCategories.length === 0) {
      if (categoryId) setCategoryId("");
      return;
    }
    if (!visibleCategories.some((c) => c.id === categoryId)) {
      setCategoryId(visibleCategories[0].id);
    }
  }, [visibleCategories, categoryId]);

  React.useEffect(() => {
    if (categoryServices.length === 0) {
      if (serviceId !== null) setServiceId(null);
      return;
    }
    if (!categoryServices.some((s) => s.id === serviceId)) {
      setServiceId(categoryServices[0].id);
    }
  }, [categoryServices, serviceId]);

  const selected = React.useMemo(
    () => services.find((s) => s.id === serviceId) ?? null,
    [services, serviceId],
  );

  // Reset the type-specific inputs whenever the chosen service changes.
  const lastServiceRef = React.useRef<number | null | undefined>(undefined);
  React.useEffect(() => {
    if (lastServiceRef.current === serviceId) return;
    lastServiceRef.current = serviceId;
    const svc = services.find((s) => s.id === serviceId) ?? null;
    setDrip(false);
    setValues((current) => ({
      ...defaultsFor(svc, config.minDripIntervalMinutes),
      link: current.link,
    }));
  }, [serviceId, services, config.minDripIntervalMinutes]);

  // ------------------------------------------------------------- money
  const runs = drip ? Math.max(1, toInt(values.runs)) : 1;
  const quantity = selected ? effectiveQuantity(selected.type, values) : 0;
  const charge = selected ? computeCharge(selected, quantity, runs) : "0";
  const chargeLabel = money(charge, config.currencySymbol);
  const overBalance = isOverBalance(charge, user.balance);

  const issue =
    selected && needsQuantity(selected.type) && values.quantity.trim() !== ""
      ? quantityIssue(quantity, selected)
      : null;

  const quantityError =
    issue === "min"
      ? tx.quantityBelowMin(formatNumber(selected?.min ?? 0, 0))
      : issue === "max"
        ? tx.quantityAboveMax(formatNumber(selected?.max ?? 0, 0))
        : issue === "increment"
          ? tx.incrementHint(formatNumber(selected?.increment ?? 1, 0))
          : issue === "invalid"
            ? tx.quantityInvalid
            : undefined;

  const quantityHint = selected ? (
    <span className="font-mono text-[11px] tabular-nums">
      {tx.minMax(formatNumber(selected.min, 0), formatNumber(selected.max, 0))}
      {selected.increment && selected.increment > 1
        ? ` · ${tx.incrementHint(formatNumber(selected.increment, 0))}`
        : ""}
    </span>
  ) : null;

  const missingLink = Boolean(selected && needsLink(selected.type) && !values.link.trim());
  const canSubmit =
    Boolean(selected) && !issue && !missingLink && quantity > 0 && Number(charge) > 0;

  // ------------------------------------------------------------- action result
  const handledRef = React.useRef<NewOrderState>(null);
  React.useEffect(() => {
    if (!state || handledRef.current === state) return;
    handledRef.current = state;
    if (state.ok) {
      setLastOrder(state.data);
      setDrip(false);
      setValues(defaultsFor(selected, config.minDripIntervalMinutes));
      toast.success(tx.successToast(String(state.data.orderId)));
    } else {
      toast.error(state.error);
    }
  }, [state, selected, config.minDripIntervalMinutes]);

  const failure = state && state.ok === false ? state : null;
  const fieldErrors = failure?.fieldErrors ?? {};
  const showFundsWarning = overBalance || failure?.code === "not_enough_funds";

  const set = React.useCallback((key: keyof OrderFormValues, value: string) => {
    setValues((current) => ({ ...current, [key]: value }));
  }, []);

  const totalDripQuantity = drip && selected ? quantity * runs : 0;

  return (
    <div className="space-y-6">
      <WelcomeCards
        username={user.username}
        balanceLabel={user.balanceLabel}
        totalOrders={totalOrders}
      />

      {/* platform filters + search */}
      <div className="space-y-4 rounded-2xl border bg-card p-4 shadow-sm sm:p-5">
        <div className="flex flex-wrap gap-2">
          {PLATFORMS.map((p) => {
            const active = platform === p.key;
            return (
              <button
                key={p.key}
                type="button"
                onClick={() => setPlatform(p.key)}
                aria-pressed={active}
                className={cn(
                  "inline-flex items-center gap-1.5 rounded-lg border px-3 py-1.5 text-sm font-medium transition-colors",
                  active
                    ? "border-primary bg-primary text-primary-foreground"
                    : "bg-background hover:bg-muted",
                )}
              >
                <PlatformIcon
                  platform={p.key}
                  className={cn("size-4", active ? "text-primary-foreground" : platformTint(p.key))}
                />
                {p.label}
              </button>
            );
          })}
        </div>

        <div className="flex flex-col gap-2 sm:flex-row sm:items-center">
          <div className="relative flex-1">
            <Search className="pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
            <Input
              value={query}
              onChange={(e) => setQuery(e.target.value)}
              placeholder={tx.searchPlaceholder}
              className="h-10 pl-9"
              aria-label={tx.searchPlaceholder}
            />
            {query ? (
              <button
                type="button"
                onClick={() => setQuery("")}
                className="absolute right-2 top-1/2 -translate-y-1/2 rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
                aria-label={tx.clearSearch}
              >
                <X className="size-4" />
              </button>
            ) : null}
          </div>
          <p className="shrink-0 text-xs text-muted-foreground sm:w-40 sm:text-right">
            <span className="font-mono tabular-nums">{formatNumber(filtered.length, 0)}</span>{" "}
            {tx.searchResults}
          </p>
        </div>
      </div>

      {filtered.length === 0 ? (
        <EmptyState
          icon={Search}
          title={tx.noServices}
          hint={tx.noServicesHint}
          action={
            <Button
              variant="outline"
              size="sm"
              onClick={() => {
                setQuery("");
                setPlatform("ALL");
              }}
            >
              <RotateCcw className="size-4" />
              {tx.clearSearch}
            </Button>
          }
        />
      ) : (
        <div className="grid gap-6 xl:grid-cols-3">
          <form action={formAction} className="space-y-5 xl:col-span-2">
            <input type="hidden" name="serviceId" value={selected?.id ?? ""} />

            <div className="space-y-5 rounded-2xl border bg-card p-5 shadow-sm sm:p-6">
              <div className="grid gap-4 sm:grid-cols-2">
                <div className="space-y-2">
                  <label className="text-sm font-medium" htmlFor="category-select">
                    {tx.categoryLabel}
                  </label>
                  <Select
                    value={categoryId}
                    onValueChange={setCategoryId}
                    disabled={pending || visibleCategories.length === 0}
                  >
                    <SelectTrigger id="category-select" className="h-10 w-full">
                      <SelectValue placeholder={tx.categoryPlaceholder} />
                    </SelectTrigger>
                    <SelectContent className="max-h-80">
                      <SelectGroup>
                        {visibleCategories.map((c) => (
                          <SelectItem key={c.id} value={c.id}>
                            <PlatformIcon
                              platform={c.platform}
                              className={cn("size-3.5", platformTint(c.platform))}
                            />
                            <span className="truncate">{c.name}</span>
                            <span className="font-mono text-[11px] text-muted-foreground">
                              {c.serviceCount}
                            </span>
                          </SelectItem>
                        ))}
                      </SelectGroup>
                    </SelectContent>
                  </Select>
                </div>

                <div className="space-y-2">
                  <label className="text-sm font-medium" htmlFor="service-select">
                    {tx.serviceLabel}
                  </label>
                  <Select
                    value={selected ? String(selected.id) : ""}
                    onValueChange={(v) => setServiceId(Number(v))}
                    disabled={pending || categoryServices.length === 0}
                  >
                    <SelectTrigger id="service-select" className="h-10 w-full">
                      <SelectValue placeholder={tx.servicePlaceholder} />
                    </SelectTrigger>
                    <SelectContent className="max-h-80">
                      <SelectGroup>
                        {categoryServices.map((s) => (
                          <SelectItem key={s.id} value={String(s.id)}>
                            <span className="font-mono text-xs text-muted-foreground">
                              {s.id}
                            </span>
                            <span className="text-muted-foreground">-</span>
                            <span className="truncate">{s.name}</span>
                            <span className="text-muted-foreground">-</span>
                            <span className="font-mono text-xs text-primary">{s.rateLabel}</span>
                            <span className="text-[11px] text-muted-foreground">
                              {tx.perThousand}
                            </span>
                          </SelectItem>
                        ))}
                      </SelectGroup>
                    </SelectContent>
                  </Select>
                </div>
              </div>

              {/* description */}
              <div className="space-y-2">
                <p className="text-sm font-medium">{tx.descriptionLabel}</p>
                <div className="max-h-56 overflow-y-auto whitespace-pre-line rounded-xl border bg-muted/40 px-4 py-3 text-sm leading-relaxed text-muted-foreground">
                  {selected?.description?.trim() ? selected.description : tx.noDescription}
                </div>
              </div>

              {selected ? (
                <DynamicFields
                  service={selected}
                  values={values}
                  set={set}
                  errors={fieldErrors}
                  disabled={pending}
                  config={config}
                  drip={drip}
                  setDrip={setDrip}
                  quantityHint={quantityHint}
                  quantityError={quantityError}
                />
              ) : (
                <p className="rounded-lg border border-dashed px-3 py-6 text-center text-sm text-muted-foreground">
                  {tx.selectServiceFirst}
                </p>
              )}

              {drip && selected ? (
                <p className="flex items-center gap-1.5 text-xs text-muted-foreground">
                  <Repeat className="size-3.5" />
                  <span className="font-mono tabular-nums">
                    {tx.dripTotalQuantity(formatNumber(totalDripQuantity, 0))}
                  </span>
                </p>
              ) : null}

              <ChargePanel
                chargeLabel={chargeLabel}
                pending={pending}
                disabled={!canSubmit}
                notEnoughFunds={showFundsWarning}
                lastOrder={lastOrder}
              />
            </div>
          </form>

          {/* service summary */}
          <aside className="space-y-4">
            <div className="space-y-4 rounded-2xl border bg-card p-5 shadow-sm">
              <p className="flex items-center gap-2 font-display text-sm font-semibold tracking-tight">
                <Info className="size-4 text-primary" />
                {selected ? selected.name : tx.serviceLabel}
              </p>

              {selected ? (
                <>
                  <dl className="space-y-2.5 text-sm">
                    <div className="flex items-center justify-between gap-3">
                      <dt className="text-muted-foreground">{tx.summaryServiceId}</dt>
                      <dd className="font-mono tabular-nums">{selected.id}</dd>
                    </div>
                    <div className="flex items-center justify-between gap-3">
                      <dt className="text-muted-foreground">{tx.categoryLabel}</dt>
                      <dd className="truncate text-right">{selected.categoryName}</dd>
                    </div>
                    <div className="flex items-center justify-between gap-3">
                      <dt className="text-muted-foreground">{tx.summaryRate}</dt>
                      <dd className="font-mono font-semibold tabular-nums text-primary">
                        {selected.rateLabel}
                      </dd>
                    </div>
                    <div className="flex items-center justify-between gap-3">
                      <dt className="text-muted-foreground">{tx.summaryMinMax}</dt>
                      <dd className="font-mono text-xs tabular-nums">
                        {formatNumber(selected.min, 0)} / {formatNumber(selected.max, 0)}
                      </dd>
                    </div>
                    {config.averageTimeEnabled && selected.averageTimeMinutes !== null ? (
                      <div className="flex items-center justify-between gap-3">
                        <dt className="text-muted-foreground">{tx.averageTimeLabel}</dt>
                        <dd className="font-mono text-xs tabular-nums">
                          {formatMinutes(selected.averageTimeMinutes)}
                        </dd>
                      </div>
                    ) : null}
                  </dl>

                  <div className="flex flex-wrap gap-1.5">
                    {selected.refillEnabled ? (
                      <span className="inline-flex items-center gap-1 rounded-full bg-emerald-100 px-2 py-0.5 text-[11px] font-medium text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-400">
                        <ShieldCheck className="size-3" />
                        {tx.badgeRefill}
                        {selected.refillDays ? ` ${selected.refillDays}d` : ""}
                      </span>
                    ) : null}
                    {selected.cancelEnabled ? (
                      <span className="inline-flex items-center gap-1 rounded-full bg-slate-100 px-2 py-0.5 text-[11px] font-medium text-slate-700 dark:bg-slate-500/15 dark:text-slate-300">
                        <X className="size-3" />
                        {tx.badgeCancel}
                      </span>
                    ) : null}
                    {selected.dripfeedEnabled ? (
                      <span className="inline-flex items-center gap-1 rounded-full bg-blue-100 px-2 py-0.5 text-[11px] font-medium text-blue-700 dark:bg-blue-500/15 dark:text-blue-400">
                        <Repeat className="size-3" />
                        {tx.badgeDripfeed}
                      </span>
                    ) : null}
                    <span className="inline-flex items-center gap-1 rounded-full bg-violet-100 px-2 py-0.5 text-[11px] font-medium text-violet-700 dark:bg-violet-500/15 dark:text-violet-400">
                      <Tag className="size-3" />
                      {selected.type.replace(/_/g, " ").toLowerCase()}
                    </span>
                  </div>
                </>
              ) : (
                <p className="text-sm text-muted-foreground">{tx.selectServiceFirst}</p>
              )}
            </div>

            <div className="rounded-2xl border border-dashed p-5">
              <p className="flex items-center gap-2 font-display text-sm font-semibold tracking-tight">
                <Zap className="size-4 text-cyan-500" />
                {tx.tipsTitle}
              </p>
              <ul className="mt-2.5 space-y-2 text-xs leading-relaxed text-muted-foreground">
                {[tx.tip1, tx.tip2, tx.tip3].map((tip) => (
                  <li key={tip} className="flex gap-2">
                    <span className="mt-1.5 size-1.5 shrink-0 rounded-full bg-cyan-500" />
                    <span>{tip}</span>
                  </li>
                ))}
              </ul>
            </div>
          </aside>
        </div>
      )}
    </div>
  );
}

export default NewOrderScreen;
