import { useEffect, useMemo, useState } from 'react'
import {
  Checkbox,
  HelperText,
  Label,
  Select,
  Textarea,
  TextInput,
} from 'flowbite-react'
import { Controller, useFormContext, useWatch } from 'react-hook-form'

import formTheme from '@/lib/themes/form'
import { getMarketingChannels } from '@/lib/services/marketing-channels'
import PhoneNumberInput from '@/lib/components/forms/PhoneNumberInput'
import DatePicker, { FormattedDate } from '@/lib/components/DatePicker'
import CountrySelector from '@/lib/components/forms/CountrySelector'
import LanguageSelector from '@/lib/components/forms/LanguageSelector'
import AffiliateCategorySelector from '@/lib/components/forms/AffiliateCategorySelector'
import AffiliateLevelSelector from '@/lib/components/forms/AffiliateLevelSelector'
import { AffiliateExperience, PayoutMethod } from '@/lib/types/enums/partner'
import {
  AffiliatePartnerFormValues,
  MarketingChannel,
} from '@/lib/types/partner'
import { AffiliateLevel } from '@/app/(dashboard)/affiliate-levels/types'
import { capitalizeWords } from '@/lib/utils/string'
import { ReferralLink } from '@/app/(dashboard)/referral-links/types'
import BankSelect from './BankSelect'
import ReferralLinksSection from './ReferralLinksSection'

interface FormProps {
  initialReferralLinks?: ReferralLink[]
  hideAffiliateLevelSelector?: boolean
}

function generateRandomReferral(length: number = 4) {
  const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'

  return Array.from({ length }, () => {
    const randomIndex = Math.floor(Math.random() * characters.length)
    return characters[randomIndex]
  }).join('')
}

export default function Form({
  initialReferralLinks = [],
  hideAffiliateLevelSelector = false,
}: FormProps) {
  const {
    control,
    formState: { errors },
    register,
    setValue,
  } = useFormContext<AffiliatePartnerFormValues>()

  const [marketingChannels, setMarketingChannels] = useState<
    MarketingChannel[]
  >([])
  const [selectedReferralLinks, setSelectedReferralLinks] =
    useState<ReferralLink[]>(initialReferralLinks)

  const payoutMethod = useWatch({
    control,
    name: 'payout_method',
  })
  const referralPrefix = useWatch({
    control,
    name: 'referral_prefix',
  })
  const referralSuffix = useWatch({
    control,
    name: 'referral_suffix',
  })
  const formReferralCode = useWatch({
    control,
    name: 'referral_code',
  })
  const marketingChannelIds = useWatch({
    control,
    name: 'marketing_channels',
  }) as number[]
  const affiliateCountryId = useWatch({
    control,
    name: 'affiliate.country_id',
  })
  const affiliateLangCode = useWatch({
    control,
    name: 'affiliate.lang_code',
  })
  const affiliateLevelId = useWatch({
    control,
    name: 'affiliate.affiliate_level_id',
  })
  const affiliateCategoryId = useWatch({
    control,
    name: 'affiliate.affiliate_category_id',
  })

  useEffect(() => {
    getMarketingChannels()
      .then(setMarketingChannels)
      .catch(() => {
        setMarketingChannels([])
      })
  }, [])

  useEffect(() => {
    if (referralPrefix || referralSuffix) {
      setValue(
        'referral_code',
        `${referralPrefix || ''}${referralSuffix || ''}`,
      )
    }
  }, [referralPrefix, referralSuffix, setValue])

  const referralCodePreview = useMemo(() => {
    if (referralPrefix || referralSuffix) {
      return `${referralPrefix || ''}${referralSuffix || ''}`
    }

    return formReferralCode || 'Preview will appear here'
  }, [referralPrefix, referralSuffix, formReferralCode])

  function handleToggleMarketingChannel(channelId: number) {
    const currentChannels = marketingChannelIds || []
    const updatedChannels = currentChannels.includes(channelId)
      ? currentChannels.filter((id) => id !== channelId)
      : [...currentChannels, channelId]

    setValue('marketing_channels', updatedChannels, {
      shouldValidate: true,
    })
  }

  function handleReferralLinksChange(referralLinks: ReferralLink[]) {
    setSelectedReferralLinks(referralLinks)
    setValue(
      'referral_links',
      referralLinks.map((link) => link.id),
      {
        shouldValidate: true,
      },
    )
  }

  function handleReferralValueChange(
    fieldName: 'referral_prefix' | 'referral_suffix',
    value: string,
  ) {
    setValue(fieldName, value.toUpperCase(), {
      shouldValidate: true,
    })
  }

  function handleAffiliateLevelChange(affiliateLevel: AffiliateLevel | null) {
    setValue('affiliate.affiliate_level_id', affiliateLevel?.id ?? null, {
      shouldValidate: true,
    })
  }

  return (
    <div className="space-y-12">
      <input type="hidden" {...register('referral_code')} />
      <input type="hidden" {...register('mode')} />

      {/* Account Details */}
      <div className="space-y-4">
        <h3 className="text-xl font-semibold text-gray-900">Account Details</h3>

        <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
          <div>
            <div className="mb-2 block">
              <Label theme={formTheme.label} htmlFor="email">
                Email <span className="text-red-500">*</span>
              </Label>
            </div>
            <TextInput
              id="email"
              theme={formTheme.textInput}
              type="email"
              placeholder="Enter email"
              {...register('email')}
            />
            <HelperText color="failure">{errors.email?.message}</HelperText>
          </div>

          <div>
            <div className="mb-2 block">
              <Label theme={formTheme.label} htmlFor="password">
                Password
              </Label>
            </div>
            <TextInput
              id="password"
              theme={formTheme.textInput}
              type="password"
              placeholder="Enter password"
              {...register('password')}
            />
            <HelperText color="failure">{errors.password?.message}</HelperText>
          </div>
        </div>

        <div>
          <div className="mb-2 block">
            <Label theme={formTheme.label} htmlFor="guest_market">
              Guest Market <span className="text-red-500">*</span>
            </Label>
          </div>
          <TextInput
            id="guest_market"
            theme={formTheme.textInput}
            type="text"
            placeholder="Enter guest market (e.g. Australian, European, Asian)"
            {...register('guest_market')}
          />
          <HelperText color="failure">
            {errors.guest_market?.message}
          </HelperText>
        </div>

        <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
          <div>
            <div className="mb-2 flex items-center justify-between">
              <Label theme={formTheme.label} htmlFor="referral_prefix">
                Referral Prefix
              </Label>
              <button
                type="button"
                onClick={() => {
                  const randomPrefix = generateRandomReferral()
                  handleReferralValueChange('referral_prefix', randomPrefix)
                }}
                className="rounded-full border border-blue-200 bg-blue-50 px-2.5 py-1 text-sm font-medium text-blue-700 transition-colors hover:border-blue-300 hover:bg-blue-100"
              >
                Generate
              </button>
            </div>
            <TextInput
              id="referral_prefix"
              theme={formTheme.textInput}
              type="text"
              placeholder="Enter referral prefix"
              {...register('referral_prefix')}
              onChange={(event) => {
                handleReferralValueChange('referral_prefix', event.target.value)
              }}
            />
            <HelperText color="failure">
              {errors.referral_prefix?.message}
            </HelperText>
          </div>

          <div>
            <div className="mb-2 flex items-center justify-between">
              <Label theme={formTheme.label} htmlFor="referral_suffix">
                Referral Suffix
              </Label>
              <button
                type="button"
                onClick={() => {
                  const randomSuffix = generateRandomReferral()
                  handleReferralValueChange('referral_suffix', randomSuffix)
                }}
                className="rounded-full border border-blue-200 bg-blue-50 px-2.5 py-1 text-sm font-medium text-blue-700 transition-colors hover:border-blue-300 hover:bg-blue-100"
              >
                Generate
              </button>
            </div>
            <TextInput
              id="referral_suffix"
              theme={formTheme.textInput}
              type="text"
              placeholder="Enter referral suffix"
              {...register('referral_suffix')}
              onChange={(event) => {
                handleReferralValueChange('referral_suffix', event.target.value)
              }}
            />
            <HelperText color="failure">
              {errors.referral_suffix?.message}
            </HelperText>
          </div>
        </div>

        <div>
          <div className="mb-2 block">
            <Label theme={formTheme.label} htmlFor="referral_code_preview">
              Referral Code Preview
            </Label>
          </div>
          <div
            id="referral_code_preview"
            className={`rounded-lg border px-4 py-3 text-sm transition-colors ${
              errors.referral_code
                ? 'border-red-300 bg-red-50 text-red-700'
                : 'border-blue-200 bg-blue-50 text-slate-700'
            }`}
          >
            <div className="flex items-center justify-between gap-3">
              <span className="font-bold">{referralCodePreview}</span>
              {!errors.referral_code && (
                <span className="rounded-full bg-white px-2.5 py-1 text-xs font-semibold uppercase tracking-wide text-blue-600">
                  Preview
                </span>
              )}
            </div>
          </div>
          {errors.referral_code?.message ? (
            <HelperText color="failure" className="mt-1">
              {errors.referral_code.message}
            </HelperText>
          ) : null}
        </div>
      </div>

      {/* Affiliate Details */}
      <div className="space-y-4">
        <h3 className="text-xl font-semibold text-gray-900">
          Affiliate Details
        </h3>

        <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
          <div>
            <div className="mb-2 block">
              <Label theme={formTheme.label} htmlFor="affiliate.name">
                Name <span className="text-red-500">*</span>
              </Label>
            </div>
            <TextInput
              id="affiliate.name"
              theme={formTheme.textInput}
              type="text"
              placeholder="Enter affiliate name"
              {...register('affiliate.name')}
            />
            <HelperText color="failure">
              {errors.affiliate?.name?.message}
            </HelperText>
          </div>

          <div>
            <div className="mb-2 block">
              <Label theme={formTheme.label} htmlFor="affiliate.email">
                Email <span className="text-red-500">*</span>
              </Label>
            </div>
            <TextInput
              id="affiliate.email"
              theme={formTheme.textInput}
              type="email"
              placeholder="Enter affiliate email"
              {...register('affiliate.email')}
            />
            <HelperText color="failure">
              {errors.affiliate?.email?.message}
            </HelperText>
          </div>
        </div>

        <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
          <div>
            <div className="mb-2 block">
              <Label theme={formTheme.label} htmlFor="affiliate.phone_number">
                Phone Number <span className="text-red-500">*</span>
              </Label>
            </div>
            <PhoneNumberInput
              controller={control}
              field_name="affiliate.phone_number"
              required
            />
            <HelperText color="failure">
              {errors.affiliate?.phone_number?.message}
            </HelperText>
          </div>

          <CountrySelector
            id="affiliate.country_id"
            label="Country"
            required
            value={affiliateCountryId ?? undefined}
            onChange={(country) => {
              setValue('affiliate.country_id', country?.id as number, {
                shouldValidate: true,
              })
            }}
            errorMessage={errors.affiliate?.country_id?.message}
          />
        </div>

        <div>
          <Controller
            name="affiliate.date_of_birth"
            control={control}
            render={({ field }) => (
              <div>
                <div className="mb-2 block">
                  <Label
                    theme={formTheme.label}
                    htmlFor="affiliate.date_of_birth"
                  >
                    Date of Birth <span className="text-red-500">*</span>
                  </Label>
                </div>
                <DatePicker
                  inputId="affiliate.date_of_birth"
                  maxDate={new Date()}
                  asSingle
                  useRange={false}
                  value={{
                    startDate: field.value ? new Date(field.value) : null,
                    endDate: field.value ? new Date(field.value) : null,
                  }}
                  onDateChange={(formattedDate: FormattedDate) => {
                    field.onChange(formattedDate?.startDate)
                  }}
                />
                <HelperText color="failure">
                  {errors.affiliate?.date_of_birth?.message}
                </HelperText>
              </div>
            )}
          />
        </div>

        <div>
          <div className="mb-2 block">
            <Label theme={formTheme.label} htmlFor="affiliate.address">
              Address <span className="text-red-500">*</span>
            </Label>
          </div>
          <Textarea
            id="affiliate.address"
            theme={formTheme.textarea}
            placeholder="Enter full address"
            rows={3}
            className="resize-none"
            {...register('affiliate.address')}
          />
          <HelperText color="failure">
            {errors.affiliate?.address?.message}
          </HelperText>
        </div>

        <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
          <LanguageSelector
            id="affiliate.lang_code"
            label="Language"
            required
            value={affiliateLangCode}
            onChange={(language) => {
              setValue('affiliate.lang_code', language?.code || '', {
                shouldValidate: true,
              })
            }}
            errorMessage={errors.affiliate?.lang_code?.message}
          />

          <AffiliateCategorySelector
            id="affiliate.affiliate_category_id"
            label="Affiliate Category"
            required
            placeholder="-- Select Affiliate Category --"
            value={affiliateCategoryId ?? undefined}
            onChange={(affiliateCategory) => {
              setValue(
                'affiliate.affiliate_category_id',
                affiliateCategory?.id as number,
                { shouldValidate: true },
              )
            }}
            errorMessage={errors.affiliate?.affiliate_category_id?.message}
          />
        </div>

        <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
          <div>
            <div className="mb-2 block">
              <Label theme={formTheme.label} htmlFor="affiliate.niche">
                Niche <span className="text-red-500">*</span>
              </Label>
            </div>
            <TextInput
              id="affiliate.niche"
              theme={formTheme.textInput}
              type="text"
              placeholder="Enter affiliate niche"
              {...register('affiliate.niche')}
            />
            <HelperText color="failure">
              {errors.affiliate?.niche?.message}
            </HelperText>
          </div>

          <div>
            <div className="mb-2 block">
              <Label
                theme={formTheme.label}
                htmlFor="affiliate.affiliate_experience"
              >
                Affiliate Experience <span className="text-red-500">*</span>
              </Label>
            </div>
            <Controller
              name="affiliate.affiliate_experience"
              control={control}
              render={({ field }) => (
                <Select
                  {...field}
                  theme={formTheme.select}
                  id="affiliate.affiliate_experience"
                >
                  <option value="">-- Select Experience --</option>
                  <option value={AffiliateExperience.NoExperience}>
                    {capitalizeWords(AffiliateExperience.NoExperience)}
                  </option>
                  <option value={AffiliateExperience.LessThanOneYear}>
                    {capitalizeWords(AffiliateExperience.LessThanOneYear)}
                  </option>
                  <option value={AffiliateExperience.OneToThreeYears}>
                    {capitalizeWords(AffiliateExperience.OneToThreeYears)}
                  </option>
                  <option value={AffiliateExperience.MoreThanThreeYears}>
                    {capitalizeWords(AffiliateExperience.MoreThanThreeYears)}
                  </option>
                </Select>
              )}
            />
            <HelperText color="failure">
              {errors.affiliate?.affiliate_experience?.message}
            </HelperText>
          </div>
        </div>

        {!hideAffiliateLevelSelector && (
          <AffiliateLevelSelector
            id="affiliate.affiliate_level_id"
            label="Affiliate Level"
            value={affiliateLevelId ?? undefined}
            onChange={handleAffiliateLevelChange}
            errorMessage={errors.affiliate?.affiliate_level_id?.message}
          />
        )}
      </div>

      {/* Payout Details */}
      <div className="space-y-4">
        <h3 className="text-xl font-semibold text-gray-900">Payout Details</h3>

        <div>
          <div className="mb-2 block">
            <Label theme={formTheme.label} htmlFor="payout_method">
              Payout Method <span className="text-red-500">*</span>
            </Label>
          </div>
          <Select
            id="payout_method"
            theme={formTheme.select}
            {...register('payout_method')}
          >
            <option value="">-- Select Payout Method --</option>
            <option value={PayoutMethod.BankTransfer}>Bank Transfer</option>
            <option value={PayoutMethod.Wise}>Wise</option>
            <option value={PayoutMethod.Paypal}>Paypal</option>
          </Select>
          <HelperText color="failure">
            {errors.payout_method?.message}
          </HelperText>
        </div>

        {payoutMethod === PayoutMethod.BankTransfer && (
          <div className="space-y-4">
            <BankSelect />
            <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
              <div>
                <div className="mb-2 block">
                  <Label
                    theme={formTheme.label}
                    htmlFor="bank_account.account_name"
                  >
                    Account Name <span className="text-red-500">*</span>
                  </Label>
                </div>
                <TextInput
                  id="bank_account.account_name"
                  theme={formTheme.textInput}
                  type="text"
                  placeholder="Enter account name"
                  {...register('bank_account.account_name')}
                />
                <HelperText color="failure">
                  {errors.bank_account?.account_name?.message}
                </HelperText>
              </div>

              <div>
                <div className="mb-2 block">
                  <Label
                    theme={formTheme.label}
                    htmlFor="bank_account.account_number"
                  >
                    Account Number <span className="text-red-500">*</span>
                  </Label>
                </div>
                <TextInput
                  id="bank_account.account_number"
                  theme={formTheme.textInput}
                  type="text"
                  placeholder="Enter account number"
                  {...register('bank_account.account_number')}
                />
                <HelperText color="failure">
                  {errors.bank_account?.account_number?.message}
                </HelperText>
              </div>
            </div>
          </div>
        )}

        {payoutMethod === PayoutMethod.Wise && (
          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
            <div>
              <div className="mb-2 block">
                <Label
                  theme={formTheme.label}
                  htmlFor="wise_account.account_name"
                >
                  Account Name <span className="text-red-500">*</span>
                </Label>
              </div>
              <TextInput
                id="wise_account.account_name"
                theme={formTheme.textInput}
                type="text"
                placeholder="Enter account name"
                {...register('wise_account.account_name')}
              />
              <HelperText color="failure">
                {errors.wise_account?.account_name?.message}
              </HelperText>
            </div>
            <div>
              <div className="mb-2 block">
                <Label theme={formTheme.label} htmlFor="wise_account.email">
                  Email <span className="text-red-500">*</span>
                </Label>
              </div>
              <TextInput
                id="wise_account.email"
                theme={formTheme.textInput}
                type="email"
                placeholder="Enter account email"
                {...register('wise_account.email')}
              />
              <HelperText color="failure">
                {errors.wise_account?.email?.message}
              </HelperText>
            </div>
          </div>
        )}

        {payoutMethod === PayoutMethod.Paypal && (
          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
            <div>
              <div className="mb-2 block">
                <Label
                  theme={formTheme.label}
                  htmlFor="paypal_account.account_name"
                >
                  Account Name <span className="text-red-500">*</span>
                </Label>
              </div>
              <TextInput
                id="paypal_account.account_name"
                theme={formTheme.textInput}
                type="text"
                placeholder="Enter account name"
                {...register('paypal_account.account_name')}
              />
              <HelperText color="failure">
                {errors.paypal_account?.account_name?.message}
              </HelperText>
            </div>
            <div>
              <div className="mb-2 block">
                <Label theme={formTheme.label} htmlFor="paypal_account.email">
                  Email <span className="text-red-500">*</span>
                </Label>
              </div>
              <TextInput
                id="paypal_account.email"
                theme={formTheme.textInput}
                type="email"
                placeholder="Enter account email"
                {...register('paypal_account.email')}
              />
              <HelperText color="failure">
                {errors.paypal_account?.email?.message}
              </HelperText>
            </div>
          </div>
        )}
      </div>

      {/* Social Media */}
      <div className="space-y-4">
        <h3 className="text-xl font-semibold text-gray-900">Social Media</h3>

        <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
          <div>
            <div className="mb-2 block">
              <Label theme={formTheme.label} htmlFor="instagram_url">
                Instagram URL
              </Label>
            </div>
            <TextInput
              id="instagram_url"
              theme={formTheme.textInput}
              type="url"
              placeholder="https://instagram.com/username"
              {...register('instagram_url')}
            />
            <HelperText color="failure">
              {errors.instagram_url?.message}
            </HelperText>
          </div>

          <div>
            <div className="mb-2 block">
              <Label theme={formTheme.label} htmlFor="facebook_url">
                Facebook URL
              </Label>
            </div>
            <TextInput
              id="facebook_url"
              theme={formTheme.textInput}
              type="url"
              placeholder="https://facebook.com/username"
              {...register('facebook_url')}
            />
            <HelperText color="failure">
              {errors.facebook_url?.message}
            </HelperText>
          </div>

          <div>
            <div className="mb-2 block">
              <Label theme={formTheme.label} htmlFor="website_url">
                Website URL
              </Label>
            </div>
            <TextInput
              id="website_url"
              theme={formTheme.textInput}
              type="url"
              placeholder="https://example.com"
              {...register('website_url')}
            />
            <HelperText color="failure">
              {errors.website_url?.message}
            </HelperText>
          </div>
        </div>
      </div>

      {/* Marketing Channels */}
      <div className="space-y-4">
        <h3 className="text-xl font-semibold text-gray-900">
          Marketing Channels
        </h3>
        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
          {marketingChannels.length > 0 ? (
            marketingChannels.map((channel) => (
              <label
                key={channel.id}
                className="flex items-center gap-3 rounded-xl border border-gray-200 bg-white p-4"
              >
                <Checkbox
                  checked={marketingChannelIds?.includes(channel.id)}
                  onChange={() => handleToggleMarketingChannel(channel.id)}
                  color="blue"
                />
                <span className="text-sm font-medium text-gray-700">
                  {channel.channel_name}
                </span>
              </label>
            ))
          ) : (
            <div className="text-sm text-gray-500">
              Loading marketing channels...
            </div>
          )}
        </div>
        <HelperText color="failure">
          {errors.marketing_channels?.message}
        </HelperText>
      </div>

      {/* Referral Links */}
      <div className="space-y-4">
        <ReferralLinksSection
          referralLinks={selectedReferralLinks}
          onChange={handleReferralLinksChange}
        />
      </div>
    </div>
  )
}
