import { useState } from "react";
import type { z } from "zod";
import type { EventPlaceForm } from "../model/types";

import { zodResolver } from "@hookform/resolvers/zod";
import { type Control, useForm } from "react-hook-form";

import { Button } from "@/shared/ui/button";
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/shared/ui/form";
import { Input } from "@/shared/ui/input";

import { type EventPlace, placesQueries } from "@/entities/place";
import { handleNumericInput } from "@/shared/lib/handleNumericInput";
import { formatUsdt } from "@/shared/lib/money/usdt";
import { Switch } from "@/shared/ui/switch";
import { useCheckSubmit } from "../hooks/useCheckSubmit";
import { usePlacePersist } from "../hooks/usePlacePersist";
import { formSchema } from "../model/formSchema";

import type { LatLng } from "@/entities/geodata";
import { EbaliMap } from "@/features/map";
import { Circle } from "@/features/map";
import { useQuery } from "@tanstack/react-query";
import { AdvancedMarker, Pin } from "@vis.gl/react-google-maps";
import { twMerge } from "tailwind-merge";

type PlaceFormProps = {
  existingPlace?: EventPlace;
  onSubmit: (values: EventPlaceForm) => void;
  disableFields: boolean;
};

export const PlaceForm: React.FC<PlaceFormProps> = ({
  existingPlace,
  onSubmit: submitHandler,
  disableFields,
}) => {
  const { data: places } = useQuery(placesQueries.list());
  const { WithSubmitCheck, props } = useCheckSubmit();

  const hasActiveEvents = existingPlace?.isUsed ?? false;
  const isApproved = existingPlace?.status === "approved";
  // Deposit can only be edited if:
  // 1. Place is not yet approved (still submitted), AND
  // 2. There are no active events
  const canEditDeposit = !isApproved && !hasActiveEvents;

  const form = useForm<z.infer<typeof formSchema>>({
    resolver: zodResolver(formSchema),
    defaultValues: existingPlace
      ? {
          title: existingPlace.title,
          geometry: existingPlace.geometry.coordinates[0] as LatLng,
          maxTickets: existingPlace.maxTickets,
          minTickets: existingPlace.minTickets,
          minPrice: formatUsdt(BigInt(existingPlace.minPrice)),
          minDays: existingPlace.minDays,
          daysBeforeCancel: existingPlace.daysBeforeCancel,
          eventDepositSize: formatUsdt(BigInt(existingPlace.eventDepositSize)),
          available: existingPlace.available ?? true,
        }
      : {
          title: "",
          geometry: null,
          minTickets: 1,
          maxTickets: 100,
          daysBeforeCancel: 1,
          minDays: 1,
          minPrice: "1",
          eventDepositSize: "1",
          available: true,
        },
  });

  !existingPlace && usePlacePersist(form);

  function onSubmit(values: z.infer<typeof formSchema>) {
    submitHandler(values);
  }

  const [selectedLocation, setSelectedLocation] = useState<LatLng | null>(null);

  const formLocation = form.watch("geometry");
  const setFormLocation = (coords: LatLng | null) =>
    form.setValue("geometry", coords);

  return (
    <Form {...form}>
      <form
        onSubmit={form.handleSubmit(onSubmit)}
        className="flex flex-col gap-7"
      >
        <FormField
          control={form.control}
          disabled={disableFields}
          name="title"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Title</FormLabel>
              <FormControl>
                <Input placeholder="Place's name" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        <FormField
          control={form.control}
          name="geometry"
          render={() => {
            return (
              <FormItem>
                <FormLabel>Place location</FormLabel>
                <div className="relative">
                  <p
                    className={twMerge(
                      "absolute pointer-events-none top-0 left-1 z-1 transition-all duration-500",
                      (selectedLocation || formLocation) && "opacity-0",
                    )}
                  >
                    Long press to place marker
                  </p>
                  <EbaliMap
                    initialCenter={formLocation ?? undefined}
                    className={twMerge(
                      "h-[55dvh] transition-all duration-300",
                      selectedLocation && "h-[40dvh]",
                      formLocation && "h-[30dvh]",
                    )}
                    longPressHandler={
                      formLocation
                        ? () => {}
                        : (latLng) => {
                            form.clearErrors("geometry");
                            setSelectedLocation(latLng);
                          }
                    }
                  >
                    {places?.map((place) => {
                      const isExisting = place.id === existingPlace?.id;
                      return (
                        <Circle
                          key={place.id}
                          center={place.geometry.coordinates[0]}
                          radius={60}
                          strokeWeight={2}
                          strokeColor={isExisting ? "#3e8801" : "#02d6f2"}
                          fillColor={isExisting ? "#3e8801" : "#02d6f2"}
                        />
                      );
                    })}
                    {selectedLocation && (
                      <AdvancedMarker position={selectedLocation}>
                        <Pin
                          background={"#ffc107"}
                          borderColor={"#ff9800"}
                          glyphColor={"#ffe082"}
                        />
                      </AdvancedMarker>
                    )}
                    {formLocation && (
                      <AdvancedMarker position={formLocation}>
                        <Pin
                          background={"#76ff05"}
                          borderColor={"#006400"}
                          glyphColor={"#b2ff59"}
                        />
                      </AdvancedMarker>
                    )}
                  </EbaliMap>
                  <FormMessage />
                  {selectedLocation && (
                    <div className="py-1">
                      <p className="text-lg py-2">Place set correctly?</p>
                      <div className="flex flex-row justify-between items-center">
                        <Button
                          variant="secondary"
                          className="w-1/4"
                          onClick={() => {
                            setFormLocation(selectedLocation);
                            form.clearErrors("geometry");
                            setSelectedLocation(null);
                          }}
                        >
                          Yes
                        </Button>
                        <Button
                          variant="destructive"
                          className="w-1/4"
                          onClick={() => setSelectedLocation(null)}
                        >
                          No
                        </Button>
                      </div>
                    </div>
                  )}
                  {formLocation && (
                    <Button
                      className="w-full mt-4"
                      onClick={() => {
                        setSelectedLocation(formLocation);
                        setFormLocation(null);
                      }}
                    >
                      Change
                    </Button>
                  )}
                </div>
              </FormItem>
            );
          }}
        />
        <CustomFormComponent
          control={form.control}
          fieldDisabled={disableFields}
          fieldName="minTickets"
          title="Minimum tickets amount"
        />
        <CustomFormComponent
          control={form.control}
          fieldDisabled={disableFields}
          fieldName="maxTickets"
          title="Maximum tickets amount"
        />
        <CustomFormComponent
          control={form.control}
          fieldDisabled={disableFields}
          fieldName="minDays"
          title="Minimum days"
        />
        <CustomFormComponent
          control={form.control}
          fieldDisabled={disableFields}
          fieldName="minPrice"
          title="Minimum price"
        />
        <CustomFormComponent
          control={form.control}
          fieldDisabled={disableFields}
          fieldName="daysBeforeCancel"
          title="Days before cancel"
        />

        <FormField
          control={form.control}
          name="eventDepositSize"
          disabled={disableFields || !canEditDeposit}
          render={({ field }) => (
            <FormItem>
              <FormLabel>Event deposit (USDT)</FormLabel>
              <FormControl>
                <Input
                  placeholder="Deposit required for events"
                  inputMode="decimal"
                  {...field}
                  value={field.value || ""}
                  onChange={(e) => field.onChange(e.target.value)}
                  disabled={disableFields || !canEditDeposit}
                />
              </FormControl>
              <FormMessage />
              {!canEditDeposit && existingPlace && (
                <p className="text-xs text-muted-foreground">
                  {isApproved
                    ? "Deposit is set during approval and cannot be changed after."
                    : "Deposit cannot be changed while there are active events at this place."}
                </p>
              )}
            </FormItem>
          )}
        />

        <FormField
          control={form.control}
          name={"available"}
          disabled={disableFields}
          render={({ field }) => (
            <FormItem className="flex justify-between items-center">
              <FormLabel>Available</FormLabel>
              <FormControl>
                <Switch
                  className="h-12"
                  checked={field.value}
                  onCheckedChange={field.onChange}
                />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />

        <div className="sticky bottom-5 w-full mt-5">
          <WithSubmitCheck {...props}>
            <Button className="block mx-auto" type="submit" variant="default">
              Submit
            </Button>
          </WithSubmitCheck>
        </div>
      </form>
    </Form>
  );
};

type CustomFormComponentProps = {
  control: Control<EventPlaceForm, unknown, EventPlaceForm>;
  fieldName:
    | "maxTickets"
    | "minTickets"
    | "minPrice"
    | "minDays"
    | "daysBeforeCancel";
  title: string;
  fieldDisabled: boolean;
};

const CustomFormComponent = ({
  control,
  fieldName,
  title,
  fieldDisabled,
}: CustomFormComponentProps) => {
  const isMoney = fieldName === "minPrice";
  return (
    <FormField
      control={control}
      name={fieldName}
      disabled={fieldDisabled}
      render={({ field }) => (
        <FormItem>
          <FormLabel>{title}</FormLabel>
          <FormControl>
            <Input
              placeholder=""
              inputMode={isMoney ? "decimal" : "numeric"}
              {...field}
              value={
                isMoney
                  ? ((field.value as string | undefined) ?? "")
                  : field.value
              }
              onChange={(e) =>
                field.onChange(
                  isMoney ? e.target.value : handleNumericInput(e.target.value),
                )
              }
            />
          </FormControl>
          <FormMessage />
        </FormItem>
      )}
    />
  );
};

Graph