'use client'

import * as Dialog from '@radix-ui/react-dialog'
import { AlertTriangle, Check, Loader2, Lock } from 'lucide-react'
import { useId, type ReactNode } from 'react'
import type { SettingsSourceMetadata, ValidationIssue } from './useGeneralSettings.js'

/**
 * The canonical Settings section card: a bordered `bg-card` surface with a
 * header (title + optional description) and an optional right-aligned actions
 * slot. This is the single source of truth for the Settings design language —
 * every tab's sections render through it so spacing, padding, typography, and
 * the title/description rhythm stay identical across General, Appearance,
 * Security, SEO, AI, and beyond. Match the Appearance tab exactly: `p-6`,
 * `text-lg` medium title, `text-sm` muted description.
 */
export function SettingsCard({
  title,
  description,
  actions,
  children,
  className,
  headingLevel: Heading = 'h3',
}: {
  title: ReactNode
  description?: ReactNode
  /** Right-aligned controls in the header (e.g. a Refresh or Add button). */
  actions?: ReactNode
  children: ReactNode
  className?: string
  /** Override the heading element for correct document outline nesting. */
  headingLevel?: 'h2' | 'h3'
}) {
  const headingId = useId()
  return (
    <section
      aria-labelledby={headingId}
      className={`border-border bg-card rounded-lg border p-6 ${className ?? ''}`}
    >
      <header className="mb-4 flex items-start justify-between gap-3">
        <div className="min-w-0">
          <Heading id={headingId} className="text-foreground text-lg font-medium">
            {title}
          </Heading>
          {description && <p className="text-muted-foreground mt-0.5 text-sm">{description}</p>}
        </div>
        {actions && <div className="flex shrink-0 items-center gap-2">{actions}</div>}
      </header>
      {children}
    </section>
  )
}

/**
 * A sub-section inside a {@link SettingsCard}: a top divider plus a
 * `text-base` medium label and optional description. Use for grouped controls
 * within a single card (e.g. "Admin branding" under "Branding").
 */
export function SettingsSubsection({
  title,
  description,
  children,
  className,
}: {
  title: ReactNode
  description?: ReactNode
  children?: ReactNode
  className?: string
}) {
  return (
    <div className={`border-border border-t pt-4 ${className ?? ''}`}>
      <div className="text-foreground text-base font-medium">{title}</div>
      {description && <p className="text-muted-foreground mt-0.5 text-sm">{description}</p>}
      {children}
    </div>
  )
}

/**
 * A single setting row: an optional leading visual plus a label and
 * description on the left, and a control aligned to the right edge. This is the
 * uniform rhythm for compact controls (upload buttons, segmented toggles)
 * inside a {@link SettingsCard} — mirror it everywhere so rows line up instead
 * of stacking controls beneath their copy.
 */
export function SettingsControlRow({
  label,
  description,
  control,
  leading,
  htmlFor,
  align = 'center',
  className,
}: {
  label: ReactNode
  description?: ReactNode
  /** Right-aligned control(s) for this row. */
  control: ReactNode
  /** Optional visual (e.g. a logo thumbnail) shown before the label. */
  leading?: ReactNode
  /** When set, the label renders as a `<label>` bound to this control id. */
  htmlFor?: string
  /** Vertical alignment of the two columns. Defaults to centered. */
  align?: 'center' | 'start'
  className?: string
}) {
  const labelClass = 'text-foreground block text-base font-medium'
  return (
    <div
      className={`flex justify-between gap-4 ${align === 'center' ? 'items-center' : 'items-start'} ${className ?? ''}`}
    >
      <div className="flex min-w-0 items-center gap-4">
        {leading}
        <div className="min-w-0">
          {htmlFor ? (
            <label htmlFor={htmlFor} className={labelClass}>
              {label}
            </label>
          ) : (
            <span className={labelClass}>{label}</span>
          )}
          {description && <p className="text-muted-foreground mt-0.5 text-sm">{description}</p>}
        </div>
      </div>
      <div className="flex shrink-0 items-center gap-2">{control}</div>
    </div>
  )
}

const SOURCE_LABEL: Record<SettingsSourceMetadata['source'], string> = {
  config: 'Config-managed',
  environment: 'Environment-managed',
  database: 'Editable',
  plugin: 'Plugin setting',
  computed: 'Computed',
}

/** Small badge showing where a setting's value comes from. */
export function SettingsSourceBadge({ meta }: { meta?: SettingsSourceMetadata }) {
  if (!meta || (meta.source === 'database' && meta.editable)) return null
  const locked = !meta.editable
  return (
    <span
      className="text-muted-foreground border-border bg-muted inline-flex items-center gap-1 rounded-md border px-1.5 py-0.5 text-xs"
      title={meta.reason}
    >
      {locked && <Lock size={11} aria-hidden="true" />}
      {SOURCE_LABEL[meta.source]}
    </span>
  )
}

/** A labelled switch row with description, used for the SEO defaults. */
export function SettingsToggleRow({
  label,
  description,
  checked,
  onChange,
  disabled = false,
  badge,
}: {
  label: string
  description: string
  checked: boolean
  onChange: (value: boolean) => void
  disabled?: boolean
  badge?: ReactNode
}) {
  return (
    <div className="flex items-start justify-between gap-4">
      <div className="flex-1">
        <div className="flex items-center gap-2">
          <span className="text-foreground text-base font-medium">{label}</span>
          {badge}
        </div>
        <p className="text-muted-foreground mt-0.5 text-sm">{description}</p>
      </div>
      <button
        type="button"
        role="switch"
        aria-checked={checked}
        aria-label={label}
        disabled={disabled}
        onClick={() => onChange(!checked)}
        className={`focus-visible:ring-ring relative mt-0.5 h-6 w-11 shrink-0 rounded-full transition-colors focus-visible:ring-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 ${
          checked ? 'bg-brand' : 'bg-switch-background'
        }`}
      >
        <span
          className={`absolute top-0.5 block h-5 w-5 rounded-full bg-white shadow-sm transition-transform ${
            checked ? 'translate-x-[22px]' : 'translate-x-0.5'
          }`}
        />
      </button>
    </div>
  )
}

/** Aggregated validation messages shown above the cards. */
export function SettingsValidationSummary({ issues }: { issues: ValidationIssue[] }) {
  if (issues.length === 0) return null
  const errors = issues.filter((i) => i.severity === 'error')
  const warnings = issues.filter((i) => i.severity === 'warning')
  const isError = errors.length > 0
  return (
    <div
      role="alert"
      aria-live="polite"
      className={`flex items-start gap-3 rounded-lg border p-3 text-sm ${
        isError
          ? 'border-destructive/30 bg-destructive/10 text-destructive'
          : 'border-warning/30 bg-warning/10 text-warning'
      }`}
    >
      <AlertTriangle size={16} className="mt-0.5 shrink-0" aria-hidden="true" />
      <div className="space-y-1">
        {[...errors, ...warnings].map((issue, i) => (
          <p key={`${issue.field}-${i}`}>{issue.message}</p>
        ))}
      </div>
    </div>
  )
}

/** Sticky footer with Reset + Save, gated on dirty state. */
export function SettingsSaveBar({
  dirty,
  canEdit,
  hasErrors,
  saveState,
  onSave,
  onReset,
}: {
  dirty: boolean
  canEdit: boolean
  hasErrors: boolean
  saveState: 'idle' | 'saving' | 'success' | 'error'
  onSave: () => void
  onReset: () => void
}) {
  const saving = saveState === 'saving'
  return (
    <div className="border-border bg-background/80 sticky bottom-0 z-10 flex items-center justify-end gap-4 border-t py-3 backdrop-blur">
      {saveState === 'success' && !dirty && (
        <span className="text-success flex items-center gap-1.5 text-sm" aria-live="polite">
          <Check size={16} aria-hidden="true" /> Saved
        </span>
      )}
      <button
        type="button"
        onClick={onReset}
        disabled={!dirty || saving}
        className="text-muted-foreground hover:text-foreground rounded-md px-3 py-2 text-base transition-colors disabled:cursor-not-allowed disabled:opacity-40"
      >
        Reset
      </button>
      <button
        type="button"
        onClick={onSave}
        disabled={!canEdit || !dirty || hasErrors || saving}
        className="bg-brand text-brand-foreground focus-visible:ring-ring inline-flex items-center gap-2 rounded-md px-5 py-2 text-base font-medium transition-opacity hover:opacity-90 focus-visible:ring-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50"
      >
        {saving && <Loader2 size={16} className="animate-spin" aria-hidden="true" />}
        {saving ? 'Saving…' : 'Save Changes'}
      </button>
    </div>
  )
}

/** Confirmation dialog for dangerous indexing changes. */
export function ConfirmDangerousSettingDialog({
  open,
  title,
  description,
  confirmLabel = 'Continue',
  onConfirm,
  onCancel,
}: {
  open: boolean
  title: string
  description: string
  confirmLabel?: string
  onConfirm: () => void
  onCancel: () => void
}) {
  return (
    <Dialog.Root open={open} onOpenChange={(o) => !o && onCancel()}>
      <Dialog.Portal>
        <Dialog.Overlay className="fixed inset-0 z-50 bg-black/50" />
        <Dialog.Content className="bg-card text-card-foreground fixed top-1/2 left-1/2 z-50 w-full max-w-md -translate-x-1/2 -translate-y-1/2 rounded-lg p-6 shadow-lg">
          <div className="mb-3 flex items-center gap-2">
            <span className="bg-warning/15 text-warning flex h-9 w-9 items-center justify-center rounded-full">
              <AlertTriangle size={20} aria-hidden="true" />
            </span>
            <Dialog.Title className="text-foreground text-lg font-medium">{title}</Dialog.Title>
          </div>
          <Dialog.Description className="text-muted-foreground mb-5 text-sm">
            {description}
          </Dialog.Description>
          <div className="flex items-center justify-end gap-3">
            <button
              type="button"
              onClick={onCancel}
              className="border-border text-foreground hover:bg-accent rounded-md border px-4 py-2 text-base transition-colors"
            >
              Cancel
            </button>
            <button
              type="button"
              onClick={onConfirm}
              className="bg-destructive text-destructive-foreground rounded-md px-4 py-2 text-base font-medium transition-opacity hover:opacity-90"
            >
              {confirmLabel}
            </button>
          </div>
        </Dialog.Content>
      </Dialog.Portal>
    </Dialog.Root>
  )
}
