"use client"

import React from "react"

type DynamicSvgProps = {
  svg?: string | null
  // If provided, component will fetch the SVG string from this URL
  src?: string
  // Width/height can be CSS lengths or numbers (treated as px)
  width?: number | string
  height?: number | string
  className?: string
  // Optional role/title for accessibility
  role?: string
  title?: string
  // If true, preserves viewBox scaling inside a wrapper
  preserveAspectRatio?: boolean
}

function normalizeSize(value?: number | string): string | undefined {
  if (value === undefined) return undefined
  return typeof value === "number" ? `${value}px` : value
}

// Minimal sanitizer: strips script/style tags and event handlers
function sanitizeSvg(svg: string): string {
  const withoutScripts = svg.replace(/<script[\s\S]*?>[\s\S]*?<\/script>/gi, "")
  const withoutStyles = withoutScripts.replace(/<style[\s\S]*?>[\s\S]*?<\/style>/gi, "")
  // Remove on* attributes (onload, onclick, etc.)
  const withoutEvents = withoutStyles.replace(/\son[a-z]+\s*=\s*"[^"]*"/gi, "")
  // Remove javascript: URLs
  const withoutJsUrls = withoutEvents.replace(/(href|xlink:href|src)\s*=\s*"javascript:[^"]*"/gi, "$1=\"\"")
  return withoutJsUrls
}

export function DynamicSvg({
  svg,
  src,
  width,
  height,
  className,
  role = "img",
  title,
  preserveAspectRatio = true,
}: DynamicSvgProps) {
  const [content, setContent] = React.useState<string | null>(svg ?? null)
  const [error, setError] = React.useState<string | null>(null)
  const w = normalizeSize(width)
  const h = normalizeSize(height)

  React.useEffect(() => {
    setContent(svg ?? null)
  }, [svg])

  React.useEffect(() => {
    if (!src) return
    let isCancelled = false
    ;(async () => {
      try {
        setError(null)
        const res = await fetch(src, { credentials: "include" })
        const text = await res.text()
        if (isCancelled) return
        // Try to pull out raw SVG if server wraps it in JSON
        let raw = text
        if (!text.trim().startsWith("<svg")) {
          try {
            const json = JSON.parse(text)
            raw = (json?.svg || json?.data?.svg || "").toString()
          } catch {
            // fallback to original text
          }
        }
        if (!raw || !raw.includes("<svg")) {
          throw new Error("No SVG content in response")
        }
        setContent(raw)
      } catch (e) {
        if (isCancelled) return
        setError(e instanceof Error ? e.message : "Failed to load SVG")
      }
    })()
    return () => {
      isCancelled = true
    }
  }, [src])

  if (error) {
    return <div className={className} role="img" aria-label={title || "SVG error"}>Failed to render SVG: {error}</div>
  }

  if (!content) {
    return <div className={className} role="img" aria-label={title || "Loading SVG"} />
  }

  const sanitized = sanitizeSvg(content)

  // Wrap raw SVG in a container to control layout dimensions
  const style: React.CSSProperties = {
    width: w,
    height: h,
    display: "inline-block",
  }

  // When preserving aspect ratio, let inner SVG own its viewBox sizing
  // Otherwise, we force width/height via a wrapper CSS
  return (
    <div className={className} style={style} role={role} aria-label={title} title={title}>
      <div
        style={{ width: "100%", height: "100%" }}
        dangerouslySetInnerHTML={{
          __html: preserveAspectRatio
            ? sanitized
            : sanitized.replace(
                /<svg(\s[^>]*)?>/i,
                (match) =>
                  match.includes("width=") || match.includes("height=")
                    ? match
                    : match.replace(
                        /<svg/i,
                        '<svg width="100%" height="100%"'
                      )
              ),
        }}
      />
    </div>
  )
}

export default DynamicSvg


