'use client'

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

/**
 * ScriptManager — active consent-aware script blocking + injection.
 *
 * Two mechanisms:
 * 1. INJECTION: Scripts in CONSENT_SCRIPTS are only injected AFTER consent.
 * 2. BLOCKING: Existing <script data-consent="category" type="text/plain">
 *    elements in the page are activated after consent by changing type to
 *    "text/javascript". This is the standard CMP blocking pattern.
 *
 * Usage for inline scripts in pages:
 *   <script type="text/plain" data-consent="analytics">
 *     // This won't execute until analytics consent is given
 *     gtag('config', 'G-XXXXXX');
 *   </script>
 *
 * Usage for adding new third-party scripts:
 *   Add to CONSENT_SCRIPTS below. They'll be injected only after consent.
 */

interface ConsentScript {
  src: string
  async?: boolean
  id?: string
}

const CONSENT_SCRIPTS: Record<string, ConsentScript[]> = {
  analytics: [
    // { src: 'https://www.googletagmanager.com/gtag/js?id=G-XXXXXX', async: true, id: 'gtag' },
    // { src: 'https://plausible.io/js/script.js', async: true, id: 'plausible' },
  ],
  marketing: [
    // { src: 'https://connect.facebook.net/en_US/fbevents.js', async: true, id: 'fb-pixel' },
    // { src: 'https://snap.licdn.com/li.lms-analytics/insight.min.js', async: true, id: 'li-insight' },
  ],
  functional: [
    // { src: 'https://widget.example.com/chat.js', async: true, id: 'chat-widget' },
  ],
}

interface ConsentState {
  essential: boolean
  functional: boolean
  analytics: boolean
}

function getStoredConsent(): ConsentState | null {
  if (typeof window === 'undefined') return null
  try {
    const raw = localStorage.getItem('bp_consent')
    return raw ? JSON.parse(raw) : null
  } catch { return null }
}

export default function ScriptManager() {
  const injected = useRef(new Set<string>())

  const applyConsent = useCallback((consent: ConsentState) => {
    const accepted = new Set<string>()
    accepted.add('essential') // always allowed
    if (consent.functional) accepted.add('functional')
    if (consent.analytics) accepted.add('analytics')

    // 1. INJECT: Add scripts from CONSENT_SCRIPTS for accepted categories
    for (const cat of accepted) {
      for (const script of CONSENT_SCRIPTS[cat] ?? []) {
        if (injected.current.has(script.src)) continue
        const el = document.createElement('script')
        el.src = script.src
        if (script.async) el.async = true
        if (script.id) el.id = script.id
        el.dataset.consent = cat
        document.head.appendChild(el)
        injected.current.add(script.src)
      }
    }

    // 2. ACTIVATE: Unblock <script type="text/plain" data-consent="...">
    const blocked = document.querySelectorAll('script[type="text/plain"][data-consent]')
    for (const el of blocked) {
      const cat = el.getAttribute('data-consent') || ''
      if (accepted.has(cat)) {
        const clone = document.createElement('script')
        // Copy attributes
        for (const attr of el.attributes) {
          if (attr.name === 'type') continue // skip type="text/plain"
          clone.setAttribute(attr.name, attr.value)
        }
        clone.type = 'text/javascript'
        clone.textContent = el.textContent
        el.parentNode?.replaceChild(clone, el)
      }
    }
  }, [])

  useEffect(() => {
    // On mount: apply saved consent (return visitors)
    const saved = getStoredConsent()
    if (saved) applyConsent(saved)

    // Listen for new consent decisions
    function onConsentChange(e: Event) {
      const detail = (e as CustomEvent<ConsentState>).detail
      if (detail) applyConsent(detail)
    }

    window.addEventListener('consent-change', onConsentChange)
    return () => window.removeEventListener('consent-change', onConsentChange)
  }, [applyConsent])

  return null
}
