import React from "react";
import { sanitizeHtml } from "@/shared/lib/sanitize";
import {
  TemplateSampleData,
  TemplateSampleSetting,
} from "@/user-management/services/TemplateConfiguration/types/templateTypes";
import { normalizeLetterLabelsValue } from "./utils/letterLabelsConstants";
import { normalizePageMarginValue } from "./components/PageMarginEditor";

interface TemplateLivePreviewProps {
  formData: TemplateSampleData;
  settings: TemplateSampleSetting[];
  selectedHeader: string; // HTML string with <img>
  selectedFooter: string; // HTML string with <img>
  templateName?: string;
}

export const TemplateLivePreview: React.FC<TemplateLivePreviewProps> = ({
  formData,
  settings,
  selectedHeader,
  selectedFooter,
  templateName,
}) => {
  const { content, preferredLanguage, recordType } = formData;

  // Debug: Log when component renders and show render count
  const renderCount = React.useRef(0);
  renderCount.current += 1;

  // CSS parser that correctly handles data URIs (colons/semicolons inside url(...))
  const parseCSSString = (cssString: string): React.CSSProperties => {
    if (!cssString) return {};

    const styles: React.CSSProperties = {};
    // Walk char-by-char, splitting on ';' only when outside parentheses
    let depth = 0;
    let current = "";

    const processDeclaration = (decl: string) => {
      decl = decl.trim();
      if (!decl) return;
      // Split on first ':' only
      const colonIdx = decl.indexOf(":");
      if (colonIdx <= 0) return;
      const property = decl.slice(0, colonIdx).trim();
      const value = decl.slice(colonIdx + 1).trim();
      if (!property || !value) return;
      // Convert CSS property names to camelCase for React
      const camelCaseProperty = property
        .split("-")
        .map((part, index) =>
          index === 0 ? part : part.charAt(0).toUpperCase() + part.slice(1),
        )
        .join("");
      (styles as any)[camelCaseProperty] = value;
    };

    for (let i = 0; i < cssString.length; i++) {
      const ch = cssString[i];
      if (ch === "(") depth++;
      else if (ch === ")") depth--;
      if (ch === ";" && depth === 0) {
        processDeclaration(current);
        current = "";
      } else {
        current += ch;
      }
    }
    processDeclaration(current); // last declaration (no trailing semicolon)

    return styles;
  };

  // Helper to extract style object from settings by code
  const getStyleFor = (code: string): React.CSSProperties => {
    const setting = settings.find((s) => s.code.includes(code));
    if (!setting) return {};

    const { value } = setting;

    // If value is a string (CSS), parse it
    if (typeof value === "string") {
      return parseCSSString(value);
    }

    // Fallback for object format
    return {
      fontSize: (value as any)["font-size"],
      fontWeight: (value as any)["font-weight"] as any,
      textDecoration: (value as any)["text-decoration"] as any,
    };
  };

  const getStyleForAliases = (aliases: string[]): React.CSSProperties => {
    const normalized = aliases.map((alias) => alias.toLowerCase());
    const setting = settings.find((s) => {
      const code = s.code.toLowerCase();
      return normalized.some((alias) => code.includes(alias));
    });
    if (!setting) return {};

    const { value } = setting;
    if (typeof value === "string") {
      return parseCSSString(value);
    }

    return parseCSSString(
      Object.entries(value as Record<string, string>)
        .map(([key, val]) => `${key}: ${val};`)
        .join(" "),
    );
  };

  const subjectStyle = getStyleFor("subject");
  const bodyStyle = getStyleFor("body");
  const headerStyle = getStyleFor("header");
  const footerStyle = getStyleFor("footer");

  const receiverStyle = getStyleForAliases([
    "receiver",
    "recipient",
    "letter-receiver",
    "to",
  ]);
  const fromStyle = getStyleForAliases([
    "collaborator",
    "from",
    "letter-from",
    "sender",
  ]);
  const prefixStyle = getStyleForAliases([
    "letter-prefix-style",
    "prefix-style",
    "letter-prefix",
    "prefix",
  ]);
  const suffixStyle = getStyleForAliases([
    "letter-suffix-style",
    "suffix-style",
    "letter-suffix",
    "suffix",
  ]);
  const ccInternalStyle = getStyleForAliases([
    "cc-internal",
    "ccinternal",
    "internal-cc",
    "internalcc",
    "cc-receiver",
  ]);
  const ccExternalStyle = getStyleForAliases([
    "cc-external",
    "ccexternal",
    "external-cc",
    "externalcc",
    "cc-receiver",
  ]);
  const ccPrefixStyle = getStyleForAliases(["cc-prefix"]);
  const ccSuffixStyle = getStyleForAliases(["cc-suffix"]);

  // Customizable bilingual labels & page margins
  const labels = normalizeLetterLabelsValue(
    settings.find((s) => s.code === "letter-labels-text")?.value,
  );
  const margins = normalizePageMarginValue(
    settings.find((s) => s.code === "letter-page-margin")?.value,
  );
  const displayLang: "en" | "am" = preferredLanguage === "am" ? "am" : "en";
  const labelStyle = (
    style?: Record<string, string>,
  ): React.CSSProperties =>
    style
      ? parseCSSString(
          Object.entries(style)
            .map(([k, v]) => `${k}: ${v};`)
            .join(" "),
        )
      : {};

  const renderBodyContent = () => {
    const bodyText = content.body || "";
    const lines = bodyText
      .split("\n")
      .map((line) => line.trim())
      .filter(Boolean);
    const bulletItems = lines
      .filter((line) => /^[-*•]\s+/.test(line))
      .map((line) => line.replace(/^[-*•]\s+/, ""));

    // Split list-specific style from text style so bullets can render on real <ul>/<li>.
    const { listStyle, listStyleType, listStyleImage, ...textStyle } =
      bodyStyle as Record<string, unknown>;
    const resolvedListStyle =
      (listStyle as string) || (listStyleType as string) || "disc";
    const resolvedListStyleImage =
      typeof listStyleImage === "string" ? listStyleImage : undefined;

    if (bulletItems.length > 0) {
      const isDisclosureTriangle =
        resolvedListStyle === "disclosure-closed" ||
        resolvedListStyle === "disclosure-open";

      if (
        resolvedListStyleImage &&
        !isDisclosureTriangle
      ) {
        return (
          <div style={textStyle as React.CSSProperties}>
            <ul
              style={{
                listStyle: "none",
                listStyleImage: resolvedListStyleImage,
                listStylePosition: "outside",
                paddingLeft: "1.5rem",
              }}
            >
              {bulletItems.map((item, idx) => (
                <li key={`${item}-${idx}`}>{item}</li>
              ))}
            </ul>
          </div>
        );
      }

      if (isDisclosureTriangle) {
        // Use inline styles with triangle for disclosure
        // Using Unicode escape sequence \25B6 for better backend compatibility
        return (
          <div style={textStyle}>
            <ul style={{ listStyle: "none", paddingLeft: 0 }}>
              {bulletItems.map((item, idx) => (
                <li
                  key={`${item}-${idx}`}
                  style={{
                    position: "relative",
                    paddingLeft: "1.2rem",
                  }}
                >
                  <span style={{ position: "absolute", left: 0 }}>
                    {String.fromCharCode(0x25b6)}
                  </span>
                  {item}
                </li>
              ))}
            </ul>
          </div>
        );
      }

      // Regular list-style rendering
      return (
        <div style={textStyle}>
          <ul
            style={{ listStyleType: resolvedListStyle, paddingLeft: "1.5rem" }}
          >
            {bulletItems.map((item, idx) => (
              <li key={`${item}-${idx}`}>{item}</li>
            ))}
          </ul>
        </div>
      );
    }

    return (
      <div style={textStyle}>
        {bodyText || "(Letter body will appear here)"}
      </div>
    );
  };

  // Helper to display a list of names based on preferred language
  const toList = content.to?.filter(Boolean) || [];
  const fromList = content.from?.filter(Boolean) || [];
  const internalCcList = content.internalCC?.filter(Boolean) || [];
  const externalCcList = content.externalCC?.filter(Boolean) || [];

  const renderStyledList = (
    items: string[],
    style: React.CSSProperties,
    emptyText: string,
  ) => {
    const { listStyle, listStyleType, listStylePosition, listStyleImage, ...textStyle } =
      style as Record<string, unknown>;
    const specialListStyles = ["disclosure-closed", "disclosure-open"];
    const resolvedListStyle =
      typeof listStyle === "string" && specialListStyles.includes(listStyle)
        ? listStyle
        : (listStyleType as string) || (listStyle as string) || "disc";
    const resolvedListPosition = ((listStylePosition as string) ||
      "outside") as React.CSSProperties["listStylePosition"];
    const resolvedListStyleImage =
      typeof listStyleImage === "string" ? listStyleImage : undefined;

    if (items.length === 0) {
      return <span>{emptyText}</span>;
    }

    if (
      resolvedListStyleImage &&
      resolvedListStyle !== "disclosure-closed" &&
      resolvedListStyle !== "disclosure-open"
    ) {
      return (
        <ul
          style={{
            listStyle: "none",
            listStyleImage: resolvedListStyleImage,
            listStylePosition: resolvedListPosition,
            paddingLeft: "1.5rem",
            margin: 0,
          }}
        >
          {items.map((item, idx) => (
            <li key={`${item}-${idx}`} style={textStyle as React.CSSProperties}>
              {item}
            </li>
          ))}
        </ul>
      );
    }

    // Check if using disclosure triangle
    const isDisclosureTriangle =
      resolvedListStyle === "disclosure-closed" ||
      resolvedListStyle === "disclosure-open";

    if (isDisclosureTriangle) {
      // Use inline styles with triangle for disclosure
      // Using Unicode escape sequence \25B6 for better backend compatibility
      return (
        <ul
          style={{
            listStyle: "none",
            paddingLeft: 0,
            margin: 0,
          }}
        >
          {items.map((item, idx) => (
            <li
              key={`${item}-${idx}`}
              style={{
                position: "relative",
                paddingLeft: "1.2rem",
                ...textStyle,
              }}
            >
              <span
                style={{
                  content: '"\\25B6"',
                  position: "absolute",
                  left: 0,
                  display: "inline-block",
                  width: "1rem",
                }}
              >
                {String.fromCharCode(0x25b6)}
              </span>
              {item}
            </li>
          ))}
        </ul>
      );
    }

    // Regular list-style rendering
    return (
      <ul
        style={{
          listStyleType: resolvedListStyle,
          listStylePosition: resolvedListPosition,
          paddingLeft: "1.5rem",
          margin: 0,
        }}
      >
        {items.map((item, idx) => (
          <li key={`${item}-${idx}`} style={textStyle}>
            {item}
          </li>
        ))}
      </ul>
    );
  };

  return (
    <div
      className="bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 shadow-sm font-serif text-gray-900 dark:text-gray-100 min-h-96"
      style={{
        paddingTop: `${margins.top}px`,
        paddingRight: `${margins.right}px`,
        paddingBottom: `${margins.bottom}px`,
        paddingLeft: `${margins.left}px`,
      }}
    >
      {/* Header with its own style */}
      {selectedHeader && (
        <div
          className="mb-6 border-b border-gray-200 dark:border-gray-600 pb-4"
          style={headerStyle}
          dangerouslySetInnerHTML={{ __html: sanitizeHtml(selectedHeader) }}
        />
      )}

      {/* Subject */}
      <div className="mb-4 text-lg font-semibold" style={subjectStyle}>
        <span style={labelStyle(labels.subject.style)}>
          {labels.subject[displayLang]}
        </span>{" "}
        {content.subject || "(Subject)"}
      </div>

      {/* Date (right aligned) */}
      <div className="text-right text-gray-600 dark:text-gray-400 mb-4 text-sm">
        <span style={labelStyle(labels.date.style)}>
          {labels.date[displayLang]}:
        </span>{" "}
        {content.date || new Date().toISOString().split("T")[0]}
      </div>

      {/* To: */}
      <div className="mb-2 text-sm">
        <span
          className="font-semibold text-gray-900 dark:text-white"
          style={labelStyle(labels.to.style)}
        >
          {labels.to[displayLang]}:
        </span>{" "}
        {renderStyledList(toList, receiverStyle, "(recipients)")}
      </div>

      {/* From: */}
      <div className="mb-4 text-sm" style={fromStyle}>
        <span
          className="font-semibold text-gray-900 dark:text-white"
          style={labelStyle(labels.from.style)}
        >
          {labels.from[displayLang]}:
        </span>{" "}
        {fromList.length > 0 ? fromList.join(", ") : "(collaborators)"}
      </div>

      {/* Body */}
      <div className="mb-4 whitespace-pre-wrap text-sm leading-relaxed text-gray-700 dark:text-gray-300">
        {renderBodyContent()}
      </div>

      {/* Sincerely / Closing */}
      <div className="mb-2 text-sm">{content.sincerelyText || "Sincerely"}</div>

      {/* Delegate signature */}
      {content.isWithDelegateSignature && content.delegatorName && (
        <div className="mb-2 text-gray-700 dark:text-gray-300 italic text-sm">
          <span style={labelStyle(labels.delegate.style)}>
            {labels.delegate[displayLang]}
          </span>{" "}
          {content.delegatorName}
        </div>
      )}

      {/* Prefix / Suffix */}
      {(content.prefix || content.suffix) && (
        <div className="mb-2 text-xs text-gray-600 dark:text-gray-400">
          {content.prefix && <span style={prefixStyle}>{content.prefix}</span>}
          {content.prefix && content.suffix && " "}
          {content.suffix && <span style={suffixStyle}>{content.suffix}</span>}
        </div>
      )}

      {/* CC lists */}
      {(internalCcList.length > 0 || externalCcList.length > 0) && (
        <div className="mt-4 pt-2 border-t border-gray-200 dark:border-gray-600 text-xs text-gray-600 dark:text-gray-400">
          {internalCcList.length > 0 && (
            <div>
              <span
                className="font-semibold text-gray-900 dark:text-white"
                style={labelStyle(labels.cc.style)}
              >
                {labels.cc[displayLang]}
              </span>{" "}
              {renderStyledList(internalCcList, ccInternalStyle, "(none)")}
            </div>
          )}
          {externalCcList.length > 0 && (
            <div>
              <span
                className="font-semibold text-gray-900 dark:text-white"
                style={labelStyle(labels.cc.style)}
              >
                {labels.cc[displayLang]}
              </span>{" "}
              {renderStyledList(externalCcList, ccExternalStyle, "(none)")}
            </div>
          )}
        </div>
      )}

      {/* Prefix CC / Suffix CC (optional) */}
      {(content.prefixCC || content.suffixCC) && (
        <div className="text-xs text-gray-400 dark:text-gray-500 mt-1">
          <span style={ccPrefixStyle}>{content.prefixCC}</span>{" "}
          <span style={ccSuffixStyle}>{content.suffixCC}</span>
        </div>
      )}

      {/* Footer with its own style */}
      {selectedFooter && (
        <div
          className="mt-6 border-t border-gray-200 dark:border-gray-600 pt-4"
          style={footerStyle}
          dangerouslySetInnerHTML={{ __html: sanitizeHtml(selectedFooter) }}
        />
      )}

      {/* Small indicator of template name / record type */}
      <div className="text-xs text-gray-400 dark:text-gray-500 mt-4 text-right">
        {templateName && `${templateName} • `}
        {recordType === "external" ? "External" : "Internal"}
      </div>
    </div>
  );
};
