/**
 * ConsentPreferences — granular cookie category toggle modal.
 *
 * Composes the existing Dialog primitive.  Lists categories from
 * useConsent().fetchCategories() and renders a Switch per category.
 * Required categories have the toggle disabled.
 *
 * Props mirror Radix Dialog: open + onOpenChange for controlled usage.
 */
import { useState, useEffect } from 'react'

import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
} from '../primitives/dialog'
import { Button } from '../primitives/button'
import { Switch } from '../primitives/switch'
import { Skeleton } from '../primitives/skeleton'
import { Collapsible, CollapsibleTrigger, CollapsibleContent } from '../primitives/collapsible'
import { useConsent } from '../hooks/useConsent'
import type { CategoryInfo, ConsentCategories } from '../hooks/useConsent'

export interface ConsentPreferencesProps {
  open: boolean
  onOpenChange: (open: boolean) => void
}

export function ConsentPreferences({ open, onOpenChange }: ConsentPreferencesProps) {
  const { preferences, acceptAll, rejectAll, fetchCategories, saveConsent } = useConsent()

  const [categories, setCategories] = useState<CategoryInfo[]>([])
  const [loading, setLoading] = useState(false)
  const [saving, setSaving] = useState(false)

  // Local state for per-category toggles — seeded from stored preferences.
  const [localPrefs, setLocalPrefs] = useState<ConsentCategories>({
    essential: true,
    performance: false,
    analytics: false,
    advertising: false,
    social_media: false,
  })

  // Fetch categories when the dialog opens.
  useEffect(() => {
    if (!open) return
    setLoading(true)
    fetchCategories()
      .then(cats => {
        setCategories(cats)
      })
      .catch(() => {
        setCategories([])
      })
      .finally(() => {
        setLoading(false)
      })
  }, [open, fetchCategories])

  // Seed local prefs from stored preferences when dialog opens.
  useEffect(() => {
    if (!open) return
    if (preferences) {
      setLocalPrefs(preferences)
    }
  }, [open, preferences])

  function handleToggle(categoryId: string, value: boolean) {
    setLocalPrefs(prev => ({ ...prev, [categoryId]: value }))
  }

  function handleAcceptAll() {
    acceptAll()
    onOpenChange(false)
  }

  function handleRejectAll() {
    rejectAll()
    onOpenChange(false)
  }

  async function handleSave() {
    setSaving(true)
    try {
      await saveConsent(localPrefs, 'preferences')
    } finally {
      setSaving(false)
      onOpenChange(false)
    }
  }

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-h-[85dvh] overflow-y-auto sm:max-w-xl" showCloseButton>
        <DialogHeader>
          <DialogTitle>Cookie preferences</DialogTitle>
          <DialogDescription>
            Manage which categories of cookies you allow. Required cookies cannot be disabled.
          </DialogDescription>
        </DialogHeader>

        {/* Quick-action shortcuts */}
        <div className="flex gap-2 border-b border-border-glass pb-4">
          <Button variant="secondary" size="sm" type="button" onClick={handleAcceptAll}>
            Accept all
          </Button>
          <Button variant="ghost" size="sm" type="button" onClick={handleRejectAll}>
            Reject all
          </Button>
        </div>

        {/* Category list */}
        <div className="space-y-4" role="list">
          {loading
            ? // Skeleton rows while fetching.
              Array.from({ length: 3 }).map((_, i) => (
                <div key={i} className="space-y-2">
                  <Skeleton className="h-5 w-1/3" />
                  <Skeleton className="h-4 w-full" />
                </div>
              ))
            : categories.length > 0
              ? categories.map(cat => (
                  <CategoryRow
                    key={cat.id}
                    category={cat}
                    value={localPrefs[cat.id as keyof ConsentCategories] ?? false}
                    onToggle={handleToggle}
                  />
                ))
              : // Fallback when the API returns nothing — show hardcoded essential row.
                null}
        </div>

        <DialogFooter>
          <Button
            variant="default"
            type="button"
            onClick={() => void handleSave()}
            loading={saving}
          >
            Save preferences
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  )
}

// ── Internal ──────────────────────────────────────────────────────────────────

interface CategoryRowProps {
  category: CategoryInfo
  value: boolean
  onToggle: (id: string, value: boolean) => void
}

function CategoryRow({ category, value, onToggle }: CategoryRowProps) {
  const switchId = `consent-cat-${category.id}`

  return (
    <div role="listitem" className="flex flex-col gap-2 rounded-xl border border-border-glass p-4">
      <div className="flex items-center justify-between gap-3">
        <div>
          <label htmlFor={switchId} className="text-foreground text-sm font-medium">
            {category.name}
            {category.required && (
              <span className="text-foreground-muted ml-2 text-xs font-normal">(Required)</span>
            )}
          </label>
          <p className="text-foreground-muted mt-0.5 text-xs">{category.description}</p>
        </div>
        <Switch
          id={switchId}
          checked={category.required ? true : value}
          disabled={category.required}
          onCheckedChange={checked => {
            onToggle(category.id, checked)
          }}
          aria-label={`${category.name} cookies`}
        />
      </div>

      {category.cookies.length > 0 && (
        <Collapsible defaultOpen={false}>
          <CollapsibleTrigger className="text-foreground-muted flex items-center gap-1 text-xs hover:text-foreground">
            View cookies ({category.cookies.length})
          </CollapsibleTrigger>
          <CollapsibleContent>
            <div className="mt-2 space-y-1.5">
              {category.cookies.map(cookie => (
                <div key={cookie.name} className="rounded-lg bg-glass px-3 py-2 text-xs">
                  <span className="text-foreground font-medium">{cookie.name}</span>
                  {cookie.provider && (
                    <span className="text-foreground-muted ml-2">· {cookie.provider}</span>
                  )}
                  {cookie.description && (
                    <p className="text-foreground-muted mt-0.5">{cookie.description}</p>
                  )}
                </div>
              ))}
            </div>
          </CollapsibleContent>
        </Collapsible>
      )}
    </div>
  )
}
