"use client";

import { zodResolver } from "@hookform/resolvers/zod";
import { useMutation, useQuery } from "@tanstack/react-query";
import { Button } from "@workspace/ui/components/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@workspace/ui/components/card";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@workspace/ui/components/dialog";
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@workspace/ui/components/form";
import { Input } from "@workspace/ui/components/input";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@workspace/ui/components/select";
import { Textarea } from "@workspace/ui/components/textarea";
import { ConfirmButton } from "@workspace/ui/composed/confirm-button";
import type { ProListActions } from "@workspace/ui/composed/pro-list/pro-list";
import { ProList } from "@workspace/ui/composed/pro-list/pro-list";
import { UploadImage } from "@workspace/ui/composed/upload-image";
import {
  commissionWithdraw,
  queryUserAffiliate,
  queryUserAffiliateList,
  queryWithdrawalLog,
  uploadFile,
  withdrawalCancel,
} from "@workspace/ui/services/user/user";
import { formatDate } from "@workspace/ui/utils/formatting";
import { unitConversion } from "@workspace/ui/utils/unit-conversions";
import { Copy, X } from "lucide-react";
import { useRef, useState, useTransition } from "react";
import { CopyToClipboard } from "react-copy-to-clipboard";
import { useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
import { z } from "zod";
import { Display } from "@/components/display";
import { useGlobalStore } from "@/stores/global";

const WITHDRAWAL_METHODS = [
  { value: 1, label: "支付宝" },
  { value: 2, label: "微信" },
  { value: 3, label: "银行卡" },
  { value: 0, label: "其他" },
] as const;

function getWithdrawalMethodLabel(method: number): string {
  return WITHDRAWAL_METHODS.find((m) => m.value === method)?.label ?? "未知";
}

function getWithdrawalStatusMeta(
  status: number,
  t: ReturnType<typeof useTranslation<"affiliate">>["t"]
) {
  switch (status) {
    case 1:
      return {
        label: t("withdrawal.status.approved", "Approved"),
        className: "bg-emerald-500/10 text-emerald-600",
      };
    case 2:
      return {
        label: t("withdrawal.status.rejected", "Rejected"),
        className: "bg-destructive/10 text-destructive",
      };
    case 3:
      return {
        label: t("withdrawal.status.cancelled", "Cancelled"),
        className: "bg-muted text-muted-foreground",
      };
    default:
      return {
        label: t("withdrawal.status.pending", "Pending"),
        className: "bg-amber-500/10 text-amber-600",
      };
  }
}

function QrCodeView({ url }: { url: string }) {
  const [zoomOpen, setZoomOpen] = useState(false);
  return (
    <>
      <button
        className="block overflow-hidden rounded border"
        onClick={() => setZoomOpen(true)}
        type="button"
      >
        <img
          alt="收款码"
          className="h-16 w-16 cursor-zoom-in object-cover"
          src={url}
        />
      </button>
      {zoomOpen && (
        <Dialog onOpenChange={setZoomOpen} open={zoomOpen}>
          <DialogContent className="max-w-sm">
            <img alt="收款码" className="w-full" src={url} />
          </DialogContent>
        </Dialog>
      )}
    </>
  );
}

const withdrawalFormSchema = z
  .object({
    amount: z.number(),
    method: z.number(),
    account: z.string().trim().max(200).optional(),
    qr_code_url: z.string().optional(),
    content: z.string().trim().max(1000).optional(),
  })
  .superRefine((data, ctx) => {
    if (!data.amount || data.amount <= 0) {
      ctx.addIssue({
        code: z.ZodIssueCode.custom,
        message: "提现金额必须大于 0",
        path: ["amount"],
      });
    }
    if (data.method === 1 || data.method === 2) {
      if (!data.qr_code_url) {
        ctx.addIssue({
          code: z.ZodIssueCode.custom,
          message: "请上传收款码",
          path: ["qr_code_url"],
        });
      }
    } else if (data.method === 3) {
      if (!data.account) {
        ctx.addIssue({
          code: z.ZodIssueCode.custom,
          message: "银行卡收款账号为必填",
          path: ["account"],
        });
      }
    } else if (data.method === 0) {
      if (!data.account && !data.content) {
        ctx.addIssue({
          code: z.ZodIssueCode.custom,
          message: "收款账号和备注至少填一项",
          path: ["account"],
        });
      }
    }
  });

type WithdrawalFormValues = z.infer<typeof withdrawalFormSchema>;

export default function Affiliate() {
  const { t } = useTranslation("affiliate");
  const { user, common, getUserInfo } = useGlobalStore();
  const [withdrawalOpen, setWithdrawalOpen] = useState(false);
  const [submitting, startTransition] = useTransition();
  const [qrUploading, setQrUploading] = useState(false);
  const withdrawalListActionRef = useRef<ProListActions | undefined>(undefined);

  const affiliateQuery = useQuery({
    queryKey: ["queryUserAffiliate"],
    queryFn: async () => {
      const response = await queryUserAffiliate();
      return response.data.data;
    },
  });
  const availableCommission = Number(
    user?.commission ?? affiliateQuery.data?.total_commission ?? 0
  );

  const withdrawalForm = useForm<WithdrawalFormValues>({
    resolver: zodResolver(withdrawalFormSchema),
    defaultValues: {
      amount: 0,
      method: 1,
      account: "",
      qr_code_url: "",
      content: "",
    },
  });

  const watchedMethod = withdrawalForm.watch("method");
  const watchedQrCodeUrl = withdrawalForm.watch("qr_code_url");

  const handleQrUpload = async (file: string | File) => {
    if (!(file instanceof File)) return;
    setQrUploading(true);
    try {
      const formData = new FormData();
      formData.append("file", file);
      formData.append("biz_type", "withdrawal_qrcode");
      const response = await uploadFile(formData);
      const uploadedUrl =
        response.data.data?.url || response.data.data?.key || "";
      withdrawalForm.setValue("qr_code_url", uploadedUrl);
      withdrawalForm.clearErrors("qr_code_url");
    } catch {
      toast.error("收款码上传失败，请重试");
    } finally {
      setQrUploading(false);
    }
  };

  const cancelMutation = useMutation({
    mutationFn: async (withdrawalId: number) =>
      withdrawalCancel({ withdrawal_id: withdrawalId }),
    onSuccess: () => {
      toast.success("提现申请已取消");
      withdrawalListActionRef.current?.refresh();
    },
    onError: () => {
      toast.error("取消失败，请重试");
    },
  });

  const submitWithdrawal = (values: WithdrawalFormValues) => {
    if (values.amount > availableCommission) {
      withdrawalForm.setError("amount", {
        message: t(
          "withdrawal.validation.amountExceeded",
          "Amount cannot exceed available commission"
        ),
      });
      return;
    }
    startTransition(async () => {
      await commissionWithdraw({
        amount: values.amount,
        method: values.method,
        account: values.account || undefined,
        qr_code_url: values.qr_code_url || undefined,
        content: values.content || undefined,
      });
      toast.success(
        t("withdrawal.submitSuccess", "Withdrawal request submitted")
      );
      await Promise.all([
        affiliateQuery.refetch(),
        getUserInfo(),
        withdrawalListActionRef.current?.refresh(),
      ]);
      setWithdrawalOpen(false);
      withdrawalForm.reset({
        amount: 0,
        method: 1,
        account: "",
        qr_code_url: "",
        content: "",
      });
    });
  };

  return (
    <div className="flex flex-col gap-4">
      <Card>
        <CardHeader>
          <CardTitle>{t("totalCommission", "Total Commission")}</CardTitle>
          <CardDescription>
            {t("commissionInfo", "Commission Info")}
          </CardDescription>
        </CardHeader>
        <CardContent>
          <div className="flex flex-col gap-4 md:flex-row md:items-end md:justify-between">
            <div className="flex items-baseline gap-2">
              <span className="font-bold text-3xl">
                <Display
                  type="currency"
                  value={affiliateQuery.data?.total_commission}
                />
              </span>
              <span className="text-muted-foreground text-sm">
                ({t("commissionRate", "Commission Rate")}:{" "}
                {user?.referral_percentage ||
                  common?.invite?.referral_percentage}
                %)
              </span>
            </div>
            <div className="flex flex-col items-start gap-2 md:items-end">
              <div className="text-muted-foreground text-sm">
                {t(
                  "withdrawal.availableCommission",
                  "Available for withdrawal"
                )}
              </div>
              <div className="font-semibold text-xl">
                <Display type="currency" value={availableCommission} />
              </div>
              <Dialog onOpenChange={setWithdrawalOpen} open={withdrawalOpen}>
                <DialogTrigger asChild>
                  <Button>
                    {t("withdrawal.apply", "Apply for Withdrawal")}
                  </Button>
                </DialogTrigger>
                <DialogContent className="max-h-[90vh] overflow-y-auto">
                  <DialogHeader>
                    <DialogTitle>
                      {t("withdrawal.applyTitle", "Apply for Withdrawal")}
                    </DialogTitle>
                    <DialogDescription>
                      {t(
                        "withdrawal.applyDescription",
                        "Enter the withdrawal amount and payout details."
                      )}
                    </DialogDescription>
                  </DialogHeader>
                  <Form {...withdrawalForm}>
                    <form
                      className="space-y-4"
                      id="withdrawal-form"
                      onSubmit={withdrawalForm.handleSubmit(submitWithdrawal)}
                    >
                      <FormField
                        control={withdrawalForm.control}
                        name="amount"
                        render={({ field }) => (
                          <FormItem>
                            <FormLabel>
                              {t("withdrawal.amount", "Amount")}
                            </FormLabel>
                            <FormControl>
                              <Input
                                inputMode="decimal"
                                min="0"
                                onChange={(event) => {
                                  const cents = unitConversion(
                                    "dollarsToCents",
                                    Number(event.target.value || 0)
                                  );
                                  field.onChange(Number(cents) || 0);
                                }}
                                placeholder={t(
                                  "withdrawal.amountPlaceholder",
                                  "Enter withdrawal amount"
                                )}
                                step="0.01"
                                type="number"
                                value={
                                  field.value
                                    ? unitConversion(
                                        "centsToDollars",
                                        Number(field.value)
                                      )
                                    : ""
                                }
                              />
                            </FormControl>
                            <p className="text-muted-foreground text-xs">
                              {t("withdrawal.amountHint", "Available")}:{" "}
                              <Display
                                type="currency"
                                value={availableCommission}
                              />
                            </p>
                            <FormMessage />
                          </FormItem>
                        )}
                      />

                      <FormField
                        control={withdrawalForm.control}
                        name="method"
                        render={({ field }) => (
                          <FormItem>
                            <FormLabel>收款方式</FormLabel>
                            <Select
                              onValueChange={(val) => {
                                field.onChange(Number(val));
                                withdrawalForm.setValue("qr_code_url", "");
                                withdrawalForm.setValue("account", "");
                                withdrawalForm.clearErrors();
                              }}
                              value={String(field.value)}
                            >
                              <FormControl>
                                <SelectTrigger>
                                  <SelectValue placeholder="请选择收款方式" />
                                </SelectTrigger>
                              </FormControl>
                              <SelectContent>
                                {WITHDRAWAL_METHODS.map((m) => (
                                  <SelectItem
                                    key={m.value}
                                    value={String(m.value)}
                                  >
                                    {m.label}
                                  </SelectItem>
                                ))}
                              </SelectContent>
                            </Select>
                            <FormMessage />
                          </FormItem>
                        )}
                      />

                      {(watchedMethod === 1 || watchedMethod === 2) && (
                        <FormField
                          control={withdrawalForm.control}
                          name="qr_code_url"
                          render={() => (
                            <FormItem>
                              <FormLabel>
                                收款码
                                <span className="ml-1 text-destructive">
                                  *
                                </span>
                              </FormLabel>
                              {watchedQrCodeUrl ? (
                                <div className="relative inline-block">
                                  <QrCodeView url={watchedQrCodeUrl} />
                                  <button
                                    className="-top-2 -right-2 absolute flex h-5 w-5 items-center justify-center rounded-full bg-destructive text-destructive-foreground"
                                    onClick={() =>
                                      withdrawalForm.setValue("qr_code_url", "")
                                    }
                                    type="button"
                                  >
                                    <X className="h-3 w-3" />
                                  </button>
                                </div>
                              ) : (
                                <UploadImage
                                  className="h-24 w-24"
                                  id="qr-code-upload"
                                  onChange={handleQrUpload}
                                  returnType="file"
                                >
                                  <div className="flex h-24 w-24 flex-col items-center justify-center rounded border-2 border-dashed text-muted-foreground text-xs">
                                    {qrUploading ? "上传中..." : "点击上传\n收款码"}
                                  </div>
                                </UploadImage>
                              )}
                              <FormMessage />
                            </FormItem>
                          )}
                        />
                      )}

                      {(watchedMethod === 3 || watchedMethod === 0) && (
                        <FormField
                          control={withdrawalForm.control}
                          name="account"
                          render={({ field }) => (
                            <FormItem>
                              <FormLabel>
                                收款账号
                                {watchedMethod === 3 && (
                                  <span className="ml-1 text-destructive">
                                    *
                                  </span>
                                )}
                              </FormLabel>
                              <FormControl>
                                <Input
                                  placeholder={
                                    watchedMethod === 3
                                      ? "请输入银行卡号或账户信息"
                                      : "请输入收款账号（与备注至少填一项）"
                                  }
                                  {...field}
                                />
                              </FormControl>
                              <FormMessage />
                            </FormItem>
                          )}
                        />
                      )}

                      <FormField
                        control={withdrawalForm.control}
                        name="content"
                        render={({ field }) => (
                          <FormItem>
                            <FormLabel>备注</FormLabel>
                            <FormControl>
                              <Textarea
                                placeholder={
                                  watchedMethod === 0
                                    ? "备注（与账号至少填一项）"
                                    : "备注（可选）"
                                }
                                rows={3}
                                {...field}
                              />
                            </FormControl>
                            <FormMessage />
                          </FormItem>
                        )}
                      />
                    </form>
                  </Form>
                  <DialogFooter>
                    <Button
                      disabled={submitting}
                      onClick={() => setWithdrawalOpen(false)}
                      variant="outline"
                    >
                      {t("withdrawal.cancel", "Cancel")}
                    </Button>
                    <Button
                      disabled={
                        submitting ||
                        qrUploading ||
                        availableCommission <= 0
                      }
                      form="withdrawal-form"
                      type="submit"
                    >
                      {submitting
                        ? t("withdrawal.submitting", "Submitting...")
                        : t("withdrawal.submit", "Submit Withdrawal")}
                    </Button>
                  </DialogFooter>
                </DialogContent>
              </Dialog>
            </div>
          </div>
        </CardContent>
      </Card>
      <Card>
        <CardHeader className="flex flex-row items-center justify-between space-y-0">
          <CardTitle className="font-medium text-lg">
            {t("inviteCode", "Invite Code")}
          </CardTitle>
        </CardHeader>
        <CardContent>
          <div className="flex items-center justify-between">
            <code className="rounded bg-muted px-2 py-1 font-bold text-2xl">
              {user?.refer_code}
            </code>
            <CopyToClipboard
              onCopy={(_, result) => {
                if (result) {
                  toast.success(t("copySuccess", "Copy Success"));
                }
              }}
              text={`${location?.origin}/#/auth?invite=${user?.refer_code}`}
            >
              <Button className="gap-2" size="sm" variant="secondary">
                <Copy className="h-4 w-4" />
                {t("copyInviteLink", "Copy Invite Link")}
              </Button>
            </CopyToClipboard>
          </div>
        </CardContent>
      </Card>
      <ProList<API.WithdrawalLog, Record<string, unknown>>
        action={withdrawalListActionRef}
        header={{
          title: t("withdrawal.records", "Withdrawal Records"),
        }}
        renderItem={(item) => {
          const statusMeta = getWithdrawalStatusMeta(item.status, t);
          return (
            <Card className="overflow-hidden">
              <CardContent className="space-y-3 p-4 text-sm">
                <div className="flex flex-wrap items-center justify-between gap-2">
                  <div className="font-semibold text-lg">
                    <Display type="currency" value={item.amount} />
                  </div>
                  <div className="flex items-center gap-2">
                    <span
                      className={`inline-flex rounded-full px-3 py-1 font-medium text-xs ${statusMeta.className}`}
                    >
                      {statusMeta.label}
                    </span>
                    {item.status === 0 && (
                      <ConfirmButton
                        cancelText="取消"
                        confirmText="确认取消"
                        description="取消后该提现申请将关闭，佣金不会退还。确定取消吗？"
                        onConfirm={async () => {
                          await cancelMutation.mutateAsync(item.id);
                        }}
                        title="取消提现申请"
                        trigger={
                          <Button
                            disabled={cancelMutation.isPending}
                            size="sm"
                            variant="outline"
                          >
                            取消申请
                          </Button>
                        }
                      />
                    )}
                  </div>
                </div>
                <ul className="grid gap-3 md:grid-cols-2">
                  <li className="flex flex-col gap-1">
                    <span className="text-muted-foreground">收款方式</span>
                    <span>{getWithdrawalMethodLabel(item.method)}</span>
                  </li>
                  {item.account && (
                    <li className="flex flex-col gap-1">
                      <span className="text-muted-foreground">收款账号</span>
                      <span className="break-all">{item.account}</span>
                    </li>
                  )}
                  {item.qr_code_url && (
                    <li className="flex flex-col gap-1">
                      <span className="text-muted-foreground">收款码</span>
                      <QrCodeView url={item.qr_code_url} />
                    </li>
                  )}
                  {item.content && (
                    <li className="flex flex-col gap-1">
                      <span className="text-muted-foreground">
                        {t("withdrawal.record.content", "Payout Information")}
                      </span>
                      <span className="whitespace-pre-wrap break-words">
                        {item.content}
                      </span>
                    </li>
                  )}
                  <li className="flex flex-col gap-1">
                    <span className="text-muted-foreground">
                      {t("withdrawal.record.createdAt", "Created At")}
                    </span>
                    <time>{formatDate(item.created_at)}</time>
                  </li>
                  {item.reason && (
                    <li className="flex flex-col gap-1 md:col-span-2">
                      <span className="text-muted-foreground">
                        {t("withdrawal.record.reason", "Reject Reason")}
                      </span>
                      <span className="whitespace-pre-wrap break-words text-destructive">
                        {item.reason}
                      </span>
                    </li>
                  )}
                </ul>
              </CardContent>
            </Card>
          );
        }}
        request={async (pagination) => {
          const response = await queryWithdrawalLog({
            page: pagination.page,
            size: pagination.size,
          });
          return {
            list: response.data.data?.list || [],
            total: response.data.data?.total || 0,
          };
        }}
      />
      <ProList<API.UserAffiliate, Record<string, unknown>>
        header={{
          title: t("inviteRecords", "Invite Records"),
        }}
        renderItem={(item) => (
          <Card className="overflow-hidden">
            <CardContent className="p-3 text-sm">
              <ul className="grid grid-cols-2 gap-3 *:flex *:flex-col">
                <li className="font-semibold">
                  <span className="text-muted-foreground">
                    {t("userIdentifier", "User Identifier")}
                  </span>
                  <span>{item.identifier}</span>
                </li>
                <li className="font-semibold">
                  <span className="text-muted-foreground">
                    {t("registrationTime", "Registration Time")}
                  </span>
                  <time>{formatDate(item.registered_at)}</time>
                </li>
              </ul>
            </CardContent>
          </Card>
        )}
        request={async (pagination, filter) => {
          const response = await queryUserAffiliateList({
            ...pagination,
            ...filter,
          });
          return {
            list: response.data.data?.list || [],
            total: response.data.data?.total || 0,
          };
        }}
      />
    </div>
  );
}
