"use client";

import { FormServerErrors } from "@/components/form-common/form-server-errors";
import { FormSubmit } from "@/components/form-common/form-submit";
import { useLabs } from "@/components/labs/hook";
import {
  type LabMetaV2,
  tidbEnvironmentLocaleKey,
} from "@/components/labs/hooks-v2";
import { useMe, useMyWorkshops } from "@/components/me-context";
import { NextLink } from "@/components/next-link";
import {
  fieldItemProps,
  fieldMessageProps,
  formInputProps,
} from "@/components/tanstack-form-utils";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuSub,
  DropdownMenuSubContent,
  DropdownMenuSubTrigger,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Input } from "@/components/ui/input";
import { ScrollArea } from "@/components/ui/scroll-area";
import {
  type LocaleFunction,
  useLocale,
  useLocaleFunction,
} from "@/hooks/use-localed";
import { toast } from "@/hooks/use-toast";
import { useLoginUrl } from "@/hooks/use-url";
import { client } from "@/lib/api-client";
import { logout, redeemEvent, type User, type Workshop } from "@/lib/api/labs";
import { handleFormElementSubmitEvent, handleSubmitErrors } from "@/lib/form";
import { type Locale, transformPathLocale } from "@/lib/locale";
import { isTrustedUser } from "@/lib/users";
import { cn } from "@/lib/utils";
import { useForm } from "@tanstack/react-form";
import { formatDate, isSameDay } from "date-fns";
import {
  BadgeIcon,
  BadgePlusIcon,
  ChevronDownIcon,
  LogOutIcon,
  TicketCheckIcon,
  UserPenIcon,
} from "lucide-react";
import type { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
import { useRouter } from "next/navigation";
import {
  type TransitionStartFunction,
  useId,
  useMemo,
  useState,
  useTransition,
} from "react";
import { z } from "zod";

export default function SiteHeaderUser({ className }: { className?: string }) {
  const { data: me, isLoading } = useMe();
  const router = useRouter();
  const [, startTransition] = useTransition();
  const loginUrl = useLoginUrl();

  const t = useLocaleFunction();

  const locale = useLocale();
  const trusted = isTrustedUser(me);

  if (!me) {
    return (
      <NextLink
        className={className}
        variant="outline"
        href={loginUrl}
        disabled={isLoading}
      >
        {t("header.user.sign-up-in")}
      </NextLink>
    );
  }

  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button
          className={cn(
            "focus-visible:ring-primary hover:bg-primary/10",
            className
          )}
          variant="ghost"
        >
          {me.name ?? me.email}
          <ChevronDownIcon />
        </Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent align="end" className="min-w-[200px] w-max">
        <DropdownMenuLabel>{me.email}</DropdownMenuLabel>
        <DropdownMenuSeparator />
        {!trusted && (
          <>
            <DropdownMenuGroup>
              <CreditsItem me={me} t={t} />
              <GetCreditsItem t={t} />
              <RedeemVoucherCodeItem />
              <Workshops />
            </DropdownMenuGroup>
            <DropdownMenuSeparator />
          </>
        )}
        <DropdownMenuGroup>
          <ProfileItem t={t} />
          <LogoutItem
            startTransition={startTransition}
            router={router}
            locale={locale}
            t={t}
          />
        </DropdownMenuGroup>
      </DropdownMenuContent>
    </DropdownMenu>
  );
}

export function SiteHeaderUserMobile({ className }: { className?: string }) {
  const { data: me, isLoading } = useMe();
  const router = useRouter();
  const [, startTransition] = useTransition();
  const loginUrl = useLoginUrl();

  const t = useLocaleFunction();

  const locale = useLocale();
  const trusted = isTrustedUser(me);

  if (!me) {
    return (
      <DropdownMenuItem>
        <NextLink
          className={className}
          noStyle
          href={loginUrl}
          disabled={isLoading}
        >
          {t("header.user.sign-up-in")}
        </NextLink>
      </DropdownMenuItem>
    );
  }

  return (
    <>
      <DropdownMenuSeparator />
      <DropdownMenuLabel>{me.email}</DropdownMenuLabel>
      {!trusted && (
        <>
          <DropdownMenuGroup>
            <CreditsItem me={me} t={t} />
            <GetCreditsItem t={t} />
            <RedeemVoucherCodeItem />
          </DropdownMenuGroup>
          <DropdownMenuSeparator />
        </>
      )}
      <ProfileItem t={t} />
      <DropdownMenuGroup>
        <LogoutItem
          startTransition={startTransition}
          router={router}
          locale={locale}
          t={t}
        />
      </DropdownMenuGroup>
    </>
  );
}

const nf = Intl.NumberFormat("en");

function CreditsItem({ t, me }: { t: LocaleFunction; me: User }) {
  return (
    <DropdownMenuItem>
      <NextLink
        href="/credits"
        noStyle
        className="flex w-full items-center justify-between"
      >
        {t("header.user.credits", nf.format(me.credits))}
        <BadgeIcon className="size-4 ml-auto" />
      </NextLink>
    </DropdownMenuItem>
  );
}

function GetCreditsItem({ t }: { t: LocaleFunction }) {
  return (
    <DropdownMenuItem>
      <NextLink
        href="/get-credits"
        noStyle
        className="flex w-full items-center justify-between"
      >
        {t("lab.get-credits")}
        <BadgePlusIcon className="size-4 ml-auto" />
      </NextLink>
    </DropdownMenuItem>
  );
}

function ProfileItem({ t }: { t: LocaleFunction }) {
  return (
    <DropdownMenuItem>
      <NextLink
        href="/profile"
        noStyle
        className="flex w-full items-center justify-between"
      >
        {t("header.user.profile")}
        <UserPenIcon className="size-4" />
      </NextLink>
    </DropdownMenuItem>
  );
}

const redeemVoucherCodeFormSchema = z.object({
  event_voucher_code: z.string().min(1),
});

function RedeemVoucherCodeItem() {
  const id = useId();
  const [open, setOpen] = useState(false);

  const form = useForm({
    validators: {
      onSubmit: redeemVoucherCodeFormSchema,
    },
    defaultValues: {
      event_voucher_code: "",
    },
    async onSubmit({ value }) {
      await handleSubmitErrors(form, async () => {
        const result = await redeemEvent(value);
        void client.refetchQueries({
          queryKey: ["user.me.workshops"],
        });
        setOpen(false);
        toast({
          title: t("header.user.redeem.succeed"),
          description: result.message,
        });
      });
    },
  });

  const t = useLocaleFunction();

  return (
    <Dialog open={open} onOpenChange={setOpen}>
      <DialogTrigger asChild>
        <DropdownMenuItem
          className="cursor-pointer"
          onSelect={(event) => event.preventDefault()}
        >
          {t("header.user.redeem")}
          <TicketCheckIcon className="ml-auto" />
        </DropdownMenuItem>
      </DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>{t("header.user.redeem.title")}</DialogTitle>
          <DialogDescription className="sr-only" />
        </DialogHeader>
        <form
          id="redeem"
          className="w-full space-y-4"
          onSubmit={handleFormElementSubmitEvent(form)}
        >
          <form.Field name="event_voucher_code">
            {(field) => (
              <div className="space-y-2">
                <Input
                  placeholder={t("header.user.redeem.enter-voucher-code")}
                  {...fieldItemProps(field, id)}
                  {...formInputProps(field)}
                />
                <p {...fieldMessageProps(field, id)} />
              </div>
            )}
          </form.Field>
          <FormServerErrors
            formApi={form}
            title={t("header.user.redeem.failed")}
          />
        </form>
        <DialogFooter>
          <FormSubmit formApi={form} form="redeem">
            {t("header.user.redeem")}
          </FormSubmit>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

function LogoutItem({
  startTransition,
  router,
  locale,
  t,
}: {
  startTransition: TransitionStartFunction;
  router: AppRouterInstance;
  locale: Locale;
  t: LocaleFunction;
}) {
  return (
    <DropdownMenuItem
      className="cursor-pointer"
      onSelect={(event) => {
        event.preventDefault();
        startTransition(async () => {
          await logout();
          client.refetchQueries({ type: "all" }).catch(() => {});
          startTransition(() => {
            router.push(transformPathLocale("/", locale));
            router.refresh();
          });
        });
      }}
    >
      {t("header.user.logout")}
      <LogOutIcon className="ml-auto" />
    </DropdownMenuItem>
  );
}

function Workshops() {
  const t = useLocaleFunction();
  const { data: labs } = useLabs();

  const { data: workshops, isLoading } = useMyWorkshops();

  const hasAnyWorkshop =
    !!workshops?.upcoming_workshops.length ||
    !!workshops?.happening_workshops.length;

  return (
    <DropdownMenuSub>
      <DropdownMenuSubTrigger>{t("workshops.title")}</DropdownMenuSubTrigger>
      <DropdownMenuSubContent>
        {isLoading && (
          <DropdownMenuLabel className="text-muted-foreground">
            {t("common.loading")}
          </DropdownMenuLabel>
        )}
        {!isLoading && !hasAnyWorkshop && (
          <DropdownMenuLabel className="text-muted-foreground">
            {t("workshops.empty")}
          </DropdownMenuLabel>
        )}
        {!!workshops?.happening_workshops?.length && (
          <DropdownMenuGroup>
            <DropdownMenuLabel className="text-muted-foreground">
              {t("workshops.happening")}
            </DropdownMenuLabel>
            {workshops.happening_workshops.map((workshop) => (
              <WorkshopLabItems
                key={workshop.id}
                workshop={workshop}
                labs={labs}
              />
            ))}
          </DropdownMenuGroup>
        )}
        {!!workshops?.upcoming_workshops?.length && (
          <DropdownMenuGroup>
            <DropdownMenuLabel className="text-muted-foreground">
              {t("workshops.upcoming")}
            </DropdownMenuLabel>
            {workshops.upcoming_workshops.map((workshop) => (
              <WorkshopLabItems
                key={workshop.id}
                workshop={workshop}
                labs={labs}
              />
            ))}
          </DropdownMenuGroup>
        )}
      </DropdownMenuSubContent>
    </DropdownMenuSub>
  );
}

function WorkshopLabItems({
  labs,
  workshop,
}: {
  labs?: LabMetaV2[];
  workshop: Workshop;
}) {
  const t = useLocaleFunction();

  const workshopLabs = useMemo(() => {
    return (
      workshop.lab_codes
        .map((code) => labs?.find((lab) => lab.lab_code === code))
        ?.filter((lab) => !!lab) ?? []
    );
  }, [labs, workshop.lab_codes]);

  return (
    <DropdownMenuSub>
      <DropdownMenuSubTrigger>
        <div>
          <div>{workshop.workshop_name}</div>
          <div className="text-xs text-muted-foreground">
            {isSameDay(workshop.start_begin_date, workshop.start_end_date)
              ? formatDate(workshop.start_begin_date, "yyyy-MM-dd")
              : `${formatDate(workshop.start_begin_date, "yyyy-MM-dd")} - ${formatDate(workshop.start_end_date, "yyyy-MM-dd")}`}
          </div>
        </div>
      </DropdownMenuSubTrigger>
      <DropdownMenuSubContent>
        <ScrollArea className="flex max-h-[50vh] flex-col overflow-y-auto">
          {!labs && (
            <DropdownMenuLabel>{t("common.loading")}</DropdownMenuLabel>
          )}
          {workshopLabs?.map((lab) => (
            <NextLink
              key={lab.lab_code}
              href={`/labs/${encodeURIComponent(lab.lab_code)}`}
              noStyle
            >
              <DropdownMenuItem className="block cursor-pointer">
                <div>{t(lab, "title")}</div>
                <div className="text-xs text-muted-foreground">
                  {lab.tidb_environments
                    .map((environment) =>
                      t(tidbEnvironmentLocaleKey(environment) as never)
                    )
                    .join(", ")}
                  {" | "}
                  {t("lab.duration-minutes", lab.estimated_duration_minutes)}
                </div>
                <div className="text-xs text-muted-foreground">
                  {([] as string[]).concat(t(lab, "category")).join(" ")}
                </div>
              </DropdownMenuItem>
            </NextLink>
          ))}
        </ScrollArea>
      </DropdownMenuSubContent>
    </DropdownMenuSub>
  );
}
