import { Fragment } from 'react'
import { Trash2Icon, PlusIcon, CircleQuestionMarkIcon } from 'lucide-react'
import { useForm, useFieldArray, Controller, useWatch } from 'react-hook-form'
import { useParams } from 'react-router'
import { ErrorMessage } from '@hookform/error-message'
import { zodResolver } from '@hookform/resolvers/zod'

import { Form } from '@repo/ui/components/ui/form'
import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput
} from '@repo/ui/components/ui/input-group'
import { Button } from '@repo/ui/components/ui/button'
import { Separator } from '@repo/ui/components/ui/separator'
import { Kbd } from '@repo/ui/components/ui/kbd'
import { Spinner } from '@repo/ui/components/ui/spinner'
import {
  HoverCard,
  HoverCardContent,
  HoverCardTrigger
} from '@repo/ui/components/ui/hover-card'

import {
  MAX_ITEMS,
  formSchema,
  type Course,
  type User
} from '../_.$orgid.enrollments.add/data'
import { ScheduledForInput } from '../_.$orgid.enrollments.add/scheduled-for'
import { Cell } from '../_.$orgid.enrollments.add/route'
import { CoursePicker } from '../_.$orgid.enrollments.add/course-picker'
import { UserPicker } from '../_.$orgid.enrollments.add/user-picker'

const emptyRow = {
  user: undefined,
  course: undefined,
  scheduled_for: undefined
}

type AssignedProps = {
  onSubmit: (value: any) => void | Promise<void>
  courses: Promise<{ hits: Course[] }>
}

export function Assigned({ courses, onSubmit }: AssignedProps) {
  const { orgid } = useParams()
  const form = useForm({
    resolver: zodResolver(formSchema),
    defaultValues: { enrollments: [emptyRow] }
  })
  const { formState, control, handleSubmit } = form
  const { fields, remove, append } = useFieldArray({
    control,
    name: 'enrollments'
  })
  const items = useWatch({
    control,
    name: 'enrollments'
  })
  const subtotal = items.reduce(
    (acc, { course }) => acc + (course?.unit_price || 0),
    0
  )

  const onSearch = async (search: string) => {
    const params = new URLSearchParams({ q: search })
    const r = await fetch(`/${orgid}/users.json?${params.toString()}`)
    const { hits } = (await r.json()) as { hits: User[] }
    return hits
  }

  const onSubmit_ = async (data: any) => {
    await onSubmit(data)
  }

  return (
    <Form {...form}>
      <form onSubmit={handleSubmit(onSubmit_)} className="space-y-4">
        <div className="grid w-full gap-1.5 lg:grid-cols-[3fr_3fr_2fr_2fr_auto]">
          {/* Header */}
          <>
            <Cell>Colaborador</Cell>
            <Cell>Curso</Cell>
            <Cell className="flex items-center gap-1.5">
              Matricular em
              <HoverCard openDelay={0}>
                <HoverCardTrigger asChild>
                  <button type="button">
                    <CircleQuestionMarkIcon className="size-4 text-muted-foreground" />
                  </button>
                </HoverCardTrigger>
                <HoverCardContent
                  align="end"
                  className="text-sm space-y-1.5 lg:w-76"
                >
                  <p>
                    Escolha a data em que o colaborador será matriculado no
                    curso.
                  </p>

                  <p>
                    Você poderá acompanhar as matrículas em{' '}
                    <Kbd>Agendamentos</Kbd>
                  </p>
                </HoverCardContent>
              </HoverCard>
            </Cell>
            <Cell>Valor unit.</Cell>
            <Cell>{/**/}</Cell>
          </>

          {/* Rows */}
          {fields.map((field, index) => {
            const { unit_price } = items?.[index]?.course || { unit_price: 0 }

            return (
              <Fragment key={field.id}>
                {/* Separator only for mobile */}
                {index >= 1 && <div className="h-2.5 lg:hidden"></div>}

                {/* User */}
                <Controller
                  control={control}
                  name={`enrollments.${index}.user`}
                  render={({
                    field: { name, value, onChange },
                    fieldState
                  }) => (
                    <div className="grid gap-1">
                      <UserPicker
                        value={value}
                        onChange={onChange}
                        onSearch={onSearch}
                        fieldState={fieldState}
                      />

                      <ErrorMessage
                        errors={formState.errors}
                        name={name}
                        render={({ message }) => (
                          <p className="text-destructive text-sm">{message}</p>
                        )}
                      />
                    </div>
                  )}
                />

                {/* Course */}
                <Controller
                  control={control}
                  name={`enrollments.${index}.course`}
                  render={({
                    field: { name, value, onChange },
                    fieldState
                  }) => (
                    <div className="grid gap-1">
                      <CoursePicker
                        value={value}
                        onChange={onChange}
                        options={courses}
                        error={fieldState.error}
                        readOnly
                      />

                      <ErrorMessage
                        errors={formState.errors}
                        name={name}
                        render={({ message }) => (
                          <p className="text-destructive text-sm">{message}</p>
                        )}
                      />
                    </div>
                  )}
                />

                {/* Scheduled for */}
                <Controller
                  control={control}
                  name={`enrollments.${index}.scheduled_for`}
                  render={({ field: { value, onChange } }) => (
                    <ScheduledForInput value={value} onChange={onChange} />
                  )}
                />

                {/* Unit price */}
                <InputGroup>
                  <InputGroupAddon className="border-r pr-2.5 w-1/3 lg:hidden justify-end">
                    Valor unit.
                  </InputGroupAddon>

                  <InputGroupInput
                    className="pointer-events-none"
                    tabIndex={-1}
                    readOnly
                    value={currency.format(unit_price)}
                  />
                </InputGroup>

                {/* Action */}
                <Button
                  tabIndex={-1}
                  variant="destructive"
                  className="cursor-pointer"
                  disabled={fields.length == 1}
                  onClick={() => remove(index)}
                >
                  <Trash2Icon />
                </Button>
              </Fragment>
            )
          })}

          {/* Add button */}
          <div className="max-lg:mb-2.5">
            <Button
              type="button"
              // @ts-ignore
              onClick={() => append(emptyRow)}
              className="cursor-pointer"
              disabled={fields.length == MAX_ITEMS}
              variant="outline"
              size="sm"
            >
              <PlusIcon /> Adicionar
            </Button>
          </div>

          {/* Subtotal */}
          <>
            <div className="col-start-3 flex items-center justify-end text-sm font-medium max-lg:hidden">
              Subtotal
            </div>

            <InputGroup>
              <InputGroupAddon className="border-r pr-2.5 w-1/3 lg:hidden justify-end">
                Subtotal
              </InputGroupAddon>
              <InputGroupInput
                name="subtotal"
                value={currency.format(subtotal)}
                className="pointer-events-none text-muted-foreground"
                readOnly
              />
            </InputGroup>
          </>

          {/* Discount */}
          <>
            <div className="col-start-3 flex items-center justify-end text-sm font-medium max-lg:hidden">
              Cupom
            </div>
            <InputGroup>
              <InputGroupAddon className="border-r pr-2.5 w-1/3 lg:hidden justify-end">
                Cupom
              </InputGroupAddon>
              <InputGroupInput
                name="discount"
                value={currency.format(0)}
                className="pointer-events-none text-muted-foreground"
                readOnly
              />
              <InputGroupAddon align="inline-end">
                <Button
                  variant="outline"
                  className="text-xs cursor-pointer h-6 px-2"
                  type="button"
                >
                  Adicionar
                </Button>
              </InputGroupAddon>
            </InputGroup>
          </>

          {/* Total */}
          <>
            <div className="col-start-3 flex items-center justify-end text-sm font-medium max-lg:hidden">
              Total
            </div>
            <InputGroup>
              <InputGroupAddon className="border-r pr-2.5 w-1/3 lg:hidden justify-end">
                Total
              </InputGroupAddon>
              <InputGroupInput
                name="total"
                value={currency.format(subtotal)}
                className="pointer-events-none text-muted-foreground"
                readOnly
              />
            </InputGroup>
          </>
        </div>

        <Separator />

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

const currency = new Intl.NumberFormat('pt-BR', {
  style: 'currency',
  currency: 'BRL'
})
