import React, { useRef, useState } from "react";
import { DashboardTemplatePage } from "@/components/DashboardTemplatePage";

type FormState = {
  id: string;
  name: string;
  tags: string;
};

export default function AdminUploadLogoTemplate() {
  const [svgFile, setSvgFile] = useState<File | null>(null);
  const [previewFile, setPreviewFile] = useState<File | null>(null);

  const [svgContent, setSvgContent] = useState<string>("");
  const [previewImageUrl, setPreviewImageUrl] = useState<string>("");

  const [msg, setMsg] = useState<string>("");
  const [busy, setBusy] = useState(false);
  const [previewTitle, setPreviewTitle] = useState<string>("Logo Template");

  const [form, setForm] = useState<FormState>({
    id: "",
    name: "",
    tags: "modern, emblem",
  });

  const svgInputRef = useRef<HTMLInputElement>(null);
  const previewInputRef = useRef<HTMLInputElement>(null);

  // ---------- Utilities ----------
  const readText = (file: File) =>
    new Promise<string>((resolve, reject) => {
      const reader = new FileReader();
      reader.onerror = () => reject(new Error("Failed to read file"));
      reader.onload = () => resolve(String(reader.result || ""));
      reader.readAsText(file);
    });

  const readAsDataUrl = (file: File) =>
    new Promise<string>((resolve, reject) => {
      const reader = new FileReader();
      reader.onerror = () => reject(new Error("Failed to read file"));
      reader.onload = () => resolve(String(reader.result || ""));
      reader.readAsDataURL(file);
    });

  // Drop handling (works for both zones)
  const handleDrop = async (
    e: React.DragEvent<HTMLDivElement>,
    kind: "svg" | "preview"
  ) => {
    e.preventDefault();
    const f = e.dataTransfer.files?.[0];
    if (!f) return;
    setMsg("");

    if (kind === "svg") {
      if (f.type && f.type !== "image/svg+xml" && !f.name.toLowerCase().endsWith(".svg")) {
        return setMsg("SVG drop rejected: not an SVG file.");
      }
      await loadSvgForPreview(f);
      setSvgFile(f);
      if (!form.name) setPreviewTitle(f.name.replace(/\.[^.]+$/, "") || "Logo Template");
    } else {
      if (
        f.type &&
        !/^image\/(png|jpeg|jpg)$/i.test(f.type) &&
        !/\.(png|jpe?g)$/i.test(f.name)
      ) {
        return setMsg("Preview must be PNG or JPG.");
      }
      await loadPreviewImage(f);
      setPreviewFile(f);
      if (!form.name && !svgFile)
        setPreviewTitle(f.name.replace(/\.[^.]+$/, "") || "Logo Template");
    }
  };

  // ---------- SVG Preview Pipeline ----------
  const sanitizeSvg = (raw: string) => {
    // strip <script> blocks
    let out = raw.replace(/<script[\s\S]*?>[\s\S]*?<\/script>/gi, "");
    // strip inline on* handlers (onload, onclick, etc.)
    out = out.replace(/\son[a-z]+\s*=\s*(['"]).*?\1/gi, "");
    return out;
  };

  const injectTokensAndVars = (raw: string) => {
    const parser = new DOMParser();
    const doc = parser.parseFromString(raw, "image/svg+xml");
    const svg = doc.documentElement;

    // Replace tokens across text nodes by stringifying, then reparse to keep it simple
    let text = new XMLSerializer().serializeToString(doc);
    text = text.replace(/\{Brand_Name\}/g, "Sample Brand");
    text = text.replace(/\{Tagline\}/g, "Sample Tagline");
    text = text.replace(/\{Est_Year\}/g, "2025");

    const doc2 = parser.parseFromString(text, "image/svg+xml");
    const svg2 = doc2.documentElement;

    // Merge CSS vars onto style attribute
    const existingStyle = svg2.getAttribute("style") || "";
    const vars =
      "--primary:#231f20;--secondary:#978752;--accent:#6dc282;";
    const merged =
      existingStyle.trim().length > 0
        ? existingStyle.trim().replace(/;?$/, ";") + vars
        : vars;
    svg2.setAttribute("style", merged);

    // Ensure preserveAspectRatio / viewBox behave in constrained container
    if (!svg2.getAttribute("width")) svg2.setAttribute("width", "100%");
    if (!svg2.getAttribute("height")) svg2.setAttribute("height", "100%");

    // Serialize back to string
    return new XMLSerializer().serializeToString(doc2);
  };

  const loadSvgForPreview = async (file: File) => {
    try {
      const raw = await readText(file);
      if (!/^\s*<svg[\s\S]*<\/svg>\s*$/i.test(raw)) {
        setSvgContent("");
        setMsg("SVG preview failed: not a valid <svg>…</svg> document.");
        return;
      }
      const clean = sanitizeSvg(raw);
      const finalSvg = injectTokensAndVars(clean);
      setSvgContent(finalSvg);
    } catch (err) {
      console.error(err);
      setSvgContent("");
      setMsg("Failed to load SVG preview.");
    }
  };

  // ---------- Image Preview ----------
  const loadPreviewImage = async (file: File) => {
    try {
      const url = await readAsDataUrl(file);
      setPreviewImageUrl(url);
    } catch (err) {
      console.error(err);
      setPreviewImageUrl("");
      setMsg("Failed to load image preview.");
    }
  };

  // ---------- Effects: react to file changes from file inputs ----------
  React.useEffect(() => {
    if (!svgFile) {
      setSvgContent("");
      return;
    }
    loadSvgForPreview(svgFile);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [svgFile]);

  React.useEffect(() => {
    if (!previewFile) {
      setPreviewImageUrl("");
      return;
    }
    loadPreviewImage(previewFile);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [previewFile]);

  // ---------- Validation ----------
  const validateSVG = async (file: File) => {
    if (!file) return "Please provide an SVG file.";
    if (file.type && file.type !== "image/svg+xml" && !file.name.toLowerCase().endsWith(".svg"))
      return "File is not an SVG.";
    const text = await readText(file);
    const issues: string[] = [];
    if (!/^\s*<svg[\s\S]*<\/svg>\s*$/i.test(text))
      issues.push("Not a valid <svg>…</svg> document.");
    ["{Brand_Name}", "{Tagline}", "{Est_Year}"].forEach((tok) => {
      if (!text.includes(tok)) issues.push(`Missing token ${tok}`);
    });
    ["--primary", "--secondary", "--accent"].forEach((v) => {
      if (!text.includes(v)) issues.push(`Missing CSS var ${v}`);
    });
    return issues.length ? issues.join(" ") : null;
  };

  // ---------- Submit ----------
  const onSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setMsg("");
    if (!form.id || !form.name) return setMsg("ID and Name are required.");
    if (!svgFile || !previewFile)
      return setMsg("SVG and Preview files are required.");
    const svgErr = await validateSVG(svgFile);
    if (svgErr) return setMsg("SVG validation failed: " + svgErr);

    try {
      setBusy(true);
      const fd = new FormData();
      fd.append("id", form.id);
      fd.append("name", form.name);
      fd.append("tags", form.tags);
      fd.append("svg", svgFile);
      fd.append("preview", previewFile);

      const res = await fetch("/api/logo-templates/upload", {
        method: "POST",
        body: fd,
      });
      const json = await res.json().catch(() => ({}));
      if (!res.ok) throw new Error(json?.error || `HTTP ${res.status}`);
      setMsg("Uploaded and manifest updated ✅");
    } catch (e: any) {
      setMsg("Upload failed: " + (e?.message || "Unknown error"));
    } finally {
      setBusy(false);
    }
  };

  return (
    <DashboardTemplatePage title="Upload Logo Template">
      <form className="grid md:grid-cols-2 gap-6" onSubmit={onSubmit}>
        {/* Left Side - Preview */}
        <section className="space-y-4">
          <div className="bg-white rounded-xl border border-gray-200 p-6">
            <div className="mb-2 text-lg font-semibold text-gray-900">
              {previewTitle}
            </div>
            <div className="mb-4 text-sm font-medium text-gray-700">Preview</div>

            <div
              className="w-full bg-gray-50 rounded-lg border flex items-center justify-center"
              style={{ minHeight: 300, maxHeight: 400 }}
              data-testid="logo-preview"
            >
              {svgContent ? (
                <div
                  dangerouslySetInnerHTML={{ __html: svgContent }}
                  style={{ maxWidth: "100%", maxHeight: "350px" }}
                />
              ) : previewImageUrl ? (
                <img
                  src={previewImageUrl}
                  alt="Logo Preview"
                  style={{
                    maxWidth: "100%",
                    maxHeight: "350px",
                    objectFit: "contain",
                  }}
                />
              ) : (
                <div className="text-gray-400 text-center">
                  <div className="text-lg mb-2">Logo Preview</div>
                  <div className="text-sm">
                    Upload an SVG or Preview file to see the preview
                  </div>
                </div>
              )}
            </div>

            <div className="text-xs text-gray-500 mt-3">
              {svgContent
                ? 'SVG Preview with sample values: "Sample Brand", "Sample Tagline", "2025"'
                : previewImageUrl
                ? "Image Preview from uploaded PNG/JPG file"
                : "Preview will show here after uploading an SVG or Preview file"}
            </div>
          </div>
        </section>

        {/* Right Side - Form and Uploads */}
        <section className="space-y-4">
          <FileDrop
            label="SVG Master"
            accept=".svg,image/svg+xml"
            file={svgFile}
            onRemove={() => {
              setSvgFile(null);
              setSvgContent("");
            }}
            onChoose={() => svgInputRef.current?.click()}
            onDrop={(e) => handleDrop(e, "svg")}
          />

          <input
            ref={svgInputRef}
            type="file"
            accept=".svg,image/svg+xml"
            className="hidden"
            onChange={async (e) => {
              const f = e.target.files?.[0] || null;
              setMsg("");
              setSvgFile(f);
              if (f) {
                await loadSvgForPreview(f);
                if (!form.name) setPreviewTitle(f.name.replace(/\.[^.]+$/, ""));
              } else {
                setSvgContent("");
              }
            }}
            data-testid="input-svg-file"
          />

          <FileDrop
            label="Preview (PNG/JPG)"
            accept=".png,.jpg,.jpeg,image/png,image/jpeg"
            file={previewFile}
            onRemove={() => {
              setPreviewFile(null);
              setPreviewImageUrl("");
            }}
            onChoose={() => previewInputRef.current?.click()}
            onDrop={(e) => handleDrop(e, "preview")}
          />

          <input
            ref={previewInputRef}
            type="file"
            accept=".png,.jpg,.jpeg,image/png,image/jpeg"
            className="hidden"
            onChange={async (e) => {
              const f = e.target.files?.[0] || null;
              setMsg("");
              setPreviewFile(f);
              if (f) {
                await loadPreviewImage(f);
                if (!form.name && !svgFile)
                  setPreviewTitle(f.name.replace(/\.[^.]+$/, ""));
              } else {
                setPreviewImageUrl("");
              }
            }}
            data-testid="input-preview-file"
          />

          <Field label="Template ID" hint="kebab-case, e.g. logo-emblem-law-v1">
            <input
              className="rounded-lg border px-3 py-2 w-full"
              value={form.id}
              onChange={(e) => setForm((s) => ({ ...s, id: e.target.value }))}
              data-testid="input-template-id"
            />
          </Field>

          <Field label="Logo Name">
            <input
              className="rounded-lg border px-3 py-2 w-full"
              value={form.name}
              onChange={(e) => setForm((s) => ({ ...s, name: e.target.value }))}
              data-testid="input-template-name"
            />
            <button
              type="button"
              className="mt-2 rounded-lg px-3 py-1 text-sm text-white hover:opacity-90"
              style={{ backgroundColor: "#00C851" }}
              onClick={() => {
                setPreviewTitle(form.name || "Logo Template");
              }}
              data-testid="button-add-logo-name"
            >
              Add
            </button>
          </Field>

          <Field label="Tags (comma-separated)">
            <input
              className="rounded-lg border px-3 py-2 w-full"
              value={form.tags}
              onChange={(e) => setForm((s) => ({ ...s, tags: e.target.value }))}
              data-testid="input-tags"
            />
          </Field>

          <div className="pt-2">
            <button
              className="rounded-xl px-4 py-2 border hover:bg-gray-50"
              disabled={busy}
              type="submit"
              data-testid="button-upload-template"
            >
              {busy ? "Uploading…" : "Upload & Update Manifest"}
            </button>
          </div>

          {msg && (
            <p className="text-sm text-gray-600" data-testid="text-upload-message">
              {msg}
            </p>
          )}

          <p className="text-xs text-gray-500">
            SVG must contain tokens <code>{`{Brand_Name}`}</code>,{" "}
            <code>{`{Tagline}`}</code>, <code>{`{Est_Year}`}</code> and CSS vars{" "}
            <code>--primary</code>, <code>--secondary</code>, <code>--accent</code>.
          </p>
        </section>
      </form>
    </DashboardTemplatePage>
  );
}

// ---------- UI Fragments ----------
function Field({
  label,
  hint,
  children,
}: {
  label: string;
  hint?: string;
  children: React.ReactNode;
}) {
  return (
    <div className="grid gap-1">
      <label className="text-xs text-gray-600">{label}</label>
      {children}
      {hint && <div className="text-[11px] text-gray-400">{hint}</div>}
    </div>
  );
}

function FileDrop({
  label,
  accept,
  file,
  onRemove,
  onChoose,
  onDrop,
}: {
  label: string;
  accept: string;
  file: File | null;
  onRemove: () => void;
  onChoose: () => void;
  onDrop: (e: React.DragEvent<HTMLDivElement>) => void;
}) {
  const idSafe = label.toLowerCase().replace(/[^a-z0-9]/g, "-");
  return (
    <div>
      <label className="text-xs text-gray-600">{label}</label>
      <div
        onDragOver={(e) => e.preventDefault()}
        onDrop={onDrop}
        onClick={onChoose} // make the whole area clickable
        className="mt-1 rounded-xl border-dashed border-2 p-4 text-sm text-gray-600 flex items-center justify-between gap-3 cursor-pointer"
        data-testid={`drop-zone-${idSafe}`}
        title="Click to choose a file or drag & drop"
      >
        <div className="flex-1">
          {file ? (
            <span className="font-medium">{file.name}</span>
          ) : (
            <>Drag & drop, or click to select</>
          )}
          <div className="text-[11px] text-gray-400">Accepted: {accept}</div>
        </div>
        <div className="flex items-center gap-2">
          <button
            type="button"
            className="rounded-lg px-3 py-1 border"
            onClick={(e) => {
              e.stopPropagation();
              onChoose();
            }}
            data-testid={`button-choose-${idSafe}`}
          >
            Choose
          </button>
          {file && (
            <button
              type="button"
              className="rounded-lg px-3 py-1 border"
              onClick={(e) => {
                e.stopPropagation();
                onRemove();
              }}
              data-testid={`button-remove-${idSafe}`}
            >
              Remove
            </button>
          )}
        </div>
      </div>
    </div>
  );
}
