import { useMutation, useQueryClient } from "@tanstack/react-query";
import { useState } from "react";
import { toast } from "sonner";

import { BillingStatus, config } from "@turbostarter/billing";
import { isKey, useTranslation } from "@turbostarter/i18n";
import {
  Avatar,
  AvatarFallback,
  AvatarImage,
} from "@turbostarter/ui-web/avatar";
import { Badge } from "@turbostarter/ui-web/badge";
import { Button } from "@turbostarter/ui-web/button";
import { DataTableColumnHeader } from "@turbostarter/ui-web/data-table/data-table-column-header";
import {
  DropdownMenu,
  DropdownMenuTrigger,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
} from "@turbostarter/ui-web/dropdown-menu";
import { Icons } from "@turbostarter/ui-web/icons";

import { pathsConfig } from "~/config/paths";
import { authClient } from "~/lib/auth/client";
import { admin } from "~/modules/admin/lib/api";
import { TurboLink } from "~/modules/common/turbo-link";

import { CreditsDialog } from "../components/credits-dialog";
import { invalidateCustomers } from "../server/invalidate";
import { UpdateCustomerPlanModal } from "../update-customer-plan";

import type { ColumnDef } from "@tanstack/react-table";
import type { User } from "@turbostarter/auth";
import type { Customer } from "@turbostarter/billing";

export const CustomerActions = ({
  customer,
}: {
  customer: Customer & { user: Pick<User, "name">; credits: number };
}) => {
  const { t } = useTranslation(["common", "admin", "billing"]);
  const queryClient = useQueryClient();
  const [creditsDialogOpen, setCreditsDialogOpen] = useState(false);

  const deleteCustomer = useMutation({
    ...admin.mutations.customers.delete,
    onSuccess: async () => {
      await invalidateCustomers();
      await queryClient.invalidateQueries(
        admin.queries.users.getPlans({
          id: customer.userId,
        }),
      );
      toast.success(t("customers.customer.delete.success"));
    },
  });

  return (
    <>
      <DropdownMenu>
        <DropdownMenuTrigger asChild>
          <Button variant="ghost" size="icon">
            <span className="sr-only">{t("actions")}</span>
            <Icons.Ellipsis className="size-4" />
          </Button>
        </DropdownMenuTrigger>
        <DropdownMenuContent align="end" className="w-40">
          <UpdateCustomerPlanModal
            customer={customer}
            key={`update-plan-${customer.id}`}
          >
            <DropdownMenuItem onSelect={(e) => e.preventDefault()}>
              {t("updatePlan")}
            </DropdownMenuItem>
          </UpdateCustomerPlanModal>
          <DropdownMenuItem onSelect={() => setCreditsDialogOpen(true)}>
            <Icons.HandCoins className="mr-2 size-4" />
            {t("manageCredits", { defaultValue: "Manage Credits" })}
          </DropdownMenuItem>
          <DropdownMenuSeparator />
          {(() => {
            const isPending =
              deleteCustomer.isPending &&
              deleteCustomer.variables.id === customer.id;

            return (
              <DropdownMenuItem
                variant="destructive"
                onClick={() =>
                  deleteCustomer.mutate({
                    id: customer.id,
                  })
                }
                disabled={isPending}
                key={`remove-${customer.id}`}
              >
                {t("delete")}
                {isPending && (
                  <Icons.Loader2 className="ml-auto animate-spin text-current" />
                )}
              </DropdownMenuItem>
            );
          })()}
        </DropdownMenuContent>
      </DropdownMenu>

      <CreditsDialog
        open={creditsDialogOpen}
        onOpenChange={setCreditsDialogOpen}
        customer={customer}
      />
    </>
  );
};

export const useColumns = (): ColumnDef<
  Customer & { user: Pick<User, "name" | "image">; credits: number }
>[] => {
  const { t, i18n } = useTranslation(["common", "billing"]);
  const { data: session } = authClient.useSession();

  return [
    {
      id: "q",
      accessorKey: "q",
      meta: {
        placeholder: `${t("searchPlaceholder")}`,
        variant: "text",
      },
      enableHiding: false,
      enableColumnFilter: true,
    },
    {
      id: "user.name",
      accessorKey: "user.name",
      header: ({ column }) => (
        <DataTableColumnHeader column={column} title={t("name")} />
      ),
      cell: ({ row }) => {
        return (
          <TurboLink
            href={pathsConfig.admin.users.user(row.original.userId)}
            className="group flex items-center gap-3"
          >
            <Avatar>
              <AvatarImage
                src={row.original.user.image ?? undefined}
                alt={row.original.user.name}
              />
              <AvatarFallback>
                <Icons.UserRound className="w-5" />
              </AvatarFallback>
            </Avatar>
            <div className="flex items-center gap-2">
              <span className="group-hover:text-primary truncate font-medium underline underline-offset-4">
                {row.original.user.name}
              </span>
              {row.original.userId === session?.user.id && (
                <Badge variant="outline">{t("you")}</Badge>
              )}
            </div>
          </TurboLink>
        );
      },
      enableHiding: false,
    },
    {
      id: "customerId",
      accessorKey: "customerId",
      header: ({ column }) => (
        <DataTableColumnHeader column={column} title={t("id")} />
      ),
      meta: {
        label: t("id"),
      },
    },
    {
      id: "plan",
      accessorKey: "plan",
      header: ({ column }) => (
        <DataTableColumnHeader column={column} title={t("common:plan")} />
      ),
      cell: ({ row }) => {
        const plan = config.plans.find((plan) => plan.id === row.original.plan);

        if (!plan) {
          return <span>-</span>;
        }

        return (
          <Badge variant="outline">
            {isKey(plan.name, i18n, "billing") ? t(plan.name) : plan.name}
          </Badge>
        );
      },
      meta: {
        label: t("common:plan"),
        variant: "multiSelect",
        options: Object.values(config.plans).map((plan) => ({
          label: isKey(plan.name, i18n, "billing") ? t(plan.name) : plan.name,
          value: plan.id,
        })),
      },
      enableColumnFilter: true,
    },
    {
      id: "status",
      accessorKey: "status",
      header: ({ column }) => (
        <DataTableColumnHeader column={column} title={t("common:status")} />
      ),
      cell: ({ row }) => {
        const statusKey = `status.${row.original.status?.replace(/_([a-z])/g, (_, letter: string) => letter.toUpperCase())}`;

        if (!row.original.status) {
          return <span>-</span>;
        }

        return (
          <Badge variant="secondary">
            {isKey(statusKey, i18n, "billing") ? t(statusKey) : statusKey}
          </Badge>
        );
      },
      meta: {
        label: t("common:status"),
        variant: "multiSelect",
        options: Object.values(BillingStatus).map((status) => {
          const statusKey = `status.${status.replace(/_([a-z])/g, (_, letter: string) => letter.toUpperCase())}`;
          return {
            label: isKey(statusKey, i18n, "billing") ? t(statusKey) : statusKey,
            value: status,
          };
        }),
      },
      enableColumnFilter: true,
    },
    {
      id: "credits",
      accessorKey: "credits",
      header: ({ column }) => (
        <DataTableColumnHeader column={column} title="Credits" />
      ),
      cell: ({ row }) => {
        return (
          <div className="flex items-center gap-1.5">
            <Icons.HandCoins className="size-4 text-muted-foreground" />
            <span className="font-medium tabular-nums">
              {row.original.credits.toLocaleString()}
            </span>
          </div>
        );
      },
      meta: {
        label: "Credits",
      },
    },
    {
      id: "createdAt",
      accessorKey: "createdAt",
      header: ({ column }) => (
        <div className="ml-auto w-fit">
          <DataTableColumnHeader column={column} title={t("createdAt")} />
        </div>
      ),
      cell: ({ row }) => {
        return (
          <div className="ml-auto text-right">
            {row.original.createdAt.toLocaleDateString(i18n.language)}
          </div>
        );
      },
      meta: {
        label: t("createdAt"),
        variant: "dateRange",
      },
      enableColumnFilter: true,
    },
    {
      id: "actions",
      cell: ({ row }) => (
        <div className="ml-auto w-fit">
          <CustomerActions customer={row.original} />
        </div>
      ),
      enableHiding: false,
    },
  ];
};
