'use client'

import { useEffect, useState } from 'react'
import { useForm, useWatch } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { toast } from 'sonner'
import { cn } from '@/lib/utils'
import {
  Dialog,
  DialogContent,
  DialogTitle,
} from '@/components/ui/dialog'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Textarea } from '@/components/ui/textarea'
import { DemoTooltip } from '@/components/shared/demo-tooltip'
import {
  useDirtyCloseGuard,
  DirtyCloseGuardDialog,
} from '@/components/shared/use-dirty-close-guard'
import { useDialogSubmitShortcut } from '@/components/shared/use-dialog-submit-shortcut'
import {
  entityDialogBodyClasses,
  entityDialogContentClasses,
  entityDialogFooterClasses,
  entityDialogHeaderClasses,
} from '@/components/shared/entity-dialog-layout'
import { productSchema, type ProductInput } from '@/lib/schemas/product'
import { createProductAction, updateProductAction } from '@/actions/products'
import { useProductsStore } from '@/stores/products-store'

export interface ProductDialogProduct {
  id: string
  name: string
  code?: string | null
  description?: string | null
  repo_url?: string | null
  definition_of_done?: string | null
  auto_pr?: boolean
}

type Props =
  | { mode: 'create'; open: boolean; onOpenChange: (v: boolean) => void; onSaved?: (id: string) => void; isDemo?: boolean }
  | { mode: 'edit'; open: boolean; onOpenChange: (v: boolean) => void; product: ProductDialogProduct; onSaved?: (id: string) => void; isDemo?: boolean }

export function ProductDialog(props: Props) {
  const { mode, open, onOpenChange, isDemo = false } = props
  const product = mode === 'edit' ? props.product : null
  const addProduct = useProductsStore((s) => s.addProduct)
  const updateProduct = useProductsStore((s) => s.updateProduct)

  const [isPending, setIsPending] = useState(false)

  const form = useForm<ProductInput>({
    resolver: zodResolver(productSchema),
    mode: 'onTouched',
    defaultValues: {
      name: product?.name ?? '',
      code: product?.code ?? '',
      description: product?.description ?? '',
      repo_url: product?.repo_url ?? '',
      definition_of_done: product?.definition_of_done ?? '',
      auto_pr: product?.auto_pr ?? false,
    },
  })

  // Reset when opening or switching product
  useEffect(() => {
    if (open) {
      form.reset({
        name: product?.name ?? '',
        code: product?.code ?? '',
        description: product?.description ?? '',
        repo_url: product?.repo_url ?? '',
        definition_of_done: product?.definition_of_done ?? '',
        auto_pr: product?.auto_pr ?? false,
      })
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [open, product?.id])

  const closeGuard = useDirtyCloseGuard(form.formState.isDirty, () => onOpenChange(false))
  const handleKeyDown = useDialogSubmitShortcut(() => form.handleSubmit(onSubmit)())

  async function onSubmit(values: ProductInput) {
    setIsPending(true)
    try {
      const payload: ProductInput = {
        name: values.name,
        code: values.code || undefined,
        description: values.description || undefined,
        repo_url: values.repo_url || null,
        definition_of_done: values.definition_of_done || undefined,
        auto_pr: values.auto_pr,
      }

      function applyError(result: { error: string; code?: number; fieldErrors?: Partial<Record<keyof ProductInput, string[]>> }) {
        if (result.code === 422 && result.fieldErrors) {
          for (const [field, errors] of Object.entries(result.fieldErrors)) {
            if (errors && errors.length > 0) {
              form.setError(field as keyof ProductInput, { message: errors[0] })
            }
          }
          const firstError = Object.keys(result.fieldErrors)[0] as keyof ProductInput | undefined
          if (firstError) form.setFocus(firstError)
          return
        }
        toast.error(result.error)
      }

      if (mode === 'create') {
        const result = await createProductAction(payload)
        if ('error' in result) {
          applyError(result)
          return
        }
        const productId = result.productId
        addProduct({
          id: productId,
          name: values.name,
          code: values.code ?? null,
          description: values.description ?? null,
          repo_url: values.repo_url ?? null,
          definition_of_done: values.definition_of_done ?? '',
          auto_pr: values.auto_pr,
        })
        toast.success('Product aangemaakt')
        onOpenChange(false)
        props.onSaved?.(productId)
      } else {
        const result = await updateProductAction(product!.id, payload)
        if ('error' in result) {
          applyError(result)
          return
        }
        updateProduct(product!.id, {
          name: values.name,
          code: values.code ?? null,
          description: values.description ?? null,
          repo_url: values.repo_url ?? null,
          definition_of_done: values.definition_of_done ?? '',
          auto_pr: values.auto_pr,
        })
        toast.success('Product opgeslagen')
        onOpenChange(false)
        props.onSaved?.(product!.id)
      }
    } finally {
      setIsPending(false)
    }
  }

  const autoPr = useWatch({ control: form.control, name: 'auto_pr' })

  return (
    <>
      <Dialog open={open} onOpenChange={(v) => { if (!v) closeGuard.attemptClose(); else onOpenChange(v) }}>
        <DialogContent
          showCloseButton={false}
          onKeyDown={handleKeyDown}
          className={entityDialogContentClasses}
        >
          <div className={entityDialogHeaderClasses}>
            <DialogTitle className="text-xl font-semibold">
              {mode === 'edit' ? 'Product bewerken' : 'Nieuw product'}
            </DialogTitle>
          </div>

          <form
            id="product-form"
            onSubmit={form.handleSubmit(onSubmit)}
            className={entityDialogBodyClasses}
          >
            <div className="grid gap-1.5">
              <label htmlFor="product-name" className="text-sm font-medium">
                Naam <span className="text-error">*</span>
              </label>
              <Input
                id="product-name"
                autoFocus={mode === 'create'}
                disabled={isDemo}
                maxLength={200}
                aria-invalid={!!form.formState.errors.name}
                {...form.register('name')}
                className={form.formState.errors.name ? 'border-error' : ''}
              />
              {form.formState.errors.name && (
                <p className="text-xs text-error">{form.formState.errors.name.message}</p>
              )}
            </div>

            <div className="grid gap-1.5">
              <label htmlFor="product-code" className="text-sm font-medium">
                Code <span className="text-muted-foreground font-normal">(optioneel)</span>
              </label>
              <Input
                id="product-code"
                disabled={isDemo}
                maxLength={20}
                placeholder="korte slug, bv. SCRUM4ME"
                aria-invalid={!!form.formState.errors.code}
                className={cn('font-mono text-sm', form.formState.errors.code && 'border-error')}
                {...form.register('code')}
              />
              {form.formState.errors.code && (
                <p className="text-xs text-error">{form.formState.errors.code.message}</p>
              )}
            </div>

            <div className="grid gap-1.5">
              <label htmlFor="product-description" className="text-sm font-medium">
                Beschrijving <span className="text-muted-foreground font-normal">(optioneel)</span>
              </label>
              <Textarea
                id="product-description"
                disabled={isDemo}
                rows={3}
                maxLength={4000}
                className="resize-none"
                {...form.register('description')}
              />
            </div>

            <div className="grid gap-1.5">
              <label htmlFor="product-repo-url" className="text-sm font-medium">
                Repository URL <span className="text-muted-foreground font-normal">(optioneel)</span>
              </label>
              <Input
                id="product-repo-url"
                disabled={isDemo}
                placeholder="https://github.com/owner/repo"
                aria-invalid={!!form.formState.errors.repo_url}
                {...form.register('repo_url')}
                className={form.formState.errors.repo_url ? 'border-error' : ''}
              />
              {form.formState.errors.repo_url && (
                <p className="text-xs text-error">{form.formState.errors.repo_url.message}</p>
              )}
            </div>

            <div className="grid gap-1.5">
              <label htmlFor="product-dod" className="text-sm font-medium">
                Definition of Done <span className="text-muted-foreground font-normal">(optioneel)</span>
              </label>
              <Textarea
                id="product-dod"
                disabled={isDemo}
                rows={4}
                maxLength={4000}
                className="resize-none"
                {...form.register('definition_of_done')}
              />
            </div>

            <div className="flex items-start gap-3">
              <button
                type="button"
                role="switch"
                aria-checked={autoPr}
                disabled={isDemo}
                onClick={() => form.setValue('auto_pr', !autoPr, { shouldDirty: true })}
                className={cn(
                  'relative mt-0.5 inline-flex h-5 w-9 shrink-0 cursor-pointer rounded-full border-2 border-transparent',
                  'transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
                  'disabled:cursor-not-allowed disabled:opacity-50',
                  autoPr ? 'bg-primary' : 'bg-input',
                )}
              >
                <span
                  className={cn(
                    'pointer-events-none inline-block h-4 w-4 rounded-full bg-background shadow-sm',
                    'transition-transform duration-200',
                    autoPr ? 'translate-x-4' : 'translate-x-0',
                  )}
                />
              </button>
              <div className="grid gap-0.5">
                <span className="text-sm font-medium">Automatisch PR aanmaken na voltooide story</span>
                <span className="text-xs text-muted-foreground">
                  Bij elke voltooide story automatisch een PR aanmaken in <code>repo_url</code>
                </span>
              </div>
            </div>
          </form>

          <div className={entityDialogFooterClasses}>
            <div className="flex items-center justify-end gap-2">
              <Button
                type="button"
                variant="ghost"
                onClick={closeGuard.attemptClose}
                disabled={isPending}
              >
                Annuleren
              </Button>
              <DemoTooltip show={isDemo}>
                <Button type="submit" form="product-form" disabled={isPending || isDemo}>
                  {isPending ? '…' : mode === 'edit' ? 'Opslaan' : 'Aanmaken'}
                </Button>
              </DemoTooltip>
            </div>
          </div>
        </DialogContent>
      </Dialog>
      <DirtyCloseGuardDialog guard={closeGuard} />
    </>
  )
}
