"use client";

import { zodResolver } from "@hookform/resolvers/zod";
import { 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 { Textarea } from "@workspace/ui/components/textarea";
import type { ProListActions } from "@workspace/ui/composed/pro-list/pro-list";
import { ProList } from "@workspace/ui/composed/pro-list/pro-list";
import {
  commissionWithdraw,
  queryUserAffiliate,
  queryUserAffiliateList,
  queryWithdrawalLog,
} from "@workspace/ui/services/user/user";
import { formatDate } from "@workspace/ui/utils/formatting";
import { unitConversion } from "@workspace/ui/utils/unit-conversions";
import { Copy } 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";

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",
      };
    default:
      return {
        label: t("withdrawal.status.pending", "Pending"),
        className: "bg-amber-500/10 text-amber-600",
      };
  }
}

export default function Affiliate() {
  const { t } = useTranslation("affiliate");
  const { user, common, getUserInfo } = useGlobalStore();
  const [withdrawalOpen, setWithdrawalOpen] = useState(false);
  const [submitting, startTransition] = useTransition();
  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 withdrawalFormSchema = z.object({
    amount: z
      .number()
      .int(t("withdrawal.validation.amountInvalid", "Amount is invalid"))
      .positive(
        t(
          "withdrawal.validation.amountPositive",
          "Amount must be greater than 0"
        )
      )
      .max(
        availableCommission,
        t(
          "withdrawal.validation.amountExceeded",
          "Amount cannot exceed available commission"
        )
      ),
    content: z
      .string()
      .trim()
      .min(
        1,
        t(
          "withdrawal.validation.contentRequired",
          "Withdrawal info is required"
        )
      )
      .max(
        1000,
        t("withdrawal.validation.contentTooLong", "Withdrawal info is too long")
      ),
  });
  const withdrawalForm = useForm<z.infer<typeof withdrawalFormSchema>>({
    resolver: zodResolver(withdrawalFormSchema),
    defaultValues: {
      amount: 0,
      content: "",
    },
  });

  const submitWithdrawal = (values: z.infer<typeof withdrawalFormSchema>) => {
    startTransition(async () => {
      await commissionWithdraw({
        amount: values.amount,
        content: values.content.trim(),
      });
      toast.success(
        t("withdrawal.submitSuccess", "Withdrawal request submitted")
      );
      await Promise.all([
        affiliateQuery.refetch(),
        getUserInfo(),
        withdrawalListActionRef.current?.refresh(),
      ]);
      setWithdrawalOpen(false);
      withdrawalForm.reset({
        amount: 0,
        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>
                  <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="content"
                        render={({ field }) => (
                          <FormItem>
                            <FormLabel>
                              {t("withdrawal.content", "Payout Information")}
                            </FormLabel>
                            <FormControl>
                              <Textarea
                                placeholder={t(
                                  "withdrawal.contentPlaceholder",
                                  "Bank account, wallet address, recipient name, or other payout details"
                                )}
                                rows={4}
                                {...field}
                              />
                            </FormControl>
                            <FormMessage />
                          </FormItem>
                        )}
                      />
                    </form>
                  </Form>
                  <DialogFooter>
                    <Button
                      disabled={submitting}
                      onClick={() => setWithdrawalOpen(false)}
                      variant="outline"
                    >
                      {t("withdrawal.cancel", "Cancel")}
                    </Button>
                    <Button
                      disabled={submitting || 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>
                  <span
                    className={`inline-flex rounded-full px-3 py-1 font-medium text-xs ${statusMeta.className}`}
                  >
                    {statusMeta.label}
                  </span>
                </div>
                <ul className="grid gap-3 md:grid-cols-2">
                  <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>
                  ) : null}
                </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>
  );
}
