'use client'

import { useCallback, useEffect, useRef, useState } from 'react'
import { createLogger } from '@sim/logger'
import { Check, Eye, EyeOff } from 'lucide-react'
import {
  ButtonGroup,
  ButtonGroupItem,
  Input,
  Label,
  Loader,
  Skeleton,
  TagInput,
  type TagItem,
  Textarea,
  Tooltip,
} from '@/components/emcn'
import { isDev } from '@/lib/core/config/feature-flags'
import { cn } from '@/lib/core/utils/cn'
import { getBaseUrl, getEmailDomain } from '@/lib/core/utils/urls'
import { isInputDefinitionTrigger } from '@/lib/workflows/triggers/input-definition-triggers'
import {
  type FieldConfig,
  useCreateForm,
  useDeleteForm,
  useFormByWorkflow,
  useUpdateForm,
} from '@/hooks/queries/forms'
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
import { useWorkflowStore } from '@/stores/workflows/workflow/store'
import { EmbedCodeGenerator } from './components/embed-code-generator'
import { FormBuilder } from './components/form-builder'
import { useIdentifierValidation } from './hooks/use-identifier-validation'

const logger = createLogger('FormDeploy')

interface FormErrors {
  identifier?: string
  title?: string
  password?: string
  emails?: string
  general?: string
}

interface FormDeployProps {
  workflowId: string
  onDeploymentComplete?: () => void
  onValidationChange?: (isValid: boolean) => void
  onSubmittingChange?: (isSubmitting: boolean) => void
  formSubmitting?: boolean
  setFormSubmitting?: (submitting: boolean) => void
  onDeployed?: () => Promise<void>
}

const getDomainPrefix = (() => {
  const prefix = `${getEmailDomain()}/form/`
  return () => prefix
})()

export function FormDeploy({
  workflowId,
  onDeploymentComplete,
  onValidationChange,
  onSubmittingChange,
  formSubmitting,
  setFormSubmitting,
  onDeployed,
}: FormDeployProps) {
  const [identifier, setIdentifier] = useState('')
  const [title, setTitle] = useState('')
  const [description, setDescription] = useState('')
  const [thankYouMessage, setThankYouMessage] = useState(
    'Your response has been submitted successfully.'
  )
  const [authType, setAuthType] = useState<'public' | 'password' | 'email'>('public')
  const [password, setPassword] = useState('')
  const [emailItems, setEmailItems] = useState<TagItem[]>([])
  const [formUrl, setFormUrl] = useState('')
  const [inputFields, setInputFields] = useState<{ name: string; type: string }[]>([])
  const [showPasswordField, setShowPasswordField] = useState(false)
  const [fieldConfigs, setFieldConfigs] = useState<FieldConfig[]>([])
  const fieldConfigsInitializedRef = useRef(false)
  const [errors, setErrors] = useState<FormErrors>({})

  const { data: existingForm, isLoading } = useFormByWorkflow(workflowId)
  const createFormMutation = useCreateForm()
  const updateFormMutation = useUpdateForm()
  const deleteFormMutation = useDeleteForm()

  const isSubmitting = createFormMutation.isPending || updateFormMutation.isPending

  const {
    isChecking: isCheckingIdentifier,
    error: identifierError,
    isValid: isIdentifierValid,
  } = useIdentifierValidation(identifier, existingForm?.identifier, !!existingForm)

  const setError = (field: keyof FormErrors, message: string) => {
    setErrors((prev) => ({ ...prev, [field]: message }))
  }

  const clearError = (field: keyof FormErrors) => {
    setErrors((prev) => ({ ...prev, [field]: undefined }))
  }

  // Populate form fields when existing form data is loaded
  useEffect(() => {
    if (existingForm) {
      setIdentifier(existingForm.identifier)
      setTitle(existingForm.title)
      setDescription(existingForm.description || '')
      setThankYouMessage(
        existingForm.customizations?.thankYouMessage ||
          'Your response has been submitted successfully.'
      )
      setAuthType(existingForm.authType)
      setEmailItems(
        (existingForm.allowedEmails || []).map((email) => ({ value: email, isValid: true }))
      )
      if (existingForm.customizations?.fieldConfigs) {
        setFieldConfigs(existingForm.customizations.fieldConfigs)
      }

      const baseUrl = getBaseUrl()
      try {
        const url = new URL(baseUrl)
        let host = url.host
        if (host.startsWith('www.')) host = host.substring(4)
        setFormUrl(`${url.protocol}//${host}/form/${existingForm.identifier}`)
      } catch {
        setFormUrl(
          isDev
            ? `http://localhost:3000/form/${existingForm.identifier}`
            : `https://sim.ai/form/${existingForm.identifier}`
        )
      }
    } else if (!isLoading) {
      const workflowName =
        useWorkflowStore.getState().blocks[Object.keys(useWorkflowStore.getState().blocks)[0]]
          ?.name || 'Form'
      setTitle(`${workflowName} Form`)
    }
  }, [existingForm, isLoading])

  useEffect(() => {
    fieldConfigsInitializedRef.current = false
  }, [workflowId])

  useEffect(() => {
    const blocks = Object.values(useWorkflowStore.getState().blocks)
    const startBlock = blocks.find((b) => isInputDefinitionTrigger(b.type))

    if (startBlock) {
      const inputFormat = useSubBlockStore.getState().getValue(startBlock.id, 'inputFormat')
      if (inputFormat && Array.isArray(inputFormat)) {
        setInputFields(inputFormat)

        if (!fieldConfigsInitializedRef.current) {
          fieldConfigsInitializedRef.current = true
          setFieldConfigs(
            inputFormat.map((f: { name: string; type?: string }) => ({
              name: f.name,
              type: f.type || 'string',
              label: f.name
                .replace(/([A-Z])/g, ' $1')
                .replace(/_/g, ' ')
                .replace(/^./, (s) => s.toUpperCase())
                .trim(),
            }))
          )
        }
      }
    }
  }, [workflowId])

  const allowedEmails = emailItems.filter((item) => item.isValid).map((item) => item.value)

  useEffect(() => {
    const isValid =
      inputFields.length > 0 &&
      isIdentifierValid &&
      title.trim().length > 0 &&
      (authType !== 'password' || password.length > 0 || !!existingForm?.hasPassword) &&
      (authType !== 'email' || allowedEmails.length > 0)

    onValidationChange?.(isValid)
  }, [
    isIdentifierValid,
    title,
    authType,
    password,
    allowedEmails.length,
    existingForm?.hasPassword,
    onValidationChange,
    inputFields.length,
  ])

  useEffect(() => {
    onSubmittingChange?.(isSubmitting)
    setFormSubmitting?.(isSubmitting)
  }, [isSubmitting, onSubmittingChange, setFormSubmitting])

  const handleSubmit = useCallback(
    async (e: React.FormEvent) => {
      e.preventDefault()
      setErrors({})

      if (!isIdentifierValid && identifier !== existingForm?.identifier) {
        setError('identifier', 'Please wait for identifier validation to complete')
        return
      }

      if (!title.trim()) {
        setError('title', 'Title is required')
        return
      }

      if (authType === 'password' && !existingForm?.hasPassword && !password.trim()) {
        setError('password', 'Password is required')
        return
      }

      if (authType === 'email' && allowedEmails.length === 0) {
        setError('emails', 'At least one email or domain is required')
        return
      }

      const customizations = {
        thankYouMessage,
        fieldConfigs,
      }

      try {
        if (existingForm) {
          await updateFormMutation.mutateAsync({
            formId: existingForm.id,
            workflowId,
            data: {
              identifier,
              title,
              description,
              customizations,
              authType,
              password: password || undefined,
              allowedEmails,
            },
          })
        } else {
          const result = await createFormMutation.mutateAsync({
            workflowId,
            identifier,
            title,
            description,
            customizations,
            authType,
            password,
            allowedEmails,
          })

          if (result?.formUrl) {
            setFormUrl(result.formUrl)
            window.open(result.formUrl, '_blank', 'noopener,noreferrer')
          }
        }

        await onDeployed?.()

        if (!existingForm) {
          onDeploymentComplete?.()
        }
      } catch (err: unknown) {
        const message = err instanceof Error ? err.message : 'An error occurred'
        logger.error('Error deploying form:', err)

        if (message.toLowerCase().includes('identifier')) {
          setError('identifier', message)
        } else if (message.toLowerCase().includes('password')) {
          setError('password', message)
        } else if (message.toLowerCase().includes('email')) {
          setError('emails', message)
        } else {
          setError('general', message)
        }
      }
    },
    [
      existingForm,
      workflowId,
      identifier,
      title,
      description,
      thankYouMessage,
      fieldConfigs,
      authType,
      password,
      allowedEmails,
      isIdentifierValid,
      createFormMutation,
      updateFormMutation,
      onDeployed,
      onDeploymentComplete,
    ]
  )

  const handleDelete = useCallback(async () => {
    if (!existingForm) return

    try {
      await deleteFormMutation.mutateAsync({
        formId: existingForm.id,
        workflowId,
      })
      setIdentifier('')
      setTitle('')
      setDescription('')
      setFormUrl('')
    } catch (err) {
      logger.error('Error deleting form:', err)
    }
  }, [existingForm, deleteFormMutation, workflowId])

  if (isLoading) {
    return (
      <div className='-mx-1 space-y-4 px-1'>
        <div className='space-y-3'>
          <div>
            <Skeleton className='mb-[6.5px] h-[16px] w-[26px]' />
            <Skeleton className='h-[34px] w-full rounded-sm' />
            <Skeleton className='mt-[6.5px] h-[14px] w-[320px]' />
          </div>
          <div>
            <Skeleton className='mb-[6.5px] h-[16px] w-[30px]' />
            <Skeleton className='h-[34px] w-full rounded-sm' />
          </div>
        </div>
      </div>
    )
  }

  if (inputFields.length === 0) {
    return (
      <div className='flex h-full items-center justify-center text-[var(--text-secondary)] text-small'>
        Add input fields to the Start block to create a form.
      </div>
    )
  }

  const fullUrl = `${getBaseUrl()}/form/${identifier}`
  const displayUrl = fullUrl.replace(/^https?:\/\//, '')

  return (
    <form id='form-deploy-form' onSubmit={handleSubmit} className='-mx-1 space-y-4 px-1'>
      <div className='space-y-3'>
        {/* URL Input - matching chat style */}
        <div>
          <Label className='mb-[6.5px] block pl-0.5 font-medium text-[var(--text-primary)] text-small'>
            URL
          </Label>
          <div
            className={cn(
              'relative flex items-stretch overflow-hidden rounded-sm border border-[var(--border-1)]',
              (identifierError || errors.identifier) && 'border-[var(--text-error)]'
            )}
          >
            <div className='flex items-center whitespace-nowrap bg-[var(--surface-5)] pr-1.5 pl-2 font-medium text-[var(--text-secondary)] text-sm'>
              {getDomainPrefix()}
            </div>
            <div className='relative flex-1'>
              <Input
                value={identifier}
                onChange={(e) => {
                  setIdentifier(e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, ''))
                  clearError('identifier')
                }}
                placeholder='my-form'
                className={cn(
                  'rounded-none border-0 pl-0 shadow-none',
                  (isCheckingIdentifier || (isIdentifierValid && identifier)) && 'pr-8'
                )}
              />
              {isCheckingIdentifier ? (
                <div className='-translate-y-1/2 absolute top-1/2 right-2'>
                  <Loader className='size-4 text-[var(--text-tertiary)]' animate />
                </div>
              ) : (
                isIdentifierValid &&
                identifier && (
                  <Tooltip.Root>
                    <Tooltip.Trigger asChild>
                      <div className='-translate-y-1/2 absolute top-1/2 right-2'>
                        <Check className='size-4 text-[var(--brand-accent)]' />
                      </div>
                    </Tooltip.Trigger>
                    <Tooltip.Content>
                      <span>Name is available</span>
                    </Tooltip.Content>
                  </Tooltip.Root>
                )
              )}
            </div>
          </div>
          {(identifierError || errors.identifier) && (
            <p className='mt-[6.5px] text-[var(--text-error)] text-caption'>
              {identifierError || errors.identifier}
            </p>
          )}
          <p className='mt-[6.5px] truncate text-[var(--text-secondary)] text-xs'>
            {existingForm && identifier ? (
              <>
                Live at:{' '}
                <a
                  href={fullUrl}
                  target='_blank'
                  rel='noopener noreferrer'
                  className='text-[var(--text-primary)] hover-hover:underline'
                >
                  {displayUrl}
                </a>
              </>
            ) : (
              'The unique URL path where your form will be accessible'
            )}
          </p>
        </div>

        {/* Form Builder Preview */}
        <div>
          <Label className='mb-[6.5px] block pl-0.5 font-medium text-[var(--text-primary)] text-small'>
            Form builder
          </Label>
          <FormBuilder
            title={title}
            onTitleChange={(value: string) => {
              setTitle(value)
              clearError('title')
            }}
            description={description}
            onDescriptionChange={setDescription}
            fieldConfigs={fieldConfigs}
            onFieldConfigsChange={setFieldConfigs}
            titleError={errors.title}
          />
        </div>

        {/* Access Control */}
        <div>
          <Label className='mb-[6.5px] block pl-0.5 font-medium text-[var(--text-primary)] text-small'>
            Access control
          </Label>
          <ButtonGroup
            value={authType}
            onValueChange={(val) => setAuthType(val as 'public' | 'password' | 'email')}
          >
            <ButtonGroupItem value='public'>Public</ButtonGroupItem>
            <ButtonGroupItem value='password'>Password</ButtonGroupItem>
            <ButtonGroupItem value='email'>Email</ButtonGroupItem>
          </ButtonGroup>
        </div>

        {authType === 'password' && (
          <div>
            <Label className='mb-[6.5px] block pl-0.5 font-medium text-[var(--text-primary)] text-small'>
              Password
            </Label>
            <div className='relative'>
              <Input
                type={showPasswordField ? 'text' : 'password'}
                value={password}
                onChange={(e) => {
                  setPassword(e.target.value)
                  clearError('password')
                }}
                placeholder={
                  existingForm?.hasPassword ? 'Enter new password to change' : 'Enter password'
                }
                className='pr-8'
              />
              <button
                type='button'
                onClick={() => setShowPasswordField(!showPasswordField)}
                className='-translate-y-1/2 absolute top-1/2 right-[8px] text-[var(--text-secondary)]'
              >
                {showPasswordField ? <EyeOff className='size-4' /> : <Eye className='size-4' />}
              </button>
            </div>
            {errors.password && (
              <p className='mt-[6.5px] text-[var(--text-error)] text-caption'>{errors.password}</p>
            )}
            <p className='mt-[6.5px] text-[var(--text-secondary)] text-xs'>
              {existingForm?.hasPassword
                ? 'Leave empty to keep the current password'
                : 'This password will be required to access your form'}
            </p>
          </div>
        )}

        {authType === 'email' && (
          <div>
            <Label className='mb-[6.5px] block pl-0.5 font-medium text-[var(--text-primary)] text-small'>
              Allowed emails
            </Label>
            <TagInput
              items={emailItems}
              onAdd={(value) => {
                const trimmed = value.trim().toLowerCase()
                if (!trimmed || emailItems.some((item) => item.value === trimmed)) {
                  return false
                }
                const isDomainPattern = trimmed.startsWith('@')
                const isValid = isDomainPattern || trimmed.includes('@')
                setEmailItems((prev) => [...prev, { value: trimmed, isValid }])
                if (isValid) {
                  clearError('emails')
                }
                return isValid
              }}
              onRemove={(_value, index) => {
                setEmailItems((prev) => prev.filter((_, i) => i !== index))
              }}
              placeholder='Enter emails or @domain.com'
              placeholderWithTags='Add another'
            />
            {errors.emails && (
              <p className='mt-[6.5px] text-[var(--text-error)] text-caption'>{errors.emails}</p>
            )}
            <p className='mt-[6.5px] text-[var(--text-secondary)] text-xs'>
              Add specific emails or entire domains (@example.com)
            </p>
          </div>
        )}

        {/* Thank You Message */}
        <div>
          <Label className='mb-[6.5px] block pl-0.5 font-medium text-[var(--text-primary)] text-small'>
            Thank you message
          </Label>
          <Textarea
            value={thankYouMessage}
            onChange={(e) => setThankYouMessage(e.target.value)}
            placeholder='Your response has been submitted successfully.'
            rows={2}
            className='min-h-[60px] resize-none'
          />
          <p className='mt-[6.5px] text-[var(--text-secondary)] text-xs'>
            This message will be displayed after form submission
          </p>
        </div>

        {/* Embed Code - only when deployed */}
        {existingForm && formUrl && (
          <EmbedCodeGenerator formUrl={formUrl} identifier={identifier} />
        )}

        {errors.general && (
          <p className='mt-[6.5px] text-[var(--text-error)] text-caption'>{errors.general}</p>
        )}

        <button type='button' data-delete-trigger onClick={handleDelete} className='hidden' />
      </div>
    </form>
  )
}
