import { FormServerErrors } from "@/components/form-common/form-server-errors";
import { FormSubmit } from "@/components/form-common/form-submit";
import { useLabFeedback } from "@/components/labs/hook";
import { formInputProps } from "@/components/tanstack-form-utils";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { StarRating } from "@/components/ui/star-rating";
import { Textarea } from "@/components/ui/textarea";
import { useLocaleFunction } from "@/hooks/use-localed";
import { submitLabFeedback } from "@/lib/api/labs";
import { handleFormElementSubmitEvent, handleSubmitErrors } from "@/lib/form";
import { type ReactFormApi, useForm } from "@tanstack/react-form";
import { useEffect, useState } from "react";

export default function LabFeedback({ labCode }: { labCode: string }) {
  const { data, isLoading, refetch } = useLabFeedback(labCode);

  const [open, setOpen] = useState(false);
  const [initialRating, setInitialRating] = useState<number | undefined>(
    undefined
  );

  const t = useLocaleFunction();

  useEffect(() => {
    if (data) {
      setInitialRating(data.rating_score);
    }
  }, [data]);

  return (
    <>
      <div className="flex items-center justify-between">
        <StarRating
          disabled={isLoading}
          rating={data?.rating_score ?? 0}
          onRate={(rate) => {
            setInitialRating(rate);
            setOpen(true);
          }}
        />
      </div>
      <Dialog open={open} onOpenChange={setOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>{t("lab.feedback")}</DialogTitle>
            <DialogDescription className="sr-only" />
          </DialogHeader>
          {(data != null || initialRating != null) && (
            <LabFeedbackForm
              labCode={labCode}
              initialRating={initialRating ?? 0}
              initialComment={data?.comment ?? ""}
              onSubmitted={() => {
                void refetch();
                setOpen(false);
              }}
            />
          )}
        </DialogContent>
      </Dialog>
    </>
  );
}

export type LabFeedbackFormData = {
  rating_score: number;
  comment: string;
};

function LabFeedbackForm({
  labCode,
  disabled,
  initialRating,
  initialComment,
  onSubmitted,
}: {
  labCode: string;
  disabled?: boolean;
  initialRating: number;
  initialComment: string;
  onSubmitted: () => void;
}) {
  const t = useLocaleFunction();

  const form = useForm({
    defaultValues: {
      rating_score: initialRating,
      comment: initialComment,
    },
    async onSubmit({ value, formApi }) {
      await handleSubmitErrors(formApi, async () => {
        await submitLabFeedback(labCode, value);
        onSubmitted();
      });
    },
  });

  useEffect(() => {
    form.update({
      defaultValues: {
        rating_score: initialRating,
        comment: initialComment,
      },
    });
  }, [form, initialRating, initialComment]);

  return (
    <form className="space-y-4" onSubmit={handleFormElementSubmitEvent(form)}>
      <LabFeedbackRatingField form={form} disabled={disabled} />
      <LabFeedbackCommentField form={form} disabled={disabled} />
      <FormServerErrors formApi={form} title={t("lab.feedback.failed")} />
      <FormSubmit formApi={form} disabled={disabled}>
        {t("lab.feedback.form-submit")}
      </FormSubmit>
    </form>
  );
}

export function LabFeedbackRatingField({
  form,
  disabled,
}: {
  form: ReactFormApi<
    LabFeedbackFormData,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any
  >;
  disabled?: boolean;
}) {
  return (
    <form.Field name="rating_score">
      {(field) => (
        <StarRating
          rating={field.state.value}
          onRate={field.handleChange}
          disabled={field.form.state.isSubmitting || disabled}
        />
      )}
    </form.Field>
  );
}

export function LabFeedbackCommentField({
  form,
  disabled,
}: {
  form: ReactFormApi<
    LabFeedbackFormData,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any
  >;
  disabled?: boolean;
}) {
  const t = useLocaleFunction();

  return (
    <form.Field name="comment">
      {(field) => (
        <Textarea
          {...formInputProps(field, disabled)}
          placeholder={t("lab.feedback.form.comment")}
        />
      )}
    </form.Field>
  );
}
