'use client'

import { useEffect, useState } from 'react'
import { Copy, Minus, Plus, Trash2, X } from 'lucide-react'
import { toast } from 'sonner'
import {
  InspectorPaneBody,
  InspectorPaneFooter,
  InspectorPaneHeader,
  InspectorPaneSection,
} from '../ui/InspectorPane.js'
import { Toggle } from '../ui/Toggle.js'
import { ConfirmDialog } from '../ui/ConfirmDialog.js'
import { cmsApi } from '../../lib/api.js'

export interface ScriptTag {
  id: string
  name: string
  code: string
  placement: string
  scope: string
  targetPaths: string[]
  priority: number
  enabled: boolean
  loadAsync: boolean
  disableInPreview: boolean
  consentCategory: string
  createdAt: string
  updatedAt: string
}

export const PLACEMENT_LABELS: Record<string, string> = {
  head: 'Head',
  body_open: 'Body start',
  body_close: 'Body end',
}

export const CONSENT_LABELS: Record<string, string> = {
  none: 'No consent',
  analytics: 'Analytics',
  marketing: 'Marketing',
  functional: 'Functional',
  preferences: 'Preferences',
}

/** Design-system location badges (`.loc-head` / `.loc-bs` / `.loc-be`). */
export const PLACEMENT_COLORS: Record<string, string> = {
  head: 'bg-[var(--acc-l)] text-[var(--acc)]',
  body_open: 'bg-[var(--suc-l)] text-[var(--suc)]',
  body_close: 'bg-[var(--info-l)] text-[var(--info)]',
}

export interface ConsentBadgeColors {
  badge: string
  dot: string
}

/** Neutral "No consent" chip — also the fallback for unknown categories. */
export const NO_CONSENT_COLORS: ConsentBadgeColors = {
  badge: 'border border-[var(--bdr)] bg-[var(--bg)] text-[var(--muted)]',
  dot: 'bg-[var(--muted)]',
}

/** Design-system consent badges (`.cb-*`): tinted chip + colored dot per category. */
export const CONSENT_COLORS: Record<string, ConsentBadgeColors> = {
  none: NO_CONSENT_COLORS,
  analytics: { badge: 'bg-[var(--acc-l)] text-[var(--acc)]', dot: 'bg-[var(--acc)]' },
  marketing: { badge: 'bg-[var(--err-l)] text-[var(--err)]', dot: 'bg-[var(--err)]' },
  functional: { badge: 'bg-[var(--suc-l)] text-[var(--suc)]', dot: 'bg-[var(--suc)]' },
  preferences: { badge: 'bg-[var(--warn-l)] text-[var(--warn)]', dot: 'bg-[var(--warn)]' },
}

const PLACEMENT_OPTIONS = [
  { value: 'head', label: 'Head', hint: '<head>' },
  { value: 'body_open', label: 'Body start', hint: '<body>' },
  { value: 'body_close', label: 'Body end', hint: '</body>' },
]

const SCOPE_OPTIONS = [
  { value: 'site', label: 'Entire site' },
  { value: 'parents', label: 'Parent pages' },
  { value: 'urls', label: 'Specific URLs' },
]

const CONSENT_OPTIONS = ['none', 'analytics', 'marketing', 'functional', 'preferences']

function OptionTile({
  active,
  onClick,
  children,
}: {
  active: boolean
  onClick: () => void
  children: React.ReactNode
}) {
  return (
    <button
      type="button"
      aria-pressed={active}
      onClick={onClick}
      className={`rounded-[7px] border px-2 py-2 text-[12px] font-medium transition-colors duration-[var(--motion-fast)] focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none ${
        active
          ? 'border-[var(--acc)] bg-[var(--acc-l)] text-[var(--acc)]'
          : 'border-[var(--bdr)] bg-[var(--card)] text-[var(--sub)] hover:border-[var(--acc-m)]'
      }`}
    >
      {children}
    </button>
  )
}

function ToggleRow({
  label,
  hint,
  checked,
  onCheckedChange,
}: {
  label: string
  hint: string
  checked: boolean
  onCheckedChange: (checked: boolean) => void
}) {
  return (
    <div className="flex items-center justify-between gap-3 py-1.5">
      <div className="min-w-0">
        <div className="text-[12.5px] font-medium text-[var(--txt)]">{label}</div>
        <div className="text-[11px] text-[var(--muted)]">{hint}</div>
      </div>
      <Toggle checked={checked} onCheckedChange={onCheckedChange} aria-label={label} />
    </div>
  )
}

export interface ScriptTagEditorPaneProps {
  /** null = create mode */
  tag: ScriptTag | null
  onClose: () => void
  /** Called after any successful save/duplicate/delete so the list can refetch. */
  onChanged: (savedId?: string) => void
}

export function ScriptTagEditorPane({ tag, onClose, onChanged }: ScriptTagEditorPaneProps) {
  const isNew = tag === null

  const [name, setName] = useState('')
  const [code, setCode] = useState('')
  const [placement, setPlacement] = useState('head')
  const [scope, setScope] = useState('site')
  const [targetPaths, setTargetPaths] = useState<string[]>([])
  const [pathInput, setPathInput] = useState('')
  const [priority, setPriority] = useState(100)
  const [enabled, setEnabled] = useState(true)
  const [loadAsync, setLoadAsync] = useState(false)
  const [disableInPreview, setDisableInPreview] = useState(true)
  const [consentCategory, setConsentCategory] = useState('none')
  const [saving, setSaving] = useState(false)
  const [confirmDelete, setConfirmDelete] = useState(false)

  useEffect(() => {
    setName(tag?.name ?? '')
    setCode(tag?.code ?? '')
    setPlacement(tag?.placement ?? 'head')
    setScope(tag?.scope ?? 'site')
    setTargetPaths(tag?.targetPaths ?? [])
    setPathInput('')
    setPriority(tag?.priority ?? 100)
    setEnabled(tag?.enabled ?? true)
    setLoadAsync(tag?.loadAsync ?? false)
    setDisableInPreview(tag?.disableInPreview ?? true)
    setConsentCategory(tag?.consentCategory ?? 'none')
  }, [tag])

  const addPath = () => {
    const trimmed = pathInput.trim()
    if (!trimmed) return
    const normalized = trimmed.startsWith('/') ? trimmed : `/${trimmed}`
    if (!targetPaths.includes(normalized)) setTargetPaths([...targetPaths, normalized])
    setPathInput('')
  }

  const buildPayload = () => ({
    name: name.trim(),
    code,
    placement,
    scope,
    targetPaths: scope === 'site' ? [] : targetPaths,
    priority,
    enabled,
    loadAsync,
    disableInPreview,
    consentCategory,
  })

  const validate = (): boolean => {
    if (!name.trim()) {
      toast.error('Name is required')
      return false
    }
    if (!code.trim()) {
      toast.error('Code snippet is required')
      return false
    }
    if (scope !== 'site' && targetPaths.length === 0) {
      toast.error('At least one target path is required for this scope')
      return false
    }
    return true
  }

  const handleSave = async () => {
    if (!validate()) return
    setSaving(true)
    const res = isNew
      ? await cmsApi<ScriptTag>('/script-tags', {
          method: 'POST',
          body: JSON.stringify(buildPayload()),
        })
      : await cmsApi<ScriptTag>(`/script-tags/${tag.id}`, {
          method: 'PUT',
          body: JSON.stringify(buildPayload()),
        })
    setSaving(false)
    if (res.error) {
      toast.error(res.error)
      return
    }
    toast.success(isNew ? 'Script created' : 'Script saved')
    onChanged(res.data?.id ?? tag?.id)
  }

  const handleDuplicate = async () => {
    if (!tag) return
    const res = await cmsApi<ScriptTag>('/script-tags', {
      method: 'POST',
      body: JSON.stringify({ ...buildPayload(), name: `${name.trim()} (Copy)`, enabled: false }),
    })
    if (res.error) {
      toast.error(res.error)
      return
    }
    toast.success('Script duplicated (created disabled)')
    onChanged(res.data?.id)
  }

  const handleDelete = async () => {
    if (!tag) return
    const res = await cmsApi(`/script-tags/${tag.id}`, { method: 'DELETE' })
    setConfirmDelete(false)
    if (res.error) {
      toast.error(res.error)
      return
    }
    toast.success('Script deleted')
    onChanged()
    onClose()
  }

  return (
    <>
      <InspectorPaneHeader onClose={onClose} closeLabel="Close script editor">
        <div className="flex items-center gap-2.5">
          <input
            type="text"
            value={name}
            onChange={(e) => setName(e.target.value)}
            placeholder="Script name…"
            aria-label="Script name"
            className="min-w-0 flex-1 rounded-[7px] border border-transparent bg-transparent px-1.5 py-1 text-[14px] font-semibold text-[var(--txt)] transition-colors duration-[var(--motion-fast)] hover:border-[var(--bdr)] focus:border-[var(--acc)] focus:outline-none"
          />
          <Toggle
            checked={enabled}
            onCheckedChange={setEnabled}
            variant="enabled"
            aria-label={enabled ? 'Deactivate script' : 'Activate script'}
          />
        </div>
        <div className="mt-1.5 flex flex-wrap items-center gap-1.5 px-1.5">
          <span
            className={`rounded-[5px] px-1.5 py-0.5 text-[10.5px] font-medium ${PLACEMENT_COLORS[placement] ?? 'border border-[var(--bdr)] bg-[var(--bg)] text-[var(--sub)]'}`}
          >
            {PLACEMENT_LABELS[placement] ?? placement}
          </span>
          <span
            className={`inline-flex items-center gap-[3px] rounded-[5px] px-1.5 py-0.5 text-[10.5px] font-medium ${(CONSENT_COLORS[consentCategory] ?? NO_CONSENT_COLORS).badge}`}
          >
            <span
              className={`inline-block h-[5px] w-[5px] rounded-full ${(CONSENT_COLORS[consentCategory] ?? NO_CONSENT_COLORS).dot}`}
              aria-hidden
            />
            {CONSENT_LABELS[consentCategory] ?? consentCategory}
          </span>
        </div>
      </InspectorPaneHeader>

      <InspectorPaneBody>
        <InspectorPaneSection title="Code" subtitle="HTML / JS">
          <textarea
            value={code}
            onChange={(e) => setCode(e.target.value)}
            placeholder="<!-- Paste your script here -->"
            rows={8}
            spellCheck={false}
            aria-label="Script code"
            className="w-full rounded-[7px] border border-[var(--bdr)] bg-[var(--card)] px-2.5 py-2 font-mono text-[11.5px] text-[var(--txt)] focus:border-[var(--acc)] focus:outline-none"
          />
          <p className="mt-1 text-[11px] text-[var(--muted)]">
            Fires on frontend only — never injected during CMS rendering.
          </p>
        </InspectorPaneSection>

        <InspectorPaneSection title="Injection Location">
          <div className="grid grid-cols-3 gap-1.5" role="group" aria-label="Injection location">
            {PLACEMENT_OPTIONS.map((opt) => (
              <OptionTile
                key={opt.value}
                active={placement === opt.value}
                onClick={() => setPlacement(opt.value)}
              >
                <span className="block">{opt.label}</span>
                <span className="block font-mono text-[10px] font-normal text-[var(--muted)]">
                  {opt.hint}
                </span>
              </OptionTile>
            ))}
          </div>
          <div className="mt-3 flex items-center justify-between gap-3">
            <div>
              <div className="text-[12.5px] font-medium text-[var(--txt)]">Load Priority</div>
              <div className="text-[11px] text-[var(--muted)]">Lower = fires first</div>
            </div>
            <div className="flex items-center gap-1">
              <button
                type="button"
                aria-label="Decrease priority"
                onClick={() => setPriority((p) => Math.max(0, p - 1))}
                className="flex h-[27px] w-[27px] items-center justify-center rounded-[6px] border border-[var(--bdr)] bg-[var(--card)] text-[var(--muted)] transition-colors duration-[var(--motion-fast)] hover:border-[var(--acc-m)] hover:text-[var(--acc)] focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none"
              >
                <Minus size={13} />
              </button>
              <input
                type="number"
                value={priority}
                min={0}
                onChange={(e) => setPriority(Math.max(0, parseInt(e.target.value, 10) || 0))}
                aria-label="Load priority"
                className="w-14 rounded-[6px] border border-[var(--bdr)] bg-[var(--card)] px-1.5 py-1 text-center font-mono text-[12px] text-[var(--txt)] focus:border-[var(--acc)] focus:outline-none"
              />
              <button
                type="button"
                aria-label="Increase priority"
                onClick={() => setPriority((p) => p + 1)}
                className="flex h-[27px] w-[27px] items-center justify-center rounded-[6px] border border-[var(--bdr)] bg-[var(--card)] text-[var(--muted)] transition-colors duration-[var(--motion-fast)] hover:border-[var(--acc-m)] hover:text-[var(--acc)] focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none"
              >
                <Plus size={13} />
              </button>
            </div>
          </div>
        </InspectorPaneSection>

        <InspectorPaneSection title="Firing Conditions">
          <div className="grid grid-cols-3 gap-1.5" role="group" aria-label="Scope">
            {SCOPE_OPTIONS.map((opt) => (
              <OptionTile
                key={opt.value}
                active={scope === opt.value}
                onClick={() => setScope(opt.value)}
              >
                {opt.label}
              </OptionTile>
            ))}
          </div>
          {scope !== 'site' && (
            <div className="mt-3">
              <label
                htmlFor="script-tag-path-input"
                className="mb-1 block text-[11.5px] font-medium text-[var(--sub)]"
              >
                {scope === 'parents' ? 'Parent paths (includes child pages)' : 'URL paths'}
              </label>
              <div className="flex gap-1.5">
                <input
                  id="script-tag-path-input"
                  type="text"
                  value={pathInput}
                  onChange={(e) => setPathInput(e.target.value)}
                  onKeyDown={(e) => {
                    if (e.key === 'Enter') {
                      e.preventDefault()
                      addPath()
                    }
                  }}
                  placeholder="/services"
                  className="min-w-0 flex-1 rounded-[7px] border border-[var(--bdr)] bg-[var(--card)] px-2.5 py-1.5 font-mono text-[12px] text-[var(--txt)] focus:border-[var(--acc)] focus:outline-none"
                />
                <button
                  type="button"
                  onClick={addPath}
                  aria-label="Add path"
                  className="flex h-[31px] w-[31px] shrink-0 items-center justify-center rounded-[7px] border border-[var(--bdr)] bg-[var(--card)] text-[var(--muted)] transition-colors duration-[var(--motion-fast)] hover:border-[var(--acc-m)] hover:text-[var(--acc)] focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none"
                >
                  <Plus size={14} />
                </button>
              </div>
              {targetPaths.length > 0 && (
                <div className="mt-2 flex flex-wrap gap-1.5">
                  {targetPaths.map((p) => (
                    <span
                      key={p}
                      className="inline-flex items-center gap-1 rounded-[var(--r-pill)] border border-[var(--bdr)] bg-[var(--bg)] px-2 py-0.5 font-mono text-[11px] text-[var(--sub)]"
                    >
                      {p}
                      <button
                        type="button"
                        onClick={() => setTargetPaths(targetPaths.filter((x) => x !== p))}
                        aria-label={`Remove ${p}`}
                        className="text-[var(--muted)] hover:text-[var(--err)]"
                      >
                        <X size={11} />
                      </button>
                    </span>
                  ))}
                </div>
              )}
            </div>
          )}
        </InspectorPaneSection>

        <InspectorPaneSection title="Cookie Consent" subtitle="GDPR / CCPA">
          <div className="mb-1.5 text-[12.5px] font-medium text-[var(--txt)]">
            Consent category required
          </div>
          <div className="grid grid-cols-3 gap-1.5" role="group" aria-label="Consent category">
            {CONSENT_OPTIONS.map((value) => (
              <OptionTile
                key={value}
                active={consentCategory === value}
                onClick={() => setConsentCategory(value)}
              >
                {CONSENT_LABELS[value]}
              </OptionTile>
            ))}
          </div>
          {consentCategory !== 'none' && (
            <p className="mt-2 text-[11px] text-[var(--muted)]">
              The script is injected only after the visitor grants the{' '}
              {CONSENT_LABELS[consentCategory] ?? consentCategory} consent category (Actuate Consent
              banner).
            </p>
          )}
        </InspectorPaneSection>

        <InspectorPaneSection title="Advanced">
          <ToggleRow
            label="Load async"
            hint="Non-blocking — doesn't delay page render"
            checked={loadAsync}
            onCheckedChange={setLoadAsync}
          />
          <ToggleRow
            label="Disable in preview mode"
            hint="Skip firing inside CMS page preview"
            checked={disableInPreview}
            onCheckedChange={setDisableInPreview}
          />
        </InspectorPaneSection>
      </InspectorPaneBody>

      <InspectorPaneFooter>
        <button
          type="button"
          onClick={() => void handleSave()}
          disabled={saving}
          className="bg-primary text-primary-foreground w-full rounded-[7px] px-3 py-2 text-[13px] font-semibold transition-colors duration-[var(--motion-fast)] hover:opacity-90 focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50"
        >
          {saving ? 'Saving…' : 'Save Script'}
        </button>
        {!isNew && (
          <div className="mt-2 flex items-center justify-center gap-4">
            <button
              type="button"
              onClick={() => void handleDuplicate()}
              className="inline-flex items-center gap-1.5 text-[12px] text-[var(--sub)] transition-colors duration-[var(--motion-fast)] hover:text-[var(--acc)] focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none"
            >
              <Copy size={12} />
              Duplicate
            </button>
            <button
              type="button"
              onClick={() => setConfirmDelete(true)}
              className="inline-flex items-center gap-1.5 text-[12px] text-[var(--sub)] transition-colors duration-[var(--motion-fast)] hover:text-[var(--err)] focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none"
            >
              <Trash2 size={12} />
              Delete
            </button>
          </div>
        )}
      </InspectorPaneFooter>

      <ConfirmDialog
        open={confirmDelete}
        title="Delete script?"
        description={`"${name || 'This script'}" will stop firing on your site immediately.`}
        confirmLabel="Delete"
        destructive
        onConfirm={() => void handleDelete()}
        onClose={() => setConfirmDelete(false)}
      />
    </>
  )
}
