// @ts-nocheck
import { zodResolver } from '@hookform/resolvers/zod'
import { useParams } from 'common'
import { SubmitHandler, useForm } from 'react-hook-form'
import { toast } from 'sonner'
import {
  Button,
  cn,
  DialogFooter,
  DialogSection,
  Form,
  FormControl,
  FormField,
  Input,
  SheetFooter,
  SheetSection,
} from 'ui'
import { Admonition } from 'ui-patterns'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
import z from 'zod'

import { useIcebergWrapperExtension } from './AnalyticsBucketDetails/useIcebergWrapper'
import {
  reservedPrefixes,
  reservedSuffixes,
  validBucketNameRegex,
} from './CreateAnalyticsBucketForm.utils'
import { InlineLink } from '@/components/ui/InlineLink'
import { useDatabaseExtensionEnableMutation } from '@/data/database-extensions/database-extension-enable-mutation'
import { useAnalyticsBucketCreateMutation } from '@/data/storage/analytics-bucket-create-mutation'
import { useAnalyticsBucketsQuery } from '@/data/storage/analytics-buckets-query'
import { useIcebergWrapperCreateMutation } from '@/data/storage/iceberg-wrapper-create-mutation'
import { useSendEventMutation } from '@/data/telemetry/send-event-mutation'
import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { DOCS_URL } from '@/lib/constants'

const FormSchema = z
  .object({
    name: z
      .string()
      .trim()
      .min(3, 'Bucket name should be at least 3 characters')
      .max(63, 'Bucket name should be up to 63 characters')
      .refine(
        (value) => !value.endsWith(' '),
        'The name of the bucket cannot end with a whitespace'
      )
      .refine(
        (value) => value !== 'public',
        '"public" is a reserved name. Please choose another name'
      ),
  })
  .superRefine((data, ctx) => {
    if (reservedPrefixes.test(data.name)) {
      const [match] = data.name.match(reservedPrefixes) ?? []
      return ctx.addIssue({
        path: ['name'],
        code: z.ZodIssueCode.custom,
        message: `Bucket name cannot start with "${match}"`,
      })
    }

    if (reservedSuffixes.test(data.name)) {
      const [match] = data.name.match(reservedSuffixes) ?? []
      return ctx.addIssue({
        path: ['name'],
        code: z.ZodIssueCode.custom,
        message: `Bucket name cannot end with "${match}"`,
      })
    }

    if (/[A-Z]/.test(data.name)) {
      return ctx.addIssue({
        path: ['name'],
        code: z.ZodIssueCode.custom,
        message: 'Bucket name can only be lowercase characters',
      })
    }

    if (!validBucketNameRegex.test(data.name)) {
      if (!/^[a-z0-9]/.test(data.name)) {
        return ctx.addIssue({
          path: ['name'],
          code: z.ZodIssueCode.custom,
          message: 'Bucket name must start with a lowercase letter or number.',
        })
      }

      if (!/[a-z0-9]$/.test(data.name)) {
        return ctx.addIssue({
          path: ['name'],
          code: z.ZodIssueCode.custom,
          message: 'Bucket name must end with a lowercase letter or number.',
        })
      }

      const [match] = data.name.match(/[^a-z0-9-]/) ?? []
      return ctx.addIssue({
        path: ['name'],
        code: z.ZodIssueCode.custom,
        message: !!match
          ? `Bucket name cannot contain the "${match}" character`
          : 'Bucket name contains an invalid special character',
      })
    }
  })

const formId = 'create-analytics-storage-bucket-form'

export type CreateAnalyticsBucketForm = z.infer<typeof FormSchema>

interface CreateAnalyticsBucketFormProps {
  type?: 'dialog' | 'sheet'
  onOpenChange: (value: boolean) => void
}

export const CreateAnalyticsBucketForm = ({
  type = 'dialog',
  onOpenChange,
}: CreateAnalyticsBucketFormProps) => {
  const { ref } = useParams()
  const { data: org } = useSelectedOrganizationQuery()
  const { data: project } = useSelectedProjectQuery()
  const { extension: wrappersExtension, state: wrappersExtensionState } =
    useIcebergWrapperExtension()

  const { data: buckets = [] } = useAnalyticsBucketsQuery({ projectRef: ref })
  const wrappersExtensionNeedsUpgrading = wrappersExtensionState === 'needs-upgrade'

  const { mutate: sendEvent } = useSendEventMutation()

  const { mutateAsync: createAnalyticsBucket, isPending: isCreatingAnalyticsBucket } =
    useAnalyticsBucketCreateMutation({
      // [Joshen] Silencing the error here as it's being handled in onSubmit
      onError: () => {},
    })

  const { mutateAsync: createIcebergWrapper, isPending: isCreatingIcebergWrapper } =
    useIcebergWrapperCreateMutation()

  const { mutateAsync: enableExtension, isPending: isEnablingExtension } =
    useDatabaseExtensionEnableMutation()

  const isCreating = isEnablingExtension || isCreatingIcebergWrapper || isCreatingAnalyticsBucket

  const form = useForm<CreateAnalyticsBucketForm>({
    resolver: zodResolver(FormSchema as any),
    defaultValues: { name: '' },
  })

  const onSubmit: SubmitHandler<CreateAnalyticsBucketForm> = async (values) => {
    if (!ref) return console.error('Project ref is required')
    if (!project) return console.error('Project details is required')
    if (!wrappersExtension) return console.error('Unable to find wrappers extension')

    const hasExistingBucket = buckets.some((x) => x.name === values.name)
    if (hasExistingBucket) return toast.error('Bucket name already exists')

    try {
      await createAnalyticsBucket({
        projectRef: ref,
        bucketName: values.name,
      })

      if (wrappersExtensionState === 'not-installed') {
        await enableExtension({
          projectRef: project?.ref,
          connectionString: project?.connectionString,
          name: wrappersExtension.name,
          schema: wrappersExtension.schema ?? 'extensions',
          version: wrappersExtension.default_version,
        })
      }

      await createIcebergWrapper({ bucketName: values.name })

      sendEvent({
        action: 'storage_bucket_created',
        properties: { bucketType: 'analytics' },
        groups: { project: ref ?? 'Unknown', organization: org?.slug ?? 'Unknown' },
      })

      form.reset()
      toast.success(`Created bucket “${values.name}”`)
      onOpenChange(false)
    } catch (error: any) {
      toast.error(`Failed to create bucket: ${error.message}`)
    }
  }

  const Section = type === 'dialog' ? DialogSection : SheetSection
  const Footer = type === 'dialog' ? DialogFooter : SheetFooter

  return (
    <>
      <Section className="flex flex-col p-0! grow">
        <Form {...form}>
          <form id={formId} onSubmit={form.handleSubmit(onSubmit)}>
            <FormField
              key="name"
              name="name"
              control={form.control}
              render={({ field }) => (
                <FormItemLayout
                  name="name"
                  className="p-5"
                  label="Bucket name"
                  labelOptional="Cannot be changed after creation"
                  description="Must be between 3 – 63 characters. Only lowercase letters, numbers, and hyphens are allowed."
                >
                  <FormControl>
                    <Input
                      id="name"
                      data-1p-ignore
                      data-lpignore="true"
                      data-form-type="other"
                      data-bwignore
                      {...field}
                      placeholder="Enter bucket name"
                    />
                  </FormControl>
                </FormItemLayout>
              )}
            />

            {wrappersExtensionNeedsUpgrading ? (
              <Admonition
                type="warning"
                className={cn('border-x-0 rounded-none', type === 'dialog' && 'border-b-0')}
                title="Wrappers extension must be updated for Iceberg Wrapper support"
              >
                <p className="prose max-w-full text-sm leading-normal!">
                  Update the <code className="text-code-inline">wrappers</code> extension by
                  upgrading your project from your{' '}
                  <InlineLink href={`/project/${ref}/settings/infrastructure`}>
                    project settings
                  </InlineLink>{' '}
                  before creating an Analytics bucket.{' '}
                  <InlineLink href={`${DOCS_URL}/guides/database/extensions/wrappers/iceberg`}>
                    Learn more
                  </InlineLink>
                  .
                </p>
              </Admonition>
            ) : (
              <Admonition
                type="default"
                className={cn('border-x-0 rounded-none', type === 'dialog' && 'border-b-0')}
              >
                <p className="leading-normal!">
                  Briven will install the{' '}
                  {wrappersExtensionState !== 'installed' ? 'Wrappers extension and ' : ''}
                  Iceberg Wrapper integration on your behalf.{' '}
                  <InlineLink href={`${DOCS_URL}/guides/database/extensions/wrappers/iceberg`}>
                    Learn more
                  </InlineLink>
                  .
                </p>
              </Admonition>
            )}
          </form>
        </Form>
      </Section>

      <Footer>
        <Button type="default" disabled={isCreating} onClick={() => onOpenChange(false)}>
          Cancel
        </Button>
        <Button
          form={formId}
          htmlType="submit"
          loading={isCreating}
          disabled={wrappersExtensionNeedsUpgrading || isCreating}
        >
          Create bucket
        </Button>
      </Footer>
    </>
  )
}
