'use client'

import { useCallback, useEffect, useMemo, useRef, useState } from 'react'

import { cmsApi } from '../../lib/api.js'

export type EmailProviderKey = 'resend' | 'smtpcom' | 'ses' | 'smtp'
export type SaveState = 'idle' | 'saving' | 'success' | 'error'

export const EMAIL_PROVIDER_OPTIONS: Array<{ value: EmailProviderKey; label: string }> = [
  { value: 'resend', label: 'Resend' },
  { value: 'smtpcom', label: 'SMTP.com' },
  { value: 'ses', label: 'Amazon SES' },
  { value: 'smtp', label: 'SMTP server' },
]

/** Form state. Secrets are write-only: inputs start empty and never echo stored values. */
export interface EmailSettingsForm {
  /** Empty string = email delivery not configured here. */
  provider: EmailProviderKey | ''
  from: string
  apiKey: string
  channel: string
  region: string
  host: string
  port: string
  secure: boolean
  smtpUser: string
  smtpPass: string
}

interface EmailSettingsResponse {
  settings: {
    provider: EmailProviderKey | null
    from?: string
    apiKeyLast4?: string
    hasApiKey: boolean
    channel?: string
    region?: string
    host?: string
    port?: number
    secure?: boolean
    smtpUser?: string
    hasSmtpPass: boolean
    lastTestStatus?: 'success' | 'failed'
    lastTestedAt?: string
    lastTestError?: string
  }
  envProvider: EmailProviderKey | null
  factoryAvailable: boolean
  envSenderActive: boolean
  platformAdapter: boolean
}

const EMPTY_FORM: EmailSettingsForm = {
  provider: '',
  from: '',
  apiKey: '',
  channel: '',
  region: '',
  host: '',
  port: '',
  secure: false,
  smtpUser: '',
  smtpPass: '',
}

function toForm(s: EmailSettingsResponse['settings']): EmailSettingsForm {
  return {
    provider: s.provider ?? '',
    from: s.from ?? '',
    apiKey: '',
    channel: s.channel ?? '',
    region: s.region ?? '',
    host: s.host ?? '',
    port: s.port != null ? String(s.port) : '',
    secure: s.secure ?? false,
    smtpUser: s.smtpUser ?? '',
    smtpPass: '',
  }
}

function snapshot(f: EmailSettingsForm): string {
  return JSON.stringify(f)
}

export interface UseEmailSettings {
  loading: boolean
  loadError: string | null
  form: EmailSettingsForm
  /** Masked metadata about stored secrets (never the secret itself). */
  stored: {
    hasApiKey: boolean
    apiKeyLast4?: string
    hasSmtpPass: boolean
    sameProvider: boolean
  }
  env: { provider: EmailProviderKey | null; senderActive: boolean }
  factoryAvailable: boolean
  platformAdapter: boolean
  lastTest: { status?: 'success' | 'failed'; testedAt?: string; error?: string }
  dirty: boolean
  saveState: SaveState
  saveError: string | null
  testing: boolean
  testResult: { success: boolean; message: string } | null
  setField: <K extends keyof EmailSettingsForm>(key: K, value: EmailSettingsForm[K]) => void
  save: () => Promise<void>
  sendTest: () => Promise<void>
  reset: () => void
  reload: () => void
}

export function useEmailSettings(canEdit: boolean): UseEmailSettings {
  const [loading, setLoading] = useState(true)
  const [loadError, setLoadError] = useState<string | null>(null)
  const [form, setForm] = useState<EmailSettingsForm>(EMPTY_FORM)
  const [meta, setMeta] = useState<Omit<EmailSettingsResponse, 'settings'>>({
    envProvider: null,
    factoryAvailable: false,
    envSenderActive: false,
    platformAdapter: false,
  })
  const [storedSecrets, setStoredSecrets] = useState({
    provider: null as EmailProviderKey | null,
    hasApiKey: false,
    apiKeyLast4: undefined as string | undefined,
    hasSmtpPass: false,
  })
  const [lastTest, setLastTest] = useState<UseEmailSettings['lastTest']>({})
  const [saveState, setSaveState] = useState<SaveState>('idle')
  const [saveError, setSaveError] = useState<string | null>(null)
  const [testing, setTesting] = useState(false)
  const [testResult, setTestResult] = useState<UseEmailSettings['testResult']>(null)

  const baselineRef = useRef<string>(snapshot(EMPTY_FORM))

  const applyResponse = useCallback((d: EmailSettingsResponse) => {
    const nextForm = toForm(d.settings)
    setForm(nextForm)
    baselineRef.current = snapshot(nextForm)
    setMeta({
      envProvider: d.envProvider,
      factoryAvailable: d.factoryAvailable,
      envSenderActive: d.envSenderActive,
      platformAdapter: d.platformAdapter,
    })
    setStoredSecrets({
      provider: d.settings.provider,
      hasApiKey: d.settings.hasApiKey,
      apiKeyLast4: d.settings.apiKeyLast4,
      hasSmtpPass: d.settings.hasSmtpPass,
    })
    setLastTest({
      status: d.settings.lastTestStatus,
      testedAt: d.settings.lastTestedAt,
      error: d.settings.lastTestError,
    })
  }, [])

  const load = useCallback(async () => {
    setLoading(true)
    setLoadError(null)
    const res = await cmsApi<EmailSettingsResponse>('/email/settings')
    if (res.error || !res.data) {
      setLoadError(res.error ?? 'Failed to load email settings')
      setLoading(false)
      return
    }
    applyResponse(res.data)
    setSaveState('idle')
    setLoading(false)
  }, [applyResponse])

  useEffect(() => {
    void load()
  }, [load])

  const setField = useCallback(
    <K extends keyof EmailSettingsForm>(key: K, value: EmailSettingsForm[K]) => {
      setForm((prev) => ({ ...prev, [key]: value }))
      setSaveState('idle')
      setSaveError(null)
      setTestResult(null)
    },
    [],
  )

  const dirty = useMemo(() => snapshot(form) !== baselineRef.current, [form])

  const save = useCallback(async () => {
    if (!canEdit) return
    setSaveState('saving')
    setSaveError(null)

    let body: Record<string, unknown>
    if (form.provider === '') {
      body = { provider: null }
    } else {
      body = {
        provider: form.provider,
        from: form.from.trim(),
        // Secrets: omit = keep stored value; include only when re-entered.
        ...(form.apiKey.trim() ? { apiKey: form.apiKey.trim() } : {}),
        ...(form.provider === 'smtpcom' && form.channel.trim()
          ? { channel: form.channel.trim() }
          : {}),
        ...(form.provider === 'ses' ? { region: form.region.trim() } : {}),
        ...(form.provider === 'smtp'
          ? {
              host: form.host.trim(),
              ...(form.port.trim() ? { port: Number(form.port) } : {}),
              secure: form.secure,
              ...(form.smtpUser.trim() ? { smtpUser: form.smtpUser.trim() } : {}),
              ...(form.smtpPass ? { smtpPass: form.smtpPass } : {}),
            }
          : {}),
      }
    }

    const res = await cmsApi<{ settings: EmailSettingsResponse['settings'] }>('/email/settings', {
      method: 'PUT',
      body: JSON.stringify(body),
    })
    if (res.error || !res.data) {
      setSaveState('error')
      setSaveError(res.error ?? 'Failed to save email settings')
      return
    }
    const nextForm = toForm(res.data.settings)
    setForm(nextForm)
    baselineRef.current = snapshot(nextForm)
    setStoredSecrets({
      provider: res.data.settings.provider,
      hasApiKey: res.data.settings.hasApiKey,
      apiKeyLast4: res.data.settings.apiKeyLast4,
      hasSmtpPass: res.data.settings.hasSmtpPass,
    })
    setLastTest({})
    setSaveState('success')
  }, [canEdit, form])

  const sendTest = useCallback(async () => {
    setTesting(true)
    setTestResult(null)
    const res = await cmsApi<{ success: boolean; sentTo?: string }>('/email/settings/test', {
      method: 'POST',
      body: JSON.stringify({}),
    })
    setTesting(false)
    if (res.error || !res.data?.success) {
      const message = res.error ?? 'Test send failed'
      setTestResult({ success: false, message })
      setLastTest({ status: 'failed', testedAt: new Date().toISOString(), error: message })
      return
    }
    setTestResult({
      success: true,
      message: `Test email sent to ${res.data.sentTo ?? 'your address'}.`,
    })
    setLastTest({ status: 'success', testedAt: new Date().toISOString() })
  }, [])

  const reset = useCallback(() => {
    setForm(JSON.parse(baselineRef.current) as EmailSettingsForm)
    setSaveState('idle')
    setSaveError(null)
    setTestResult(null)
  }, [])

  return {
    loading,
    loadError,
    form,
    stored: {
      hasApiKey: storedSecrets.hasApiKey,
      apiKeyLast4: storedSecrets.apiKeyLast4,
      hasSmtpPass: storedSecrets.hasSmtpPass,
      sameProvider: form.provider !== '' && form.provider === storedSecrets.provider,
    },
    env: { provider: meta.envProvider, senderActive: meta.envSenderActive },
    factoryAvailable: meta.factoryAvailable,
    platformAdapter: meta.platformAdapter,
    lastTest,
    dirty,
    saveState,
    saveError,
    testing,
    testResult,
    setField,
    save,
    sendTest,
    reset,
    reload: () => void load(),
  }
}
