/**
 * CurrencyElementRenderer Component
 *
 * Renders currency symbol elements with support for:
 * - Custom currency symbols from dropdown
 * - Custom images from WordPress media library
 * - Proper padding support
 * - WooCommerce default currency
 * - Auto-resize when symbol changes
 */

import { Group, Text, Image as KonvaImage } from "react-konva";
import { useEffect, useState } from "react";
import type { CurrencyElement } from "@/types";
import { getCanvasFontFamily } from "@/types";
import { getWooCommerceCurrency } from "@/constants/currencySymbols";
import { useGoogleFont } from "@/hooks/useGoogleFonts";
import { useCanvasStore } from "@/stores/canvasStore";

interface CurrencyElementRendererProps {
  element: CurrencyElement;
}

// Build Konva fontStyle string
const buildFontStyle = (element: CurrencyElement): string => {
  const parts: string[] = [];

  if (element.typography.fontWeight.desktop >= 700) {
    parts.push("bold");
  } else if (element.typography.fontWeight.desktop <= 300) {
    parts.push("300");
  }

  if (element.typography.fontStyle === "italic") {
    parts.push("italic");
  }

  return parts.join(" ") || "normal";
};

/**
 * Calculate the required size for a currency symbol element.
 * Uses canvas measureText for accurate width calculation.
 */
const calculateCurrencySize = (
  symbol: string,
  fontSize: number,
  fontFamily: string | undefined,
  fontWeight: number,
  fontStyle: string,
  letterSpacing: number,
  padding: { top: number; right: number; bottom: number; left: number }
): { width: number; height: number } => {
  // Create an offscreen canvas for measuring
  const canvas = document.createElement("canvas");
  const ctx = canvas.getContext("2d");

  let textWidth: number;

  if (!ctx) {
    // Fallback estimation - some symbols like ﷼ or KSh are wider
    textWidth = fontSize * 0.8 * symbol.length;
  } else {
    // Build font string
    const weight = fontWeight >= 700 ? "bold" : fontWeight;
    const style = fontStyle === "italic" ? "italic" : "";
    ctx.font = `${style} ${weight} ${fontSize}px ${fontFamily || "sans-serif"}`;

    // Measure the actual text width
    const metrics = ctx.measureText(symbol);
    const letterSpacingWidth = (symbol.length - 1) * letterSpacing;
    textWidth = metrics.width + letterSpacingWidth;
  }

  // Ensure minimum width based on character count and font size
  // This prevents extremely narrow elements at certain font sizes
  const minWidth = symbol.length * fontSize * 0.5;
  textWidth = Math.max(textWidth, minWidth);

  // Add a small buffer to prevent clipping
  const widthBuffer = Math.max(2, fontSize * 0.1);

  return {
    width: Math.round(textWidth + padding.left + padding.right + widthBuffer),
    height: Math.round(fontSize + padding.top + padding.bottom),
  };
};

export function CurrencyElementRenderer({ element }: CurrencyElementRendererProps) {
  const [image, setImage] = useState<HTMLImageElement | null>(null);
  const updateElement = useCanvasStore((state) => state.updateElement);

  // Load Google font if needed - triggers re-render when font is ready
  useGoogleFont(element.typography.fontFamily);

  // Get canvas-safe font family (undefined for default)
  const fontFamily = getCanvasFontFamily(element.typography.fontFamily);

  // Get the display symbol - use element symbol or fallback to WooCommerce default
  const displaySymbol = element.symbol || getWooCommerceCurrency().symbol || "$";

  // Auto-resize element when symbol or typography changes
  useEffect(() => {
    // Skip resize for custom images
    if (element.useCustomImage && element.customImageUrl) {
      return;
    }

    const padding = {
      top: element.padding.top.desktop,
      right: element.padding.right.desktop,
      bottom: element.padding.bottom.desktop,
      left: element.padding.left.desktop,
    };

    const requiredSize = calculateCurrencySize(
      displaySymbol,
      element.typography.fontSize.desktop,
      fontFamily,
      element.typography.fontWeight.desktop,
      element.typography.fontStyle,
      element.typography.letterSpacing.desktop,
      padding
    );

    // Auto-resize to fit content (both grow and shrink)
    const widthDiffers = Math.abs(element.size.width - requiredSize.width) > 1;
    const heightDiffers = Math.abs(element.size.height - requiredSize.height) > 1;

    if (widthDiffers || heightDiffers) {
      updateElement(element.id, {
        size: {
          width: requiredSize.width,
          height: requiredSize.height,
        },
      });
    }
  }, [
    element.id,
    element.symbol,
    displaySymbol,
    element.size.width,
    element.size.height,
    element.typography.fontSize.desktop,
    element.typography.fontWeight.desktop,
    element.typography.fontStyle,
    element.typography.letterSpacing.desktop,
    element.padding.top.desktop,
    element.padding.right.desktop,
    element.padding.bottom.desktop,
    element.padding.left.desktop,
    element.useCustomImage,
    element.customImageUrl,
    fontFamily,
    updateElement,
  ]);

  // Load custom image if specified
  useEffect(() => {
    if (element.useCustomImage && element.customImageUrl) {
      const img = new window.Image();
      img.crossOrigin = "anonymous";
      img.onload = () => {
        setImage(img);

        // Auto-resize element based on image dimensions
        // Scale image to fit within a reasonable height based on typography fontSize
        const targetHeight = element.typography.fontSize.desktop;
        const imageAspect = img.width / img.height;
        const targetWidth = targetHeight * imageAspect;

        // Add padding to get final element size
        const padding = {
          top: element.padding.top.desktop,
          right: element.padding.right.desktop,
          bottom: element.padding.bottom.desktop,
          left: element.padding.left.desktop,
        };

        const newWidth = Math.round(targetWidth + padding.left + padding.right);
        const newHeight = Math.round(targetHeight + padding.top + padding.bottom);

        // Only update if size differs significantly
        const widthDiffers = Math.abs(element.size.width - newWidth) > 1;
        const heightDiffers = Math.abs(element.size.height - newHeight) > 1;

        if (widthDiffers || heightDiffers) {
          updateElement(element.id, {
            size: {
              width: newWidth,
              height: newHeight,
            },
          });
        }
      };
      img.onerror = () => setImage(null);
      img.src = element.customImageUrl;
    } else {
      setImage(null);
    }
  }, [
    element.useCustomImage,
    element.customImageUrl,
    element.id,
    element.typography.fontSize.desktop,
    element.padding.top.desktop,
    element.padding.right.desktop,
    element.padding.bottom.desktop,
    element.padding.left.desktop,
    element.size.width,
    element.size.height,
    updateElement,
  ]);

  // Calculate content area (inside padding)
  const contentX = element.padding.left.desktop;
  const contentY = element.padding.top.desktop;
  const contentWidth = element.size.width - element.padding.left.desktop - element.padding.right.desktop;
  const contentHeight = element.size.height - element.padding.top.desktop - element.padding.bottom.desktop;

  // If using custom image and image is loaded
  if (element.useCustomImage && image) {
    // Calculate image dimensions to fit within content area while maintaining aspect ratio
    const imageAspect = image.width / image.height;
    const contentAspect = contentWidth / contentHeight;

    let imgWidth: number;
    let imgHeight: number;

    if (imageAspect > contentAspect) {
      // Image is wider - fit to width
      imgWidth = contentWidth;
      imgHeight = contentWidth / imageAspect;
    } else {
      // Image is taller - fit to height
      imgHeight = contentHeight;
      imgWidth = contentHeight * imageAspect;
    }

    // Center image within content area
    const imgX = contentX + (contentWidth - imgWidth) / 2;
    const imgY = contentY + (contentHeight - imgHeight) / 2;

    return (
      <Group>
        <KonvaImage x={imgX} y={imgY} width={imgWidth} height={imgHeight} image={image} listening={false} />
      </Group>
    );
  }

  // Render text symbol
  return (
    <Text
      x={contentX}
      y={contentY}
      width={contentWidth}
      height={contentHeight}
      text={displaySymbol}
      fill={element.color}
      fontFamily={fontFamily}
      fontSize={element.typography.fontSize.desktop}
      fontStyle={buildFontStyle(element)}
      lineHeight={element.typography.lineHeight}
      letterSpacing={element.typography.letterSpacing.desktop}
      textDecoration={element.typography.textDecoration === "none" ? "" : element.typography.textDecoration}
      align="center"
      verticalAlign="middle"
      listening={false}
    />
  );
}
