import { zodResolver } from "@hookform/resolvers/zod";
import { Button } from "@workspace/ui/components/button";
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@workspace/ui/components/form";
import { ScrollArea } from "@workspace/ui/components/scroll-area";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@workspace/ui/components/select";
import {
  Sheet,
  SheetContent,
  SheetFooter,
  SheetHeader,
  SheetTitle,
} from "@workspace/ui/components/sheet";
import { Switch } from "@workspace/ui/components/switch";
import { ConfirmButton } from "@workspace/ui/composed/confirm-button";
import {
  EnhancedInput,
  type EnhancedInputProps,
} from "@workspace/ui/composed/enhanced-input";
import { Icon } from "@workspace/ui/composed/icon";
import {
  createLotteryPrize,
  deleteLotteryPrize,
  updateLotteryPrize,
} from "@workspace/ui/services/admin/lottery";
import { getSubscribeList } from "@workspace/ui/services/admin/subscribe";
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
import { z } from "zod";

const CENTS_PER_YUAN = 100;
// 概率单位约定：weight 1000 = 1%（支持 3 位小数概率，总权重 100000 = 100%）。
const WEIGHT_PER_PERCENT = 1000;

// numberOutput 把 text 输入转成数字（空/非法→undefined）。数字输入统一用 type="text"
// + 该 formatOutput，避开 EnhancedInput 在 type="number" 下 min/max 实时钳制导致的
// “输入 0 / 改中间位跳变”问题；提交仍是数字，后端收 int。
const numberOutput = (v: string | number): number | undefined => {
  const s = String(v ?? "").trim();
  if (s === "") {
    return;
  }
  const n = Number(s);
  return Number.isNaN(n) ? undefined : n;
};

type TranslateFn = (key: string, defaultValue: string) => string;

const PRIZE_TYPE_OPTIONS: {
  value: API.LotteryPrizeType;
  labelKey: string;
  labelDefault: string;
}[] = [
  {
    value: "vpn_duration",
    labelKey: "prize.typeVpnDuration",
    labelDefault: "VPN Duration",
  },
  {
    value: "crypto",
    labelKey: "prize.typeCrypto",
    labelDefault: "Crypto",
  },
  {
    value: "none",
    labelKey: "prize.typeNone",
    labelDefault: "No Prize (Thanks)",
  },
];

const getPrizeSchema = (t: TranslateFn) =>
  z
    .object({
      type: z.enum(["vpn_duration", "crypto", "none"]),
      name: z.string().min(1, t("prize.nameRequired", "Name is required")),
      icon_url: z
        .string()
        .url(t("prize.iconUrlInvalid", "Must be a valid URL"))
        .or(z.literal(""))
        .optional(),
      weight: z
        .number()
        .min(0, t("prize.weightMin", "Probability must be at least 0"))
        .max(100, t("prize.weightMax", "Probability cannot exceed 100")),
      unlimited_stock: z.boolean(),
      total_stock: z.number().optional(),
      is_fallback: z.boolean(),
      duration_days: z.number().optional(),
      subscribe_id: z.number().optional(),
      amount_yuan: z.number().optional(),
      // 人工奖（crypto / physical / manual_other）通用/专属字段
      crypto_amount: z.string().optional(),
      crypto_currency: z.string().optional(),
      crypto_networks: z.string().optional(), // 逗号分隔，提交时 split 成 string[]
      sku_name: z.string().optional(),
      claim_ttl_hours: z.number().optional(),
    })
    .superRefine((data, ctx) => {
      const issue = (path: string, message: string) => {
        ctx.addIssue({ code: z.ZodIssueCode.custom, message, path: [path] });
      };
      const isPositiveInt = (value?: number) =>
        !!value && value > 0 && Number.isInteger(value);
      if (data.type === "vpn_duration" && !isPositiveInt(data.duration_days)) {
        issue(
          "duration_days",
          t(
            "prize.durationDaysRequired",
            "Duration days must be a positive integer"
          )
        );
      }
      if (data.type === "crypto") {
        if (!data.crypto_amount?.trim()) {
          issue(
            "crypto_amount",
            t("prize.cryptoAmountRequired", "Amount is required")
          );
        }
        if (!data.crypto_currency?.trim()) {
          issue(
            "crypto_currency",
            t("prize.cryptoCurrencyRequired", "Currency is required")
          );
        }
        const networks = (data.crypto_networks ?? "")
          .split(",")
          .map((n) => n.trim())
          .filter(Boolean);
        if (networks.length === 0) {
          issue(
            "crypto_networks",
            t(
              "prize.cryptoNetworksRequired",
              "At least one network is required (comma-separated)"
            )
          );
        }
      }
      if (
        data.claim_ttl_hours !== undefined &&
        (!Number.isInteger(data.claim_ttl_hours) || data.claim_ttl_hours <= 0)
      ) {
        issue(
          "claim_ttl_hours",
          t(
            "prize.claimTtlInvalid",
            "Claim window (hours) must be a positive integer"
          )
        );
      }
      if (!(data.unlimited_stock || isPositiveInt(data.total_stock))) {
        issue(
          "total_stock",
          t(
            "prize.totalStockRequired",
            "Total stock must be a positive integer"
          )
        );
      }
    });

type PrizeFormValues = z.infer<ReturnType<typeof getPrizeSchema>>;

interface PrizeFormProps {
  activityId: number;
  slot: number;
  initialValues?: API.LotteryPrize;
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onSuccess: () => void;
}

function toFormValues(prize?: API.LotteryPrize): PrizeFormValues {
  const config = prize?.config ?? {};
  const networks = Array.isArray(config.networks)
    ? (config.networks as string[]).join(", ")
    : undefined;
  return {
    type: (prize?.type as PrizeFormValues["type"]) ?? "vpn_duration",
    name: prize?.name ?? "",
    icon_url: prize?.icon_url ?? "",
    weight: (prize?.weight ?? 0) / WEIGHT_PER_PERCENT,
    unlimited_stock: prize ? prize.total_stock === null : true,
    total_stock: prize?.total_stock ?? undefined,
    is_fallback: prize?.is_fallback ?? false,
    duration_days: config.duration_days as number | undefined,
    subscribe_id: config.subscribe_id as number | undefined,
    amount_yuan:
      typeof config.amount_cents === "number"
        ? config.amount_cents / CENTS_PER_YUAN
        : undefined,
    crypto_amount: config.amount as string | undefined,
    crypto_currency: config.currency as string | undefined,
    crypto_networks: networks,
    sku_name: config.sku_name as string | undefined,
    claim_ttl_hours: config.claim_ttl_hours as number | undefined,
  };
}

function toConfig(values: PrizeFormValues): Record<string, any> {
  // claim_ttl_hours 对所有人工奖通用：控制领奖窗口（缺省后端默认 7 天）。
  const withTtl = (base: Record<string, any>): Record<string, any> => {
    if (values.claim_ttl_hours && values.claim_ttl_hours > 0) {
      base.claim_ttl_hours = values.claim_ttl_hours;
    }
    return base;
  };
  if (values.type === "vpn_duration") {
    const config: Record<string, any> = { duration_days: values.duration_days };
    // 可选：无活跃订阅时按该套餐新建订阅发放时长。0/未选则沿用旧行为（跳过发放）。
    if (values.subscribe_id && values.subscribe_id > 0) {
      config.subscribe_id = values.subscribe_id;
    }
    return config;
  }
  if (values.type === "crypto") {
    return withTtl({
      amount: values.crypto_amount?.trim() ?? "",
      currency: values.crypto_currency?.trim() ?? "",
      networks: (values.crypto_networks ?? "")
        .split(",")
        .map((n) => n.trim())
        .filter(Boolean),
    });
  }
  return {};
}

export default function PrizeForm({
  activityId,
  slot,
  initialValues,
  open,
  onOpenChange,
  onSuccess,
}: PrizeFormProps) {
  const { t } = useTranslation("lottery");
  const [loading, setLoading] = useState(false);
  const [plans, setPlans] = useState<API.SubscribeItem[]>([]);
  const form = useForm<PrizeFormValues>({
    resolver: zodResolver(getPrizeSchema(t)),
    defaultValues: toFormValues(initialValues),
  });
  const type = form.watch("type");
  const unlimitedStock = form.watch("unlimited_stock");
  const isFallback = form.watch("is_fallback");
  const isEdit = !!initialValues?.id;
  const targetSlot = initialValues?.slot ?? slot;

  useEffect(() => {
    if (open) form.reset(toFormValues(initialValues));
  }, [form, initialValues, open]);

  // vpn_duration 需要一个可选的“新建订阅套餐”下拉，仅在面板打开且类型匹配时拉取。
  useEffect(() => {
    if (!(open && type === "vpn_duration") || plans.length > 0) return;
    getSubscribeList({ page: 1, size: 100 })
      .then(({ data }) => setPlans(data?.data?.list ?? []))
      .catch(() => {
        // Request layer already surfaces the error toast
      });
  }, [open, type, plans.length]);

  async function handleSubmit(values: PrizeFormValues) {
    setLoading(true);
    try {
      const body: API.CreateLotteryPrizeRequest = {
        activity_id: activityId,
        slot: targetSlot,
        type: values.type,
        name: values.name.trim(),
        icon_url: values.icon_url?.trim() ?? "",
        config: toConfig(values),
        weight: values.is_fallback
          ? 0
          : Math.round(values.weight * WEIGHT_PER_PERCENT),
        total_stock: values.unlimited_stock
          ? null
          : (values.total_stock ?? null),
        is_fallback: values.is_fallback,
      };
      if (isEdit) {
        await updateLotteryPrize({ ...body, id: initialValues!.id });
        toast.success(t("prize.updateSuccess", "Prize updated"));
      } else {
        await createLotteryPrize(body);
        toast.success(t("prize.createSuccess", "Prize created"));
      }
      onSuccess();
      onOpenChange(false);
    } catch {
      // Request layer already surfaces the error toast
    } finally {
      setLoading(false);
    }
  }

  async function handleDelete() {
    if (!initialValues?.id) return;
    setLoading(true);
    try {
      await deleteLotteryPrize({ id: initialValues.id });
      toast.success(t("prize.deleteSuccess", "Prize deleted"));
      onSuccess();
      onOpenChange(false);
    } catch {
      // Request layer already surfaces the error toast
    } finally {
      setLoading(false);
    }
  }

  const renderInput = (
    name:
      | "name"
      | "icon_url"
      | "weight"
      | "total_stock"
      | "duration_days"
      | "amount_yuan"
      | "crypto_amount"
      | "crypto_currency"
      | "crypto_networks"
      | "sku_name"
      | "claim_ttl_hours",
    label: string,
    inputProps: Partial<EnhancedInputProps<any>>,
    description?: string
  ) => (
    <FormField
      control={form.control}
      name={name}
      render={({ field }) => (
        <FormItem>
          <FormLabel>{label}</FormLabel>
          <FormControl>
            <EnhancedInput
              onValueChange={(value) => form.setValue(name, value)}
              value={field.value}
              {...inputProps}
            />
          </FormControl>
          {description && (
            <p className="text-muted-foreground text-xs">{description}</p>
          )}
          <FormMessage />
        </FormItem>
      )}
    />
  );

  const renderSwitch = (
    name: "unlimited_stock" | "is_fallback",
    label: string,
    description?: string
  ) => (
    <FormField
      control={form.control}
      name={name}
      render={({ field }) => (
        <FormItem className="flex items-center justify-between rounded-md border p-3">
          <div className="space-y-1">
            <FormLabel>{label}</FormLabel>
            {description && (
              <p className="text-muted-foreground text-xs">{description}</p>
            )}
          </div>
          <FormControl>
            <Switch
              checked={field.value}
              onCheckedChange={(checked) => form.setValue(name, checked)}
            />
          </FormControl>
        </FormItem>
      )}
    />
  );

  return (
    <Sheet onOpenChange={onOpenChange} open={open}>
      <SheetContent className="w-[520px] max-w-full md:max-w-screen-md">
        <SheetHeader>
          <SheetTitle>
            {isEdit
              ? t("prize.editTitle", "Edit Prize")
              : t("prize.createTitle", "Add Prize")}
            {" · "}
            {t("prize.slotLabel", "Slot")} {targetSlot}
          </SheetTitle>
        </SheetHeader>
        <ScrollArea className="h-[calc(100vh-48px-36px-36px-env(safe-area-inset-top))]">
          <Form {...form}>
            <form
              className="space-y-4 px-6 pt-4"
              onSubmit={form.handleSubmit(handleSubmit)}
            >
              <FormField
                control={form.control}
                name="type"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>{t("prize.type", "Prize Type")}</FormLabel>
                    <FormControl>
                      <Select
                        onValueChange={(value) =>
                          form.setValue(
                            field.name,
                            value as PrizeFormValues["type"]
                          )
                        }
                        value={field.value}
                      >
                        <SelectTrigger className="w-full">
                          <SelectValue
                            placeholder={t("prize.selectType", "Select type")}
                          />
                        </SelectTrigger>
                        <SelectContent>
                          {PRIZE_TYPE_OPTIONS.map((option) => (
                            <SelectItem key={option.value} value={option.value}>
                              {t(option.labelKey, option.labelDefault)}
                            </SelectItem>
                          ))}
                        </SelectContent>
                      </Select>
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />
              {renderInput("name", t("prize.name", "Prize Name"), {
                placeholder: t("prize.namePlaceholder", "e.g. 1-Day Pass"),
              })}
              {renderInput("icon_url", t("prize.iconUrl", "Icon URL"), {
                placeholder: "https://",
              })}
              {type === "vpn_duration" &&
                renderInput(
                  "duration_days",
                  t("prize.durationDays", "Duration (days)"),
                  {
                    type: "text",
                    inputMode: "numeric",
                    formatOutput: numberOutput,
                    placeholder: t("prize.durationDaysPlaceholder", "e.g. 1"),
                    suffix: t("prize.daysSuffix", "days"),
                  }
                )}
              {type === "vpn_duration" && (
                <FormField
                  control={form.control}
                  name="subscribe_id"
                  render={({ field }) => (
                    <FormItem>
                      <FormLabel>
                        {t("prize.subscribePlan", "New-subscription plan")}
                      </FormLabel>
                      <FormControl>
                        <Select
                          onValueChange={(value) =>
                            form.setValue(
                              "subscribe_id",
                              value ? Number(value) : undefined
                            )
                          }
                          value={field.value ? String(field.value) : undefined}
                        >
                          <SelectTrigger className="w-full">
                            <SelectValue
                              placeholder={t(
                                "prize.subscribePlanPlaceholder",
                                "None — skip if user has no active subscription"
                              )}
                            />
                          </SelectTrigger>
                          <SelectContent>
                            {plans.map((plan) => (
                              <SelectItem key={plan.id} value={String(plan.id)}>
                                {plan.name ?? `#${plan.id}`}
                              </SelectItem>
                            ))}
                          </SelectContent>
                        </Select>
                      </FormControl>
                      <p className="text-muted-foreground text-xs">
                        {t(
                          "prize.subscribePlanHint",
                          "When the user has no active subscription, create one on this plan and grant the duration. Leave empty to skip granting."
                        )}
                      </p>
                      <FormMessage />
                    </FormItem>
                  )}
                />
              )}
              {type === "none" && (
                <p className="rounded-md bg-muted/50 p-3 text-muted-foreground text-xs">
                  {t(
                    "prize.noneHint",
                    "No config needed. Consider enabling fallback so users always land on this prize when limited prizes run out."
                  )}
                </p>
              )}
              {type === "crypto" && (
                <>
                  {renderInput(
                    "crypto_amount",
                    t("prize.cryptoAmount", "Amount"),
                    {
                      placeholder: t(
                        "prize.cryptoAmountPlaceholder",
                        "e.g. 0.01"
                      ),
                    }
                  )}
                  {renderInput(
                    "crypto_currency",
                    t("prize.cryptoCurrency", "Currency"),
                    { placeholder: "USDT / BTC / ETH" }
                  )}
                  {renderInput(
                    "crypto_networks",
                    t("prize.cryptoNetworks", "Networks"),
                    { placeholder: "TRC20, ERC20, BTC" },
                    t(
                      "prize.cryptoNetworksHint",
                      "Comma-separated. The user picks one of these when claiming."
                    )
                  )}
                </>
              )}
              {type === "crypto" && (
                <>
                  {renderInput(
                    "claim_ttl_hours",
                    t("prize.claimTtlHours", "Claim window (hours)"),
                    {
                      type: "text",
                      inputMode: "numeric",
                      formatOutput: numberOutput,
                      placeholder: "168",
                      suffix: t("prize.hoursSuffix", "hours"),
                    },
                    t(
                      "prize.claimTtlHint",
                      "How long the user has to submit claim info. Default 168h (7 days)."
                    )
                  )}
                  <p className="rounded-md bg-muted/50 p-3 text-muted-foreground text-xs">
                    {t(
                      "prize.manualPrizeHint",
                      "Manual prize: the winner submits claim info, then an operator approves and marks it paid/shipped under the Claims tab."
                    )}
                  </p>
                </>
              )}
              {renderInput(
                "weight",
                t("prize.weight", "Win probability (%)"),
                {
                  type: "text",
                  inputMode: "decimal",
                  formatOutput: numberOutput,
                  suffix: "%",
                  disabled: isFallback,
                },
                isFallback
                  ? t(
                      "prize.fallbackIgnoresWeight",
                      "Fallback prize ignores probability (never randomly drawn)"
                    )
                  : t(
                      "prize.weightHint",
                      "Percent chance in the grid. All drawable prizes must total 100%. 0 = shown but never drawn."
                    )
              )}
              {renderSwitch(
                "unlimited_stock",
                t("prize.unlimitedStock", "Unlimited Stock")
              )}
              {!unlimitedStock &&
                renderInput(
                  "total_stock",
                  t("prize.totalStock", "Total Stock"),
                  {
                    type: "text",
                    inputMode: "numeric",
                    formatOutput: numberOutput,
                    placeholder: t("prize.totalStockPlaceholder", "e.g. 100"),
                  }
                )}
              {renderSwitch(
                "is_fallback",
                t("prize.isFallback", "Fallback Prize"),
                t(
                  "prize.isFallbackHint",
                  "Awarded when limited prizes are sold out"
                )
              )}
            </form>
          </Form>
        </ScrollArea>
        <SheetFooter className="flex-row justify-end gap-2 pt-3">
          {isEdit && (
            <ConfirmButton
              cancelText={t("prize.cancel", "Cancel")}
              confirmText={t("prize.confirmDelete", "Delete")}
              description={t(
                "prize.deleteDescription",
                "This prize will be removed from the grid. This action cannot be undone."
              )}
              onConfirm={handleDelete}
              title={t("prize.deleteTitle", "Delete this prize?")}
              trigger={
                <Button
                  className="mr-auto"
                  disabled={loading}
                  variant="destructive"
                >
                  {t("prize.delete", "Delete")}
                </Button>
              }
            />
          )}
          <Button
            disabled={loading}
            onClick={() => onOpenChange(false)}
            variant="outline"
          >
            {t("prize.cancel", "Cancel")}
          </Button>
          <Button disabled={loading} onClick={form.handleSubmit(handleSubmit)}>
            {loading && (
              <Icon className="mr-2 animate-spin" icon="mdi:loading" />
            )}
            {t("prize.confirm", "Confirm")}
          </Button>
        </SheetFooter>
      </SheetContent>
    </Sheet>
  );
}
