import type { Route } from './+types/route'

import { zodResolver } from '@hookform/resolvers/zod'
import { useForm } from 'react-hook-form'
import { useFetcher, useOutletContext } from 'react-router'
import { z } from 'zod'

import { Button } from '@repo/ui/components/ui/button'
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle
} from '@repo/ui/components/ui/card'
import { Checkbox } from '@repo/ui/components/ui/checkbox'
import { FieldGroup, FieldLegend, FieldSet } from '@repo/ui/components/ui/field'
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage
} from '@repo/ui/components/ui/form'
import { Input } from '@repo/ui/components/ui/input'
import { Label } from '@repo/ui/components/ui/label'
import {
  NativeSelect,
  NativeSelectOption
} from '@repo/ui/components/ui/native-select'
import { RadioGroup, RadioGroupItem } from '@repo/ui/components/ui/radio-group'
import { Spinner } from '@repo/ui/components/ui/spinner'
import { HttpMethod, request as req } from '@repo/util/request'

import type { Org, Subscription } from '../_app.orgs.$id/data'

const formSchema = z.object({
  plan: z.enum(['NOTHING', 'FLEXIVEL']),
  billing_day: z
    .number({ error: 'Deve estar entre 1 e 31' })
    .min(1, { error: 'Deve ser igual 1 ou maior' })
    .max(31, { error: 'Deve ser menor ou igual a 31' }),
  payment_method: z.enum(['BANK_SLIP', 'MANUAL'], {
    error: 'Selecione uma opção'
  }),
  subscription_frozen: z.boolean().optional()
})

type Schema = Subscription & z.infer<typeof formSchema>

export async function action({ params, request, context }: Route.ActionArgs) {
  const method = request.method

  if (method === 'DELETE') {
    await req({
      url: `orgs/${params.id}/subscription`,
      method: HttpMethod.DELETE,
      request,
      context
    })

    return { ok: true }
  }

  await req({
    url: `orgs/${params.id}/subscription`,
    headers: new Headers({ 'Content-Type': 'application/json' }),
    method: method as HttpMethod,
    body: JSON.stringify(await request.json()),
    request,
    context
  })

  return { ok: true }
}

export default function Route({}: Route.ComponentProps) {
  const fetcher = useFetcher()
  const { org } = useOutletContext() as { org: Org }
  const subscribed = !!org?.subscription
  const form = useForm<Schema>({
    defaultValues: {
      plan: subscribed ? 'FLEXIVEL' : 'NOTHING',
      subscription_frozen: !!org?.subscription_frozen,
      ...org?.subscription
    },
    resolver: zodResolver(formSchema)
  })
  const { handleSubmit, formState, watch, reset } = form
  const plan = watch('plan')

  const onSubmit = async ({ plan, ...data }: Schema) => {
    if (plan === 'NOTHING') {
      fetcher.submit(null, {
        method: 'DELETE'
      })

      return reset({
        plan: 'NOTHING',
        billing_day: 1,
        payment_method: undefined,
        subscription_frozen: false
      })
    }

    fetcher.submit(JSON.stringify({ name: org.name, ...data }), {
      method: subscribed ? 'PUT' : 'POST',
      encType: 'application/json'
    })
  }

  return (
    <Form {...form}>
      <form onSubmit={handleSubmit(onSubmit)}>
        <Card>
          <CardHeader>
            <CardTitle className="font-semibold text-lg">
              Escolha um plano
            </CardTitle>
            <CardDescription>
              Escolha o plano que será utilizado para configurar o funcionamento
              e os recursos da empresa.
            </CardDescription>
          </CardHeader>

          <CardContent className="space-y-6">
            <FormField
              control={form.control}
              name="plan"
              render={({ field: { value, onChange } }) => (
                <FormItem>
                  <FormControl>
                    <RadioGroup
                      defaultValue={value}
                      onValueChange={onChange}
                      className="lg:grid-cols-2 grid gap-4
                                 *:border *:p-4 *:rounded-lg *:cursor-pointer
                                 *:has-[[aria-checked=true]]:bg-muted"
                    >
                      <Label className="flex items-center gap-3">
                        <RadioGroupItem value="NOTHING" />
                        <div className="font-medium">Sem plano</div>
                      </Label>

                      <Label className="flex items-center gap-3">
                        <RadioGroupItem value="FLEXIVEL" />
                        <div className="font-medium">Flexível</div>
                      </Label>
                    </RadioGroup>
                  </FormControl>

                  <FormMessage />
                </FormItem>
              )}
            />

            <FieldSet
              className="border rounded-lg p-6 bg-accent/10"
              disabled={plan === 'NOTHING'}
            >
              <FieldLegend className="mb-0">Configurações do plano</FieldLegend>

              <FieldGroup>
                <FormField
                  control={form.control}
                  name="billing_day"
                  defaultValue={1}
                  render={({ field: { onChange, ...field } }) => (
                    <FormItem>
                      <FormLabel>Dia para faturar</FormLabel>
                      <FormControl>
                        <Input
                          type="number"
                          min={1}
                          max={30}
                          onChange={(e) => onChange(Number(e.target.value))}
                          {...field}
                        />
                      </FormControl>
                      <FormMessage />
                    </FormItem>
                  )}
                />

                <FormField
                  control={form.control}
                  name="payment_method"
                  render={({ field }) => (
                    <FormItem className="*:w-full">
                      <FormLabel>Forma de pagamento</FormLabel>
                      <FormControl>
                        <NativeSelect {...field}>
                          <NativeSelectOption value="">
                            Selecione
                          </NativeSelectOption>
                          <NativeSelectOption value="BANK_SLIP">
                            Boleto bancário
                          </NativeSelectOption>
                          <NativeSelectOption value="MANUAL">
                            Depósito bancário
                          </NativeSelectOption>
                        </NativeSelect>
                      </FormControl>
                      <FormMessage />
                    </FormItem>
                  )}
                />

                <FormField
                  control={form.control}
                  name="subscription_frozen"
                  defaultValue={false}
                  render={({ field: { onChange, value, ...field } }) => (
                    <FormItem className="flex items-center gap-2">
                      <FormControl>
                        <Checkbox
                          checked={value}
                          onCheckedChange={onChange}
                          {...field}
                        />
                      </FormControl>
                      <FormLabel>
                        Suspender temporariamente o funcionamento do plano
                      </FormLabel>
                    </FormItem>
                  )}
                />
              </FieldGroup>
            </FieldSet>

            <Button
              type="submit"
              className="cursor-pointer"
              disabled={formState.isSubmitting}
            >
              {formState.isSubmitting ? <Spinner /> : null}
              Atualizar plano
            </Button>
          </CardContent>
        </Card>
      </form>
    </Form>
  )
}
