import type { ButtonHTMLAttributes } from 'react'
import { useRequest, useToggle } from 'ahooks'
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'

import { Button } from '@repo/ui/components/ui/button'
import { Input } from '@repo/ui/components/ui/input'
import { Spinner } from '@repo/ui/components/ui/spinner'
import {
  Popover,
  PopoverContent,
  PopoverTrigger
} from '@repo/ui/components/ui/popover'
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage
} from '@repo/ui/components/ui/form'

const formSchema = z.object({
  coupon: z.string().min(3, { error: 'Digite um cupom válido' }).trim()
})

type Schema = z.infer<typeof formSchema>

export type Coupon = {
  code: string
  amount: number
  type: 'FIXED' | 'PERCENT'
}

interface DiscountProps extends Omit<
  ButtonHTMLAttributes<HTMLButtonElement>,
  'onChange'
> {
  onChange?: (value: Coupon) => void
  disabled?: boolean
}

export function Discount({ onChange, ...props }: DiscountProps) {
  const form = useForm({
    resolver: zodResolver(formSchema)
  })
  const [open, { toggle, set }] = useToggle()
  const { handleSubmit, control, formState, setError, reset } = form
  const { runAsync } = useRequest(
    async (coupon) => {
      return await fetch(`/~/api/coupons/${coupon}`, {
        method: 'GET'
      })
    },
    { manual: true }
  )

  const onSubmit = async (data: Schema) => {
    const r = await runAsync(data.coupon)

    if (!r.ok) {
      return setError('coupon', { message: 'Cupom inválido' })
    }

    const {
      sk: code,
      discount_amount: amount,
      discount_type: type
    } = (await r.json()) as {
      sk: string
      discount_amount: number
      discount_type: 'FIXED' | 'PERCENT'
    }

    onChange?.({ code, amount, type })

    reset()
    set(false)
  }

  return (
    <Popover open={open} onOpenChange={toggle} modal={true}>
      <PopoverTrigger asChild>
        <Button
          tabIndex={-1}
          variant="outline"
          className="text-xs cursor-pointer h-6 px-2"
          type="button"
          {...props}
        >
          Adicionar
        </Button>
      </PopoverTrigger>

      <PopoverContent align="end" className="w-82">
        <Form {...form}>
          <form
            onSubmit={async (e) => {
              e.stopPropagation()
              e.preventDefault()
              await handleSubmit(onSubmit)(e)
            }}
          >
            <div className="space-y-2.5">
              <h4 className="leading-none font-medium">Recebeu um cupom?</h4>
              <p className="text-muted-foreground text-sm">
                Aplique seu cupom e tenha acesso aos cursos com descontos
                exclusivos.
              </p>

              <FormField
                control={control}
                name="coupon"
                defaultValue=""
                render={({ field }) => (
                  <FormItem className="grid grid-cols-[20%_auto] gap-1">
                    <FormLabel>Cupom</FormLabel>
                    <FormControl>
                      <Input {...field} />
                    </FormControl>
                    <FormMessage className="col-start-2 " />
                  </FormItem>
                )}
              />

              <div className="flex justify-end gap-2.5">
                <Button
                  type="button"
                  variant="link"
                  tabIndex={-1}
                  className="cursor-pointer dark:text-white text-black"
                  onClick={() => set(false)}
                >
                  Cancelar
                </Button>

                <Button
                  type="submit"
                  className="cursor-pointer"
                  disabled={formState.isSubmitting}
                >
                  {formState.isSubmitting && <Spinner />}
                  Aplicar
                </Button>
              </div>
            </div>
          </form>
        </Form>
      </PopoverContent>
    </Popover>
  )
}

export function applyDiscount(
  subtotal: number,
  discountAmount: number,
  discountType: 'FIXED' | 'PERCENT'
) {
  if (subtotal <= 0) {
    return 0
  }

  const amount =
    discountType === 'PERCENT'
      ? (subtotal * discountAmount) / 100
      : discountAmount

  return Math.min(amount, subtotal)
}
