/**
 * Container Background Layer
 *
 * Renders the container's background (color and image) BEHIND all elements.
 * This component should be placed in a Layer that renders before the elements layer.
 *
 * Supports CSS-like background properties:
 * - backgroundSize: cover, contain, auto
 * - backgroundPosition: center, top, bottom, left, right
 * - backgroundRepeat: no-repeat, repeat, repeat-x, repeat-y
 */

import {Rect, Image as KonvaImage, Group} from "react-konva";
import {useMemo, useState, useEffect} from "react";
import {useElements, useContainerSettings} from "@/stores/canvasStore";
import {calculateContainerBounds} from "@/utils/layoutAnalyzer";
import type {ContainerSettings} from "@/types";

interface ContainerBackgroundProps {
  containerSize: {width: number; height: number};
}

/**
 * Calculate image dimensions and position based on CSS-like background settings
 */
function calculateImageLayout(
  imgWidth: number,
  imgHeight: number,
  containerWidth: number,
  containerHeight: number,
  size: ContainerSettings["backgroundSize"],
  position: ContainerSettings["backgroundPosition"]
): {
  x: number;
  y: number;
  width: number;
  height: number;
  cropX?: number;
  cropY?: number;
  cropWidth?: number;
  cropHeight?: number;
} {
  const imgAspect = imgWidth / imgHeight;
  const containerAspect = containerWidth / containerHeight;

  let finalWidth: number;
  let finalHeight: number;
  let offsetX = 0;
  let offsetY = 0;

  // Calculate dimensions based on size mode
  switch (size) {
    case "cover": {
      // Scale to cover entire container (may crop)
      if (imgAspect > containerAspect) {
        // Image is wider - fit height, crop width
        finalHeight = containerHeight;
        finalWidth = containerHeight * imgAspect;
      } else {
        // Image is taller - fit width, crop height
        finalWidth = containerWidth;
        finalHeight = containerWidth / imgAspect;
      }
      break;
    }
    case "contain": {
      // Scale to fit inside container (may have empty space)
      if (imgAspect > containerAspect) {
        // Image is wider - fit width
        finalWidth = containerWidth;
        finalHeight = containerWidth / imgAspect;
      } else {
        // Image is taller - fit height
        finalHeight = containerHeight;
        finalWidth = containerHeight * imgAspect;
      }
      break;
    }
    case "auto":
    default: {
      // Use original image dimensions
      finalWidth = imgWidth;
      finalHeight = imgHeight;
      break;
    }
  }

  // Calculate position offset
  switch (position) {
    case "center":
      offsetX = (containerWidth - finalWidth) / 2;
      offsetY = (containerHeight - finalHeight) / 2;
      break;
    case "top":
      offsetX = (containerWidth - finalWidth) / 2;
      offsetY = 0;
      break;
    case "bottom":
      offsetX = (containerWidth - finalWidth) / 2;
      offsetY = containerHeight - finalHeight;
      break;
    case "left":
      offsetX = 0;
      offsetY = (containerHeight - finalHeight) / 2;
      break;
    case "right":
      offsetX = containerWidth - finalWidth;
      offsetY = (containerHeight - finalHeight) / 2;
      break;
  }

  return {
    x: offsetX,
    y: offsetY,
    width: finalWidth,
    height: finalHeight,
  };
}

/**
 * Convert CSS repeat value to Konva fillPatternRepeat
 */
function getKonvaRepeat(
  repeat: ContainerSettings["backgroundRepeat"]
): "repeat" | "repeat-x" | "repeat-y" | "no-repeat" {
  return repeat;
}

export function ContainerBackground({
  containerSize: _containerSize,
}: ContainerBackgroundProps) {
  const elements = useElements();
  const containerSettings = useContainerSettings();

  const [bgImage, setBgImage] = useState<HTMLImageElement | null>(null);
  const [imageSize, setImageSize] = useState<{
    width: number;
    height: number;
  } | null>(null);

  // Load background image if set
  useEffect(() => {
    if (containerSettings.backgroundImage) {
      const img = new window.Image();
      img.crossOrigin = "anonymous";
      img.src = containerSettings.backgroundImage;
      img.onload = () => {
        setBgImage(img);
        setImageSize({width: img.naturalWidth, height: img.naturalHeight});
      };
    } else {
      setBgImage(null);
      setImageSize(null);
    }
  }, [containerSettings.backgroundImage]);

  // Calculate bounds from visible elements
  const bounds = useMemo(() => {
    const visibleElements = elements.filter((el) => el.visible);
    if (visibleElements.length === 0) return null;

    return calculateContainerBounds(visibleElements, 8); // 8px padding
  }, [elements]);

  // Calculate image layout based on settings
  const imageLayout = useMemo(() => {
    if (!bgImage || !imageSize || !bounds) return null;

    const {padding} = containerSettings;
    // Safe accessors with fallback to 0
    const padLeft = padding?.left?.desktop ?? 0;
    const padRight = padding?.right?.desktop ?? 0;
    const padTop = padding?.top?.desktop ?? 0;
    const padBottom = padding?.bottom?.desktop ?? 0;

    const containerWidth = bounds.width + padLeft + padRight;
    const containerHeight = bounds.height + padTop + padBottom;

    return calculateImageLayout(
      imageSize.width,
      imageSize.height,
      containerWidth,
      containerHeight,
      containerSettings.backgroundSize,
      containerSettings.backgroundPosition
    );
  }, [bgImage, imageSize, bounds, containerSettings]);

  if (!bounds) {
    return null;
  }

  // Extract container settings
  const {border, padding, backgroundColor, backgroundRepeat} =
    containerSettings;

  // Safe accessors for padding (default to 0)
  const padTop = padding?.top?.desktop ?? 0;
  const padRight = padding?.right?.desktop ?? 0;
  const padBottom = padding?.bottom?.desktop ?? 0;
  const padLeft = padding?.left?.desktop ?? 0;

  // Calculate padded bounds (the actual container area including padding)
  const paddedBounds = {
    x: bounds.x - padLeft,
    y: bounds.y - padTop,
    width: bounds.width + padLeft + padRight,
    height: bounds.height + padTop + padBottom,
  };

  // Check if there's any background to render
  const hasBackground =
    (backgroundColor && backgroundColor !== "transparent") || bgImage;
  const hasBorder = border.width.desktop > 0;

  if (!hasBackground && !hasBorder) {
    return null;
  }

  // Determine if we should use pattern fill (for repeat modes)
  const usePatternFill = bgImage && backgroundRepeat !== "no-repeat";

  return (
    <Group listening={false}>
      {/* Background color layer */}
      {backgroundColor && backgroundColor !== "transparent" && (
        <Rect
          x={paddedBounds.x}
          y={paddedBounds.y}
          width={paddedBounds.width}
          height={paddedBounds.height}
          fill={backgroundColor}
          cornerRadius={border.radius}
          listening={false}
        />
      )}

      {/* Background image with pattern fill (for repeat modes) */}
      {usePatternFill && bgImage && (
        <Rect
          x={paddedBounds.x}
          y={paddedBounds.y}
          width={paddedBounds.width}
          height={paddedBounds.height}
          fillPatternImage={bgImage}
          fillPatternRepeat={getKonvaRepeat(backgroundRepeat)}
          fillPatternScale={
            imageLayout
              ? {
                  x: imageLayout.width / (imageSize?.width ?? 1),
                  y: imageLayout.height / (imageSize?.height ?? 1),
                }
              : {x: 1, y: 1}
          }
          fillPatternOffset={
            imageLayout ? {x: -imageLayout.x, y: -imageLayout.y} : {x: 0, y: 0}
          }
          cornerRadius={border.radius}
          listening={false}
        />
      )}

      {/* Background image without repeat (cover/contain/auto with no-repeat) */}
      {!usePatternFill && bgImage && imageLayout && (
        <Group
          x={paddedBounds.x}
          y={paddedBounds.y}
          clipX={0}
          clipY={0}
          clipWidth={paddedBounds.width}
          clipHeight={paddedBounds.height}
        >
          <KonvaImage
            x={imageLayout.x}
            y={imageLayout.y}
            width={imageLayout.width}
            height={imageLayout.height}
            image={bgImage}
            listening={false}
          />
        </Group>
      )}

      {/* Border (on top of everything) */}
      {hasBorder && (
        <Rect
          x={paddedBounds.x}
          y={paddedBounds.y}
          width={paddedBounds.width}
          height={paddedBounds.height}
          stroke={border.color}
          strokeWidth={border.width.desktop}
          dash={
            border.style === "dashed"
              ? [6, 4]
              : border.style === "dotted"
              ? [2, 2]
              : undefined
          }
          cornerRadius={border.radius}
          fill="transparent"
          listening={false}
        />
      )}
    </Group>
  );
}
