"use client";

import { submitCommissionRequest } from "@/actions/commissions/submitCommissionRequest";
import { Button } from "@/components/ui/button";
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import type {
  CommissionCustomInput,
  CommissionCustomCard,
  CommissionCustomCardExtra,
  CommissionCustomCardOption,
  CommissionExtra,
  CommissionOption,
  CommissionType,
  CommissionTypeCustomInput,
  CommissionTypeExtra,
  CommissionTypeOption,
} from "@/generated/prisma/client";
import { commissionOrderSchema } from "@/schemas/commissionOrder";
import { calculatePriceRange } from "@/utils/calculatePrice";
import { zodResolver } from "@hookform/resolvers/zod";
import Link from "next/link";
import { useMemo, useState } from "react";
import { useForm, useWatch } from "react-hook-form";
import { toast } from "sonner";
import type * as z from "zod/v4";
import { FileDropzone } from "./FileDropzone";

type CommissionTypeWithRelations = CommissionType & {
  options: (CommissionTypeOption & { option: CommissionOption })[];
  extras: (CommissionTypeExtra & { extra: CommissionExtra })[];
  customInputs: (CommissionTypeCustomInput & { customInput: CommissionCustomInput })[];
};

type CommissionCustomCardWithRelations = CommissionCustomCard & {
  options: (CommissionCustomCardOption & { option: CommissionOption })[];
  extras: (CommissionCustomCardExtra & { extra: CommissionExtra })[];
};

type Props = {
  types: CommissionTypeWithRelations[];
  customCards: CommissionCustomCardWithRelations[];
};

type SelectedOption = {
  id: string;
  optionId: string;
  option: CommissionOption;
  price: number | null;
  pricePercent: number | null;
  priceRange: string | null;
};

type SelectedExtra = {
  id: string;
  extraId: string;
  extra: CommissionExtra;
  price: number | null;
  pricePercent: number | null;
  priceRange: string | null;
};

export function CommissionOrderForm({ types, customCards }: Props) {
  const form = useForm<z.infer<typeof commissionOrderSchema>>({
    resolver: zodResolver(commissionOrderSchema),
    defaultValues: {
      typeId: "",
      customCardId: "",
      optionId: "",
      extraIds: [],
      customerName: "",
      customerEmail: "",
      customerSocials: "",
      message: "",
    },
  });

  const [files, setFiles] = useState<File[]>([]);
  const [isSubmitting, setIsSubmitting] = useState(false);

  const typeId = useWatch({ control: form.control, name: "typeId" });
  const customCardId = useWatch({ control: form.control, name: "customCardId" });
  const optionId = useWatch({ control: form.control, name: "optionId" });
  const extraIds = useWatch({ control: form.control, name: "extraIds" });

  const selectedType = useMemo(() => types.find((t) => t.id === typeId), [types, typeId]);
  const selectedCustomCard = useMemo(
    () => customCards.find((c) => c.id === customCardId),
    [customCards, customCardId]
  );

  const selection = useMemo<{
    kind: "type" | "custom";
    name: string;
    options: SelectedOption[];
    extras: SelectedExtra[];
  } | null>(() => {
    if (selectedCustomCard) {
      return {
        kind: "custom",
        name: selectedCustomCard.name,
        options: selectedCustomCard.options,
        extras: selectedCustomCard.extras,
      };
    }
    if (selectedType) {
      return {
        kind: "type",
        name: selectedType.name,
        options: selectedType.options,
        extras: selectedType.extras,
      };
    }
    return null;
  }, [selectedCustomCard, selectedType]);

  const selectedOption = useMemo(
    () => selection?.options.find((o) => o.optionId === optionId),
    [selection, optionId]
  );

  const selectedExtras = useMemo(
    () => selection?.extras.filter((e) => extraIds?.includes(e.extraId)) ?? [],
    [selection, extraIds]
  );

  const [minPrice, maxPrice] = useMemo(() => {
    return calculatePriceRange(selectedOption, selectedExtras);
  }, [selectedOption, selectedExtras]);

  async function onSubmit(values: z.infer<typeof commissionOrderSchema>) {
    setIsSubmitting(true);

    try {
      const payload = {
        typeId: values.typeId || null,
        customCardId: values.customCardId || null,
        optionId: values.optionId || null,
        extraIds: values.extraIds ?? [],
        customerName: values.customerName,
        customerEmail: values.customerEmail,
        customerSocials: values.customerSocials ?? null,
        message: values.message,
      };

      await submitCommissionRequest({ payload, files });

      toast.success("Request submitted", {
        description: "Thanks! I’ll get back to you as soon as possible.",
      });

      form.reset({
        typeId: "",
        customCardId: "",
        optionId: "",
        extraIds: [],
        customerName: "",
        customerEmail: "",
        customerSocials: "",
        message: "",
      });

      setFiles([]);
      form.clearErrors();
    } catch (err) {
      const message =
        err instanceof Error ? err.message : "Submission failed. Please try again.";

      toast.error("Submission failed", { description: message });
    } finally {
      setIsSubmitting(false);
    }
  }

  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
        <FormField
          control={form.control}
          name="typeId"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Choose a commission type</FormLabel>
              <FormControl>
                <div className="flex flex-wrap gap-2">
                  {types.map((type) => (
                    <Button
                      key={type.id}
                      type="button"
                      variant={field.value === type.id ? "default" : "outline"}
                      onClick={() => {
                        field.onChange(type.id);
                        form.setValue("customCardId", "");
                        form.setValue("optionId", "");
                        form.setValue("extraIds", []);
                      }}
                      disabled={isSubmitting}
                    >
                      {type.name}
                    </Button>
                  ))}
                </div>
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />

        {customCards.length > 0 ? (
          <FormField
            control={form.control}
            name="customCardId"
            render={({ field }) => (
              <FormItem>
                <FormLabel>Custom requests / YCH</FormLabel>
                <FormControl>
                  <div className="flex flex-wrap gap-2">
                    {customCards.map((card) => (
                      <Button
                        key={card.id}
                        type="button"
                        variant={field.value === card.id ? "default" : "outline"}
                        onClick={() => {
                          field.onChange(card.id);
                          form.setValue("typeId", "");
                          form.setValue("optionId", "");
                          form.setValue("extraIds", []);
                        }}
                        disabled={isSubmitting}
                      >
                        {card.name}
                      </Button>
                    ))}
                  </div>
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />
        ) : null}

        {selection && (
          <>
            <FormField
              control={form.control}
              name="optionId"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Base Option</FormLabel>
                  <FormControl>
                    <div className="space-y-1">
                      {selection.options.map((opt) => (
                        <label key={opt.id} className="flex items-center gap-2">
                          <input
                            type="radio"
                            checked={field.value === opt.optionId}
                            value={opt.optionId}
                            onChange={() => field.onChange(opt.optionId)}
                            disabled={isSubmitting}
                          />
                          {opt.option.name}
                        </label>
                      ))}
                    </div>
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />

            <FormField
              control={form.control}
              name="extraIds"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Extras</FormLabel>
                  <FormControl>
                    <div className="space-y-1">
                      {selection.extras.map((ext) => (
                        <label key={ext.id} className="flex items-center gap-2">
                          <input
                            type="checkbox"
                            checked={field.value?.includes(ext.extraId) ?? false}
                            value={ext.extraId}
                            disabled={isSubmitting}
                            onChange={(e) => {
                              const checked = e.target.checked;
                              const newSet = new Set(field.value ?? []);
                              if (checked) newSet.add(ext.extraId);
                              else newSet.delete(ext.extraId);
                              field.onChange(Array.from(newSet));
                            }}
                          />
                          {ext.extra.name}
                        </label>
                      ))}
                    </div>
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />
          </>
        )}

        <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
          <FormField
            control={form.control}
            name="customerName"
            render={({ field }) => (
              <FormItem>
                <FormLabel>Your Name</FormLabel>
                <FormControl>
                  <Input placeholder="Nickname, real name, how you want to be called..." {...field} disabled={isSubmitting} />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />

          <FormField
            control={form.control}
            name="customerEmail"
            render={({ field }) => (
              <FormItem>
                <FormLabel>Email</FormLabel>
                <FormControl>
                  <Input
                    placeholder="E-Mail address for invoice and/or contact"
                    {...field}
                    disabled={isSubmitting}
                  />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />

          <FormField
            control={form.control}
            name="customerSocials"
            render={({ field }) => (
              <FormItem>
                <FormLabel>Socials</FormLabel>
                <FormControl>
                  <Input
                    placeholder="Alternative for contact (telegram, bsky, fediverse/mastodon)"
                    {...field}
                    disabled={isSubmitting}
                  />
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />
        </div>

        <FormField
          control={form.control}
          name="message"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Project Details</FormLabel>
              <FormControl>
                <Textarea
                  placeholder="Describe what you’d like drawn..."
                  rows={4}
                  {...field}
                  disabled={isSubmitting}
                />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />

        <FormItem>
          <FormLabel>Reference Images</FormLabel>
          <FormControl>
            <div className="space-y-2">
              <FileDropzone files={files} onFilesSelected={setFiles} />

              {files.length > 0 && (
                <div className="space-y-2">
                  <ul className="list-disc pl-4 text-sm text-muted-foreground">
                    {files.map((file, i) => (
                      <li key={`${file.name}-${file.size}-${file.lastModified}-${i}`}>
                        {file.name}
                      </li>
                    ))}
                  </ul>

                  <Button
                    type="button"
                    variant="outline"
                    className="h-9"
                    disabled={isSubmitting}
                    onClick={() => setFiles([])}
                  >
                    Clear files
                  </Button>
                </div>
              )}
            </div>
          </FormControl>
        </FormItem>

        <div className="text-lg font-semibold">
          Estimated Price:{" "}
          {minPrice === maxPrice
            ? `€${minPrice.toFixed(2)}`
            : `€${minPrice.toFixed(2)} – €${maxPrice.toFixed(2)}`}
        </div>

        <div className="text-muted-foreground">
          By submitting this form, you agree to our{" "}
          <Link href="/tos" className="underline">
            Terms of Service
          </Link>
          .
        </div>

        <Button type="submit" disabled={!form.formState.isValid || isSubmitting}>
          {isSubmitting ? "Submitting…" : "Submit Request"}
        </Button>
      </form>
    </Form>
  );
}
