"use client"

import { zodResolver } from "@hookform/resolvers/zod"
import { FormProvider, useForm } from "react-hook-form"
import { useIntl } from "react-intl"
import { useMediaQuery } from "usehooks-ts"

import { trpc } from "@/lib/trpc/client"
import { useAddAncillaryStore } from "@/stores/my-stay/add-ancillary-flow"

import Image from "@/components/Image"
import Modal from "@/components/Modal"
import Button from "@/components/TempDesignSystem/Button"
import Divider from "@/components/TempDesignSystem/Divider"
import Body from "@/components/TempDesignSystem/Text/Body"
import { toast } from "@/components/TempDesignSystem/Toasts"
import useLang from "@/hooks/useLang"
import { formatPrice } from "@/utils/numberFormatting"

import { generateDeliveryOptions } from "../../utils"
import ConfirmationStep from "../ConfirmationStep"
import DeliveryMethodStep from "../DeliveryDetailsStep"
import { type AncillaryFormData, ancillaryFormSchema } from "../schema"
import SelectQuantityStep from "../SelectQuantityStep"

import styles from "./addAncillaryFlowModal.module.css"

import type { AddAncillaryFlowModalProps } from "@/types/components/myPages/myStay/ancillaries"

type FieldName = keyof AncillaryFormData
const STEP_FIELD_MAP: Record<number, FieldName[]> = {
  1: ["quantityWithPoints", "quantityWithCard"],
  2: ["deliveryTime"],
  3: ["termsAndConditions"],
}

export default function AddAncillaryFlowModal({
  isOpen,
  onClose,
  booking,
  user,
}: AddAncillaryFlowModalProps) {
  const {
    step,
    nextStep,
    prevStep,
    resetStore,
    selectedAncillary,
    confirmationNumber,
    openedFrom,
    setGridIsOpen,
  } = useAddAncillaryStore()

  const intl = useIntl()
  const lang = useLang()
  const isMobile = useMediaQuery("(max-width: 767px)")

  const deliveryTimeOptions = generateDeliveryOptions(booking.checkInDate)

  const defaultDeliveryTime = deliveryTimeOptions[0]?.value

  const formMethods = useForm<AncillaryFormData>({
    defaultValues: {
      quantityWithPoints: null,
      quantityWithCard: user ? null : 1,
      deliveryTime: defaultDeliveryTime,
      optionalText: "",
      termsAndConditions: false,
    },
    mode: "onSubmit",
    reValidateMode: "onChange",
    resolver: zodResolver(ancillaryFormSchema),
  })

  const { reset, trigger, handleSubmit, formState } = formMethods

  const addAncillary = trpc.booking.packages.useMutation({
    onSuccess: (data, variables) => {
      if (!data) {
        toast.error(
          intl.formatMessage(
            {
              id: "Something went wrong. {ancillary} could not be added to your booking!",
            },
            { ancillary: selectedAncillary?.title }
          )
        )
        return
      }
      const description = variables.ancillaryDeliveryTime
        ? intl.formatMessage(
            {
              id: "Delivery between {deliveryTime}. Payment will be made on check-in.",
            },
            { deliveryTime: variables.ancillaryDeliveryTime }
          )
        : undefined

      toast.success(
        intl.formatMessage(
          { id: "{ancillary} added to your booking!" },
          { ancillary: selectedAncillary?.title }
        ),
        { description }
      )
      handleClose()
    },
    onError: () => {
      toast.error(
        intl.formatMessage(
          {
            id: "Something went wrong. {ancillary} could not be added to your booking!",
          },
          { ancillary: selectedAncillary?.title }
        )
      )
    },
  })

  const onSubmit = (data: AncillaryFormData) => {
    const packages = []
    if (data.quantityWithCard) {
      packages.push({
        code: selectedAncillary!.id,
        quantity: data.quantityWithCard,
        comment: data.optionalText || undefined,
      })
    }

    if (selectedAncillary?.loyaltyCode && data.quantityWithPoints) {
      packages.push({
        code: selectedAncillary.loyaltyCode,
        quantity: data.quantityWithPoints,
        comment: data.optionalText || undefined,
      })
    }

    addAncillary.mutate({
      confirmationNumber,
      ancillaryComment: data.optionalText ?? "",
      ancillaryDeliveryTime: data.deliveryTime ?? undefined,
      packages,
      language: lang,
    })
  }

  const handleNextStep = async () => {
    let fieldsToValidate = []

    if (isMobile && step === 1) {
      fieldsToValidate = [...STEP_FIELD_MAP[1]]
      if (selectedAncillary?.requiresDeliveryTime) {
        fieldsToValidate = [...fieldsToValidate, ...STEP_FIELD_MAP[2]]
      }
    } else if (step === 2) {
      fieldsToValidate = selectedAncillary?.requiresDeliveryTime
        ? STEP_FIELD_MAP[2] || []
        : []
    } else {
      fieldsToValidate = STEP_FIELD_MAP[step] || []
    }

    if (await trigger(fieldsToValidate)) {
      nextStep()
    }
  }

  const handleBack = () => {
    if (step > 1) {
      prevStep()
    } else {
      handleClose()
      if (openedFrom === "grid") setGridIsOpen(true)
    }
  }

  const handleClose = () => {
    reset()
    resetStore()
    onClose()
  }

  if (!selectedAncillary) return null

  const confirmLabel = intl.formatMessage({ id: "Confirm" })
  const continueLabel = intl.formatMessage({ id: "Continue" })
  const confirmStep =
    isMobile || (!isMobile && !selectedAncillary.requiresDeliveryTime) ? 2 : 3

  return (
    <Modal
      isOpen={isOpen}
      onToggle={handleClose}
      title={selectedAncillary.title}
    >
      <div className={styles.modalWrapper}>
        <FormProvider {...formMethods}>
          <form onSubmit={handleSubmit(onSubmit)} className={styles.form}>
            <div className={styles.modalScrollable}>
              <div className={styles.imageContainer}>
                <Image
                  className={styles.image}
                  src={selectedAncillary.imageUrl}
                  alt={selectedAncillary.title}
                  fill
                />
              </div>
              <div className={styles.contentContainer}>
                <div className={styles.price}>
                  <Body textTransform="bold" color="uiTextHighContrast">
                    {formatPrice(
                      intl,
                      selectedAncillary.price.total,
                      selectedAncillary.price.currency
                    )}
                  </Body>
                  {selectedAncillary.points && (
                    <>
                      <Divider variant="vertical" color="subtle" />
                      <Body textTransform="bold" color="uiTextHighContrast">
                        {selectedAncillary.points}{" "}
                        {intl.formatMessage({ id: "points" })}
                      </Body>
                    </>
                  )}
                </div>
                {selectedAncillary.description && (
                  <Body asChild color="uiTextHighContrast">
                    <div
                      dangerouslySetInnerHTML={{
                        __html: selectedAncillary.description,
                      }}
                    />
                  </Body>
                )}
              </div>
              {isMobile ? (
                <>
                  {step === 1 && (
                    <>
                      <SelectQuantityStep user={user} />
                      {selectedAncillary.requiresDeliveryTime && (
                        <DeliveryMethodStep
                          deliveryTimeOptions={deliveryTimeOptions}
                        />
                      )}
                    </>
                  )}
                  {step === 2 && <ConfirmationStep />}
                </>
              ) : (
                <>
                  {step === 1 && <SelectQuantityStep user={user} />}
                  {step === 2 && selectedAncillary.requiresDeliveryTime && (
                    <DeliveryMethodStep
                      deliveryTimeOptions={deliveryTimeOptions}
                    />
                  )}
                  {(step === 3 ||
                    (step === 2 &&
                      !selectedAncillary.requiresDeliveryTime)) && (
                    <ConfirmationStep />
                  )}
                </>
              )}
            </div>
            <div className={styles.actionButtons}>
              <Button
                type="button"
                theme="base"
                intent="text"
                size="small"
                onClick={handleBack}
              >
                {intl.formatMessage({ id: "Back" })}
              </Button>
              <Button
                type="button"
                intent={step === confirmStep ? "primary" : "secondary"}
                size="small"
                disabled={formState.isSubmitting}
                onClick={
                  step === confirmStep
                    ? () => handleSubmit(onSubmit)()
                    : handleNextStep
                }
              >
                {step === confirmStep ? confirmLabel : continueLabel}
              </Button>
            </div>
          </form>
        </FormProvider>
      </div>
    </Modal>
  )
}
