'use client'

import { useMemo, useState } from 'react'
import { Code2, Copy, Plus, Loader2, AlertTriangle, Shield, Trash2 } from 'lucide-react'
import { toast } from 'sonner'
import { EnabledSwitch } from '../components/EnabledSwitch.js'
import { Button } from '../components/ui/Button.js'
import { ConfirmDialog } from '../components/ui/ConfirmDialog.js'
import { FilterPill } from '../components/ui/FilterPill.js'
import { RowActions, RowActionButton } from '../components/ui/RowActions.js'
import { SearchInput } from '../components/ui/SearchInput.js'
import { StatPill } from '../components/ui/StatPill.js'
import { InspectorPane, SplitPaneLayout, SplitPaneList } from '../components/ui/InspectorPane.js'
import {
  CONSENT_COLORS,
  CONSENT_LABELS,
  NO_CONSENT_COLORS,
  PLACEMENT_COLORS,
  PLACEMENT_LABELS,
  ScriptTagEditorPane,
  type ScriptTag,
} from '../components/script-tags/ScriptTagEditorPane.js'
import { useApiData } from '../lib/useApiData.js'
import { cmsApi } from '../lib/api.js'

export interface ScriptTagsProps {
  onNavigate?: (path: string) => void
  /** Deep-link support: open this tag's editor pane on mount (/script-tags/:id). */
  initialSelectedId?: string
  /** Deep-link support: open the create pane on mount (/script-tags/new). */
  initialNew?: boolean
}

const LOCATION_FILTERS: Array<{ value: string; label: string }> = [
  { value: 'all', label: 'All' },
  { value: 'head', label: '<head>' },
  { value: 'body_open', label: 'Body start' },
  { value: 'body_close', label: 'Body end' },
]

const CONSENT_FILTERS: Array<{ value: string; label: string }> = [
  { value: 'all', label: 'All consent' },
  { value: 'none', label: 'No consent' },
  { value: 'analytics', label: 'Analytics' },
  { value: 'marketing', label: 'Marketing' },
  { value: 'functional', label: 'Functional' },
  { value: 'preferences', label: 'Preferences' },
]

function normalizeEnabled(value: unknown): boolean {
  if (typeof value === 'boolean') return value
  if (value === 'true' || value === 1) return true
  if (value === 'false' || value === 0 || value === null) return false
  return true
}

function scopeLabel(tag: ScriptTag): string {
  const scope = String(tag.scope ?? '')
  const targetPaths = Array.isArray(tag.targetPaths) ? tag.targetPaths : []
  if (scope === 'site') return 'Entire Site'
  if (scope === 'parents') {
    const count = targetPaths.length
    return `${count} parent path${count !== 1 ? 's' : ''} + children`
  }
  if (scope === 'urls') {
    const count = targetPaths.length
    return `${count} URL${count !== 1 ? 's' : ''}`
  }
  return scope || 'Custom'
}

function formatDate(value: string): string {
  const date = new Date(value)
  if (Number.isNaN(date.getTime())) return '—'
  return date.toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' })
}

function consentCategoryOf(tag: ScriptTag): string {
  return tag.consentCategory && tag.consentCategory !== '' ? tag.consentCategory : 'none'
}

type Selection = { mode: 'edit'; id: string } | { mode: 'new' } | null

export function ScriptTags({ initialSelectedId, initialNew }: ScriptTagsProps) {
  const { data, loading, error, refetch } = useApiData<ScriptTag[]>('/script-tags')
  const [togglingId, setTogglingId] = useState<string | null>(null)
  const [enabledOverrides, setEnabledOverrides] = useState<Record<string, boolean>>({})
  const [search, setSearch] = useState('')
  const [locationFilter, setLocationFilter] = useState('all')
  const [consentFilter, setConsentFilter] = useState('all')
  const [checkedIds, setCheckedIds] = useState<Set<string>>(new Set())
  const [pendingDelete, setPendingDelete] = useState<ScriptTag | null>(null)
  const [selection, setSelection] = useState<Selection>(
    initialNew
      ? { mode: 'new' }
      : initialSelectedId
        ? { mode: 'edit', id: initialSelectedId }
        : null,
  )

  const tags = useMemo(
    () =>
      (data ?? []).map((tag) => ({
        ...tag,
        enabled: enabledOverrides[tag.id] ?? normalizeEnabled(tag.enabled),
      })),
    [data, enabledOverrides],
  )

  const filteredTags = useMemo(() => {
    const query = search.trim().toLowerCase()
    return tags.filter((tag) => {
      if (locationFilter !== 'all' && tag.placement !== locationFilter) return false
      if (consentFilter !== 'all' && consentCategoryOf(tag) !== consentFilter) return false
      if (query && !tag.name.toLowerCase().includes(query)) return false
      return true
    })
  }, [tags, locationFilter, consentFilter, search])

  const consentGatedCount = tags.filter((t) => consentCategoryOf(t) !== 'none').length
  const checkedVisible = filteredTags.filter((t) => checkedIds.has(t.id))
  const allVisibleChecked = filteredTags.length > 0 && checkedVisible.length === filteredTags.length

  const selectedTag =
    selection?.mode === 'edit' ? (tags.find((t) => t.id === selection.id) ?? null) : null
  const paneOpen = selection?.mode === 'new' || selectedTag !== null

  const toggleRow = (tag: ScriptTag) => {
    setSelection((prev) =>
      prev?.mode === 'edit' && prev.id === tag.id ? null : { mode: 'edit', id: tag.id },
    )
  }

  const toggleChecked = (id: string) => {
    setCheckedIds((prev) => {
      const next = new Set(prev)
      if (next.has(id)) next.delete(id)
      else next.add(id)
      return next
    })
  }

  const toggleAllChecked = () => {
    setCheckedIds(allVisibleChecked ? new Set() : new Set(filteredTags.map((t) => t.id)))
  }

  const clearFilters = () => {
    setSearch('')
    setLocationFilter('all')
    setConsentFilter('all')
  }

  const toggleEnabled = async (tag: ScriptTag, nextEnabled: boolean) => {
    setEnabledOverrides((prev) => ({ ...prev, [tag.id]: nextEnabled }))
    setTogglingId(tag.id)

    const res = await cmsApi<{ enabled?: boolean }>(`/script-tags/${tag.id}`, {
      method: 'PUT',
      body: JSON.stringify({ enabled: nextEnabled }),
    })

    setTogglingId(null)

    if (res.error) {
      setEnabledOverrides((prev) => {
        const { [tag.id]: _, ...rest } = prev
        return rest
      })
      toast.error(res.error)
      return
    }

    const saved = normalizeEnabled(res.data?.enabled ?? nextEnabled)
    setEnabledOverrides((prev) => ({ ...prev, [tag.id]: saved }))
    refetch()
    toast.success(saved ? 'Tag enabled' : 'Tag disabled')
  }

  const duplicateTag = async (tag: ScriptTag) => {
    const res = await cmsApi<ScriptTag>('/script-tags', {
      method: 'POST',
      body: JSON.stringify({
        name: `${tag.name} (Copy)`,
        code: tag.code,
        placement: tag.placement,
        scope: tag.scope,
        targetPaths: tag.targetPaths,
        priority: tag.priority,
        enabled: false,
        loadAsync: tag.loadAsync,
        disableInPreview: tag.disableInPreview,
        consentCategory: tag.consentCategory,
      }),
    })
    if (res.error) {
      toast.error(res.error)
      return
    }
    toast.success('Script duplicated (created disabled)')
    refetch()
    if (res.data?.id) setSelection({ mode: 'edit', id: res.data.id })
  }

  const deleteTag = async (tag: ScriptTag) => {
    setPendingDelete(null)
    const res = await cmsApi(`/script-tags/${tag.id}`, { method: 'DELETE' })
    if (res.error) {
      toast.error(res.error)
      return
    }
    toast.success('Script deleted')
    setCheckedIds((prev) => {
      const next = new Set(prev)
      next.delete(tag.id)
      return next
    })
    if (selection?.mode === 'edit' && selection.id === tag.id) setSelection(null)
    refetch()
  }

  const handlePaneChanged = (savedId?: string) => {
    setEnabledOverrides({})
    refetch()
    if (savedId) setSelection({ mode: 'edit', id: savedId })
  }

  if (loading) {
    return (
      <div className="flex h-64 items-center justify-center p-3 pr-6 sm:p-4 sm:pr-8">
        <Loader2 className="text-primary h-6 w-6 animate-spin" />
      </div>
    )
  }

  return (
    <div className="flex h-full min-h-0 flex-col">
      <div className="p-3 pr-6 pb-0 sm:p-4 sm:pr-8 sm:pb-0">
        {error && (
          <div className="border-destructive/30 bg-destructive/10 mb-4 flex items-center gap-3 rounded-lg border p-4">
            <AlertTriangle className="text-destructive h-5 w-5 shrink-0" />
            <span className="text-destructive flex-1 text-sm">{error}</span>
            <button
              onClick={refetch}
              className="border-destructive/40 text-destructive hover:bg-destructive/15 rounded-lg border px-3 py-1 text-sm transition-colors focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none"
            >
              Retry
            </button>
          </div>
        )}

        <div className="mb-4 flex items-center justify-between">
          <div>
            <h1 className="mb-1 text-[var(--txt)]">Script Tags</h1>
            <p className="text-sm text-[var(--sub)]">
              Inject scripts into the frontend — never into CMS rendering
            </p>
            {tags.length > 0 && (
              <div className="mt-3 flex flex-wrap gap-1.5">
                <StatPill value={tags.length} label="Total" />
                <StatPill
                  value={tags.filter((t) => t.enabled).length}
                  label="Active"
                  valueClassName="text-[var(--suc)]"
                />
                <StatPill
                  value={tags.filter((t) => !t.enabled).length}
                  label="Inactive"
                  valueClassName="text-[var(--muted)]"
                />
                <StatPill
                  value={consentGatedCount}
                  label="Consent-gated"
                  icon={<Shield size={12} className="text-[var(--acc)]" aria-hidden />}
                />
              </div>
            )}
          </div>
          <Button
            type="button"
            variant="primary"
            size="md"
            onClick={() => setSelection({ mode: 'new' })}
            leftIcon={<Plus size={16} aria-hidden />}
          >
            New Script
          </Button>
        </div>

        {tags.length > 0 && (
          <div className="mb-3 flex flex-wrap items-center gap-2">
            <div className="w-full max-w-[260px]">
              <SearchInput value={search} onChange={setSearch} placeholder="Search scripts…" />
            </div>
            <div className="flex gap-1" role="group" aria-label="Filter by location">
              {LOCATION_FILTERS.map((f) => (
                <FilterPill
                  key={f.value}
                  active={locationFilter === f.value}
                  onClick={() => setLocationFilter(f.value)}
                >
                  {f.label}
                </FilterPill>
              ))}
            </div>
            <div className="ml-2 flex flex-wrap gap-1" role="group" aria-label="Filter by consent">
              {CONSENT_FILTERS.map((f) => (
                <FilterPill
                  key={f.value}
                  active={consentFilter === f.value}
                  onClick={() => setConsentFilter(f.value)}
                >
                  {f.label}
                </FilterPill>
              ))}
            </div>
            <span className="ml-auto text-xs text-[var(--muted)]" aria-live="polite">
              {checkedIds.size > 0 ? (
                <>
                  {checkedIds.size} selected ·{' '}
                  <button
                    type="button"
                    onClick={() => setCheckedIds(new Set())}
                    className="rounded-sm text-[var(--acc)] hover:underline focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none"
                  >
                    Clear
                  </button>
                </>
              ) : (
                `${filteredTags.length} script${filteredTags.length !== 1 ? 's' : ''}`
              )}
            </span>
          </div>
        )}
      </div>

      <SplitPaneLayout>
        <SplitPaneList className="p-4 pr-8 sm:pr-8">
          {tags.length === 0 && !error ? (
            <div className="rounded-lg border border-[var(--bdr)] bg-[var(--card)] p-12 text-center">
              <Code2 className="mx-auto mb-3 h-10 w-10 text-[var(--sub)]" />
              <h3 className="text-sm font-medium text-[var(--txt)]">No script tags yet</h3>
              <p className="mt-1 text-sm text-[var(--sub)]">
                Add tracking codes like Google Analytics, Tag Manager, or Facebook Pixel.
              </p>
              <Button
                type="button"
                variant="primary"
                size="md"
                className="mt-4"
                onClick={() => setSelection({ mode: 'new' })}
                leftIcon={<Plus size={16} aria-hidden />}
              >
                Add Your First Script
              </Button>
            </div>
          ) : filteredTags.length === 0 ? (
            <div className="rounded-lg border border-[var(--bdr)] bg-[var(--card)] p-12 text-center">
              <Code2 className="mx-auto mb-3 h-10 w-10 text-[var(--sub)]" />
              <h3 className="text-sm font-medium text-[var(--txt)]">
                No scripts match your filters
              </h3>
              <p className="mt-1 text-sm text-[var(--sub)]">
                Try a different search term or clear the filters.
              </p>
              <button
                type="button"
                onClick={clearFilters}
                className="mt-3 rounded-sm text-sm text-[var(--acc)] hover:underline focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none"
              >
                Clear filters
              </button>
            </div>
          ) : (
            <div className="overflow-x-auto rounded-lg border border-[var(--bdr)] bg-[var(--card)]">
              {/* min-w keeps the 8 columns readable; narrow viewports scroll sideways. */}
              <table className="w-full min-w-[920px] text-sm" aria-label="Script tags">
                <thead>
                  <tr className="bg-muted border-b border-[var(--bdr)]">
                    <th className="w-9 px-3 py-3">
                      <input
                        type="checkbox"
                        checked={allVisibleChecked}
                        onChange={toggleAllChecked}
                        aria-label={
                          allVisibleChecked ? 'Deselect all scripts' : 'Select all scripts'
                        }
                        className="h-[15px] w-[15px] cursor-pointer accent-[var(--acc)]"
                      />
                    </th>
                    <th className="px-4 py-3 text-left font-medium text-[var(--sub)]">Script</th>
                    <th className="px-4 py-3 text-left font-medium text-[var(--sub)]">Location</th>
                    <th className="px-4 py-3 text-center font-medium text-[var(--sub)]">
                      Priority
                    </th>
                    <th className="px-4 py-3 text-left font-medium text-[var(--sub)]">Scope</th>
                    <th className="px-4 py-3 text-left font-medium text-[var(--sub)]">Consent</th>
                    <th className="px-4 py-3 text-center font-medium text-[var(--sub)]">Active</th>
                    <th className="px-4 py-3 text-right font-medium text-[var(--sub)]">Updated</th>
                  </tr>
                </thead>
                <tbody>
                  {filteredTags.map((tag) => {
                    const isSelected = selection?.mode === 'edit' && selection.id === tag.id
                    const consent = CONSENT_COLORS[consentCategoryOf(tag)] ?? NO_CONSENT_COLORS
                    return (
                      <tr
                        key={tag.id}
                        className={`group cursor-pointer border-b border-[var(--bdr)] transition-colors last:border-0 ${
                          isSelected ? 'bg-[var(--acc-l)]' : 'hover:bg-[var(--acc-l)]'
                        }`}
                        onClick={() => toggleRow(tag)}
                      >
                        <td className="px-3 py-[11px]" onClick={(e) => e.stopPropagation()}>
                          <input
                            type="checkbox"
                            checked={checkedIds.has(tag.id)}
                            onChange={() => toggleChecked(tag.id)}
                            aria-label={`Select ${tag.name}`}
                            className="h-[15px] w-[15px] cursor-pointer accent-[var(--acc)]"
                          />
                        </td>
                        <td className="px-4 py-[11px]">
                          <button
                            type="button"
                            onClick={(e) => {
                              e.stopPropagation()
                              toggleRow(tag)
                            }}
                            aria-expanded={isSelected}
                            className="text-left font-medium text-[var(--txt)] hover:text-[var(--acc)]"
                          >
                            {tag.name}
                          </button>
                          <div className="mt-0.5 text-[11.5px] text-[var(--muted)]">
                            Added {formatDate(tag.createdAt)}
                          </div>
                        </td>
                        <td className="px-4 py-[11px]">
                          <span
                            className={`inline-flex items-center rounded-[5px] px-2 py-[3px] text-[11.5px] font-medium ${PLACEMENT_COLORS[tag.placement] ?? 'bg-muted text-[var(--txt)]'}`}
                          >
                            {PLACEMENT_LABELS[tag.placement] ?? tag.placement}
                          </span>
                        </td>
                        <td className="px-4 py-[11px] text-center">
                          <span className="inline-flex h-6 w-6 items-center justify-center rounded-full border-[1.5px] border-[var(--bdr)] bg-[var(--bg)] text-[11.5px] font-semibold text-[var(--sub)]">
                            {tag.priority}
                          </span>
                        </td>
                        <td className="px-4 py-[11px] text-[var(--sub)]">{scopeLabel(tag)}</td>
                        <td className="px-4 py-[11px]">
                          <span
                            className={`inline-flex items-center gap-[3px] rounded-[4px] px-[7px] py-0.5 text-[11px] font-medium ${consent.badge}`}
                          >
                            <span
                              className={`inline-block h-[5px] w-[5px] rounded-full ${consent.dot}`}
                              aria-hidden
                            />
                            {CONSENT_LABELS[consentCategoryOf(tag)] ?? tag.consentCategory}
                          </span>
                        </td>
                        <td
                          className="px-4 py-[11px] text-center"
                          onClick={(e) => e.stopPropagation()}
                        >
                          <EnabledSwitch
                            checked={tag.enabled}
                            disabled={togglingId === tag.id}
                            onCheckedChange={(next) => void toggleEnabled(tag, next)}
                            aria-label={`${tag.enabled ? 'Disable' : 'Enable'} ${tag.name}`}
                          />
                        </td>
                        <td className="px-4 py-[11px]">
                          <div className="flex items-center justify-end gap-2">
                            <RowActions>
                              <RowActionButton
                                aria-label={`Duplicate ${tag.name}`}
                                onClick={(e) => {
                                  e.stopPropagation()
                                  void duplicateTag(tag)
                                }}
                              >
                                <Copy size={12} aria-hidden />
                              </RowActionButton>
                              <RowActionButton
                                danger
                                aria-label={`Delete ${tag.name}`}
                                onClick={(e) => {
                                  e.stopPropagation()
                                  setPendingDelete(tag)
                                }}
                              >
                                <Trash2 size={12} aria-hidden />
                              </RowActionButton>
                            </RowActions>
                            <span className="text-xs whitespace-nowrap text-[var(--sub)]">
                              {formatDate(tag.updatedAt)}
                            </span>
                          </div>
                        </td>
                      </tr>
                    )
                  })}
                </tbody>
              </table>
            </div>
          )}
        </SplitPaneList>

        <InspectorPane open={paneOpen} width={420} aria-label="Script editor">
          <ScriptTagEditorPane
            key={selection?.mode === 'edit' ? selection.id : 'new'}
            tag={selectedTag}
            onClose={() => setSelection(null)}
            onChanged={handlePaneChanged}
          />
        </InspectorPane>
      </SplitPaneLayout>

      <ConfirmDialog
        open={pendingDelete !== null}
        title="Delete script?"
        description={`"${pendingDelete?.name ?? 'This script'}" will stop firing on your site immediately.`}
        confirmLabel="Delete"
        destructive
        onConfirm={() => {
          if (pendingDelete) void deleteTag(pendingDelete)
        }}
        onClose={() => setPendingDelete(null)}
      />
    </div>
  )
}
