import { FileInput, Stack, TextInput, Textarea, Checkbox } from "@mantine/core";
import { useForm, UseFormInput } from "@mantine/form";
import { LinkIcon } from "@phosphor-icons/react";
import SlidePanel, { SlidePanelField } from "@/components/sheet/slide-panel";
import { TournamentInput } from "@/features/tournaments/types";
import { isNotEmpty } from "@mantine/form";
import useCreateTournament from "../hooks/use-create-tournament";
import useUpdateTournament from "../hooks/use-update-tournament";
import toast from "@/lib/sonner";
import { logger } from "..";
import { useQueryClient } from "@tanstack/react-query";
import { tournamentKeys } from "@/features/tournaments/queries";
import { useCallback } from "react";
import { DateTimePicker } from "@/components/date-time-picker";
import { useLingui } from "@lingui/react/macro";

interface TournamentFormProps {
  close: () => void;
  initialValues?: Partial<TournamentInput>;
  tournamentId?: string;
}

const TournamentForm = ({
  close,
  initialValues,
  tournamentId,
}: TournamentFormProps) => {
  const isEditMode = !!tournamentId;
  const { t, i18n } = useLingui();

  const config: UseFormInput<TournamentInput> = {
    initialValues: {
      name: initialValues?.name || "",
      location: initialValues?.location || "",
      desc: initialValues?.desc || "",
      start_time: initialValues?.start_time || "",
      enroll_time: initialValues?.enroll_time || "",
      end_time: initialValues?.end_time || "",
      logo: undefined,
      regional: initialValues?.regional || false,
    },
    onSubmitPreventDefault: "always",
    validate: {
      name: isNotEmpty(t`Name is required`),
      location: isNotEmpty(t`Location is required`),
      start_time: isNotEmpty(t`Start time is required`),
      enroll_time: isNotEmpty(t`Enrollment time is required`),
    },
  };

  const form = useForm(config);
  const queryClient = useQueryClient();

  const { mutate: createTournament, isPending: createPending } =
    useCreateTournament();
  const { mutate: updateTournament, isPending: updatePending } =
    useUpdateTournament(tournamentId || "");

  const isPending = createPending || updatePending;

  const handleSubmit = useCallback(
    async (values: TournamentInput) => {
      const { logo, ...tournamentData } = values;

      const mutation = isEditMode ? updateTournament : createTournament;
      const successMessage = isEditMode
        ? t`Tournament updated successfully!`
        : t`Tournament created successfully!`;
      const errorMessage = isEditMode
        ? t`Failed to update tournament`
        : t`Failed to create tournament`;

      mutation(tournamentData, {
        onSuccess: async (tournament) => {
          if (logo && tournament) {
            try {
              const formData = new FormData();
              formData.append("tournamentId", tournament.id);
              formData.append("logo", logo);

              const response = await fetch("/api/tournaments/upload-logo", {
                method: "POST",
                body: formData,
              });

              if (!response.ok) {
                const error = await response.json();
                throw new Error(error.error || t`Failed to upload logo`);
              }

              const result = await response.json();

              queryClient.invalidateQueries({ queryKey: tournamentKeys.list });
              queryClient.invalidateQueries({
                queryKey: tournamentKeys.details(result.tournament!.id),
              });
              queryClient.setQueryData(
                tournamentKeys.details(result.tournament!.id),
                result.tournament
              );

              toast.success(successMessage);
            } catch (error: any) {
              const logoErrorMessage = isEditMode
                ? t`Tournament updated but logo upload failed: ${error.message}`
                : t`Tournament created but logo upload failed: ${error.message}`;
              toast.error(logoErrorMessage);
              logger.error("Tournament logo upload error", error);
            }
          } else {
            toast.success(successMessage);
          }
          close();
        },
        onError: (error: any) => {
          toast.error(`${errorMessage}: ${error.message}`);
          logger.error(
            `Tournament ${isEditMode ? "update" : "create"} error`,
            error
          );
        },
      });
    },
    [isEditMode, createTournament, updateTournament, queryClient]
  );

  return (
    <SlidePanel
      onSubmit={form.onSubmit(handleSubmit)}
      onCancel={close}
      submitText={isEditMode ? t`Update Tournament` : t`Create Tournament`}
      cancelText={t`Cancel`}
      loading={isPending}
    >
      <Stack>
        <TextInput
          label={t`Name`}
          withAsterisk
          key={form.key("name")}
          {...form.getInputProps("name")}
        />
        <TextInput
          label={t`Location`}
          withAsterisk
          key={form.key("location")}
          {...form.getInputProps("location")}
        />

        <Textarea
          label={t`Description`}
          key={form.key("desc")}
          {...form.getInputProps("desc")}
          minRows={3}
        />

        <Checkbox
          label={t`Regional Tournament`}
          key={form.key("regional")}
          {...form.getInputProps("regional", { type: "checkbox" })}
        />

        <FileInput
          key={form.key("logo")}
          accept="image/png,image/jpeg,image/gif,image/jpg"
          label={isEditMode ? t`Change Logo` : t`Logo`}
          leftSection={<LinkIcon size={16} />}
          {...form.getInputProps("logo")}
        />

        <SlidePanelField
          key={form.key("start_time")}
          {...form.getInputProps("start_time")}
          Component={DateTimePicker}
          title={t`Select Start Date`}
          label={t`Start Date`}
          withAsterisk
          formatValue={(date) =>
            !date ? t`Select a time` :
            new Date(date).toLocaleDateString(i18n.locale, {
              weekday: "short",
              year: "numeric",
              month: "short",
              day: "numeric",
              hour: "numeric",
              minute: "numeric",
              hour12: true,
            })
          }
        />

        <SlidePanelField
          key={form.key("enroll_time")}
          {...form.getInputProps("enroll_time")}
          Component={DateTimePicker}
          title={t`Select Enrollment Due Date`}
          label={t`Enrollment Due`}
          withAsterisk
          formatValue={(date) =>
            !date ? t`Select a time` :
            new Date(date).toLocaleDateString(i18n.locale, {
              weekday: "short",
              year: "numeric",
              month: "short",
              day: "numeric",
              hour: "numeric",
              minute: "numeric",
              hour12: true,
            })
          }
        />

        {isEditMode && (
          <SlidePanelField
            key={form.key("end_time")}
            {...form.getInputProps("end_time")}
            Component={DateTimePicker}
            title={t`Select End Date`}
            label={t`End Date (Optional)`}
            formatValue={(date) =>
              !date ? t`Select a time` :
              new Date(date).toLocaleDateString(i18n.locale, {
                weekday: "short",
                year: "numeric",
                month: "short",
                day: "numeric",
                hour: "numeric",
                minute: "numeric",
                hour12: true,
              })
            }
          />
        )}
      </Stack>
    </SlidePanel>
  );
};

export default TournamentForm;
