import { createCanvas, loadImage } from "@napi-rs/canvas";

const BUTTON_SIZE = 144; // Stream Deck XL size
const PADDING = 8;
const FONT_FAMILY = "Arial, sans-serif";

/**
 * Generate a button image with track info
 * @param {Object} options
 * @param {string} options.title - Track title
 * @param {string} options.artist - Track artist
 * @param {string|null} options.image - Base64 image or null
 * @param {string} options.backgroundColor - Background color
 * @param {boolean} options.isPlaying - Whether track is playing
 * @param {string} options.label - Optional label (e.g., "PREV", "NEXT")
 * @returns {string} Base64 encoded PNG image
 */
export function generateButtonImage({
  title = "",
  artist = "",
  image = null,
  backgroundColor = "#1a1a2e",
  isPlaying = false,
  label = null,
}) {
  const canvas = createCanvas(BUTTON_SIZE, BUTTON_SIZE);
  const ctx = canvas.getContext("2d");

  // Background
  ctx.fillStyle = backgroundColor;
  ctx.fillRect(0, 0, BUTTON_SIZE, BUTTON_SIZE);

  // Playing indicator border
  if (isPlaying) {
    ctx.strokeStyle = "#00ff88";
    ctx.lineWidth = 4;
    ctx.strokeRect(2, 2, BUTTON_SIZE - 4, BUTTON_SIZE - 4);
  }

  // If we have an image, draw it
  if (image) {
    return drawWithImage(canvas, ctx, { title, artist, image, label });
  }

  // No image - draw text placeholder
  return drawTextOnly(canvas, ctx, { title, artist, backgroundColor, label });
}

async function drawWithImage(canvas, ctx, { title, artist, image, label }) {
  try {
    // Load and draw the cover image
    const img = await loadImage(image);

    // Draw image (cover most of the button)
    const imgSize = BUTTON_SIZE - PADDING * 2;
    ctx.drawImage(img, PADDING, PADDING, imgSize, imgSize - 30);

    // Semi-transparent overlay at bottom for text
    ctx.fillStyle = "rgba(0, 0, 0, 0.7)";
    ctx.fillRect(0, BUTTON_SIZE - 40, BUTTON_SIZE, 40);

    // Title
    ctx.fillStyle = "#ffffff";
    ctx.font = `bold 14px ${FONT_FAMILY}`;
    ctx.textAlign = "center";
    ctx.textBaseline = "top";
    const truncatedTitle = truncateText(ctx, title, BUTTON_SIZE - PADDING * 2);
    ctx.fillText(truncatedTitle, BUTTON_SIZE / 2, BUTTON_SIZE - 36);

    // Artist
    ctx.fillStyle = "#cccccc";
    ctx.font = `12px ${FONT_FAMILY}`;
    const truncatedArtist = truncateText(ctx, artist, BUTTON_SIZE - PADDING * 2);
    ctx.fillText(truncatedArtist, BUTTON_SIZE / 2, BUTTON_SIZE - 20);

    // Label badge if provided
    if (label) {
      drawLabel(ctx, label);
    }

    return canvas.toDataURL("image/png");
  } catch (e) {
    // If image loading fails, fall back to text only
    return drawTextOnly(canvas, ctx, { title, artist, backgroundColor: "#1a1a2e", label });
  }
}

function drawTextOnly(canvas, ctx, { title, artist, backgroundColor, label }) {
  // Generate a color based on the title
  const hue = hashStringToHue(title || "default");
  const bgGradient = ctx.createLinearGradient(0, 0, BUTTON_SIZE, BUTTON_SIZE);
  bgGradient.addColorStop(0, `hsl(${hue}, 40%, 25%)`);
  bgGradient.addColorStop(1, `hsl(${hue}, 40%, 15%)`);

  ctx.fillStyle = bgGradient;
  ctx.fillRect(0, 0, BUTTON_SIZE, BUTTON_SIZE);

  // First letter as large icon
  if (title) {
    ctx.fillStyle = `hsl(${hue}, 60%, 60%)`;
    ctx.font = `bold 48px ${FONT_FAMILY}`;
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    ctx.fillText(title.charAt(0).toUpperCase(), BUTTON_SIZE / 2, BUTTON_SIZE / 2 - 15);
  }

  // Title at bottom
  ctx.fillStyle = "#ffffff";
  ctx.font = `bold 13px ${FONT_FAMILY}`;
  ctx.textAlign = "center";
  ctx.textBaseline = "bottom";
  const truncatedTitle = truncateText(ctx, title, BUTTON_SIZE - PADDING * 2);
  ctx.fillText(truncatedTitle, BUTTON_SIZE / 2, BUTTON_SIZE - 22);

  // Artist
  ctx.fillStyle = "#aaaaaa";
  ctx.font = `11px ${FONT_FAMILY}`;
  const truncatedArtist = truncateText(ctx, artist, BUTTON_SIZE - PADDING * 2);
  ctx.fillText(truncatedArtist, BUTTON_SIZE / 2, BUTTON_SIZE - 8);

  // Label badge if provided
  if (label) {
    drawLabel(ctx, label);
  }

  return canvas.toDataURL("image/png");
}

function drawLabel(ctx, label) {
  const labelColors = {
    PREV: "#ff9800",
    NEXT: "#4caf50",
    STOP: "#f44336",
  };

  const bgColor = labelColors[label] || "#666666";

  ctx.fillStyle = bgColor;
  ctx.beginPath();
  ctx.roundRect(PADDING, PADDING, 40, 18, 4);
  ctx.fill();

  ctx.fillStyle = "#ffffff";
  ctx.font = `bold 10px ${FONT_FAMILY}`;
  ctx.textAlign = "center";
  ctx.textBaseline = "middle";
  ctx.fillText(label, PADDING + 20, PADDING + 9);
}

function truncateText(ctx, text, maxWidth) {
  if (!text) return "";

  let truncated = text;
  let width = ctx.measureText(truncated).width;

  while (width > maxWidth && truncated.length > 0) {
    truncated = truncated.slice(0, -1);
    width = ctx.measureText(truncated + "…").width;
  }

  return truncated.length < text.length ? truncated + "…" : truncated;
}

function hashStringToHue(str) {
  let hash = 0;
  for (let i = 0; i < str.length; i++) {
    hash = str.charCodeAt(i) + ((hash << 5) - hash);
  }
  return Math.abs(hash) % 360;
}

/**
 * Generate a record/stop toggle button
 * @param {Object} options
 * @param {boolean} options.isConnected - Whether connected to app
 * @param {'idle'|'confirm'|'recording'|'confirm-stop'} options.state - Button state
 * @returns {string} Base64 encoded PNG image
 */
export function generateRecordButton({ isConnected, state = "idle" }) {
  const canvas = createCanvas(BUTTON_SIZE, BUTTON_SIZE);
  const ctx = canvas.getContext("2d");

  if (!isConnected) {
    ctx.fillStyle = "#2a2a2a";
    ctx.fillRect(0, 0, BUTTON_SIZE, BUTTON_SIZE);

    ctx.fillStyle = "#666666";
    ctx.font = `bold 14px ${FONT_FAMILY}`;
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    ctx.fillText("REC", BUTTON_SIZE / 2, BUTTON_SIZE / 2 - 10);
    ctx.fillText("OFFLINE", BUTTON_SIZE / 2, BUTTON_SIZE / 2 + 10);

    return canvas.toDataURL("image/png");
  }

  const cx = BUTTON_SIZE / 2;
  const cy = BUTTON_SIZE / 2 - 10;
  const squareSize = 40;

  if (state === "confirm") {
    // Confirm START — red background + red circle
    ctx.fillStyle = "#8b0000";
    ctx.fillRect(0, 0, BUTTON_SIZE, BUTTON_SIZE);

    ctx.fillStyle = "#ff0000";
    ctx.beginPath();
    ctx.arc(cx, cy, 28, 0, Math.PI * 2);
    ctx.fill();

    ctx.fillStyle = "#ffffff";
    ctx.font = `bold 13px ${FONT_FAMILY}`;
    ctx.textAlign = "center";
    ctx.textBaseline = "bottom";
    ctx.fillText("CONFIRM?", BUTTON_SIZE / 2, BUTTON_SIZE - 12);
  } else if (state === "recording") {
    // Recording active — show STOP square + red border
    ctx.fillStyle = "#3a0000";
    ctx.fillRect(0, 0, BUTTON_SIZE, BUTTON_SIZE);

    // Red border
    ctx.strokeStyle = "#ff0000";
    ctx.lineWidth = 4;
    ctx.strokeRect(2, 2, BUTTON_SIZE - 4, BUTTON_SIZE - 4);

    // Stop square
    ctx.fillStyle = "#f44336";
    ctx.beginPath();
    ctx.roundRect(cx - squareSize / 2, cy - squareSize / 2, squareSize, squareSize, 6);
    ctx.fill();

    ctx.fillStyle = "#f44336";
    ctx.font = `bold 14px ${FONT_FAMILY}`;
    ctx.textAlign = "center";
    ctx.textBaseline = "bottom";
    ctx.fillText("STOP", BUTTON_SIZE / 2, BUTTON_SIZE - 12);
  } else if (state === "confirm-stop") {
    // Confirm STOP — red background + stop square
    ctx.fillStyle = "#8b0000";
    ctx.fillRect(0, 0, BUTTON_SIZE, BUTTON_SIZE);

    ctx.fillStyle = "#f44336";
    ctx.beginPath();
    ctx.roundRect(cx - squareSize / 2, cy - squareSize / 2, squareSize, squareSize, 6);
    ctx.fill();

    ctx.fillStyle = "#ffffff";
    ctx.font = `bold 13px ${FONT_FAMILY}`;
    ctx.textAlign = "center";
    ctx.textBaseline = "bottom";
    ctx.fillText("CONFIRM?", BUTTON_SIZE / 2, BUTTON_SIZE - 12);
  } else {
    // Idle state — REC circle
    ctx.fillStyle = "#1a1a2e";
    ctx.fillRect(0, 0, BUTTON_SIZE, BUTTON_SIZE);

    // Red circle outline
    ctx.strokeStyle = "#ff4444";
    ctx.lineWidth = 4;
    ctx.beginPath();
    ctx.arc(cx, cy, 28, 0, Math.PI * 2);
    ctx.stroke();

    // Small filled inner circle
    ctx.fillStyle = "#ff4444";
    ctx.beginPath();
    ctx.arc(cx, cy, 16, 0, Math.PI * 2);
    ctx.fill();

    ctx.fillStyle = "#ff4444";
    ctx.font = `bold 14px ${FONT_FAMILY}`;
    ctx.textAlign = "center";
    ctx.textBaseline = "bottom";
    ctx.fillText("REC", BUTTON_SIZE / 2, BUTTON_SIZE - 12);
  }

  return canvas.toDataURL("image/png");
}

/**
 * Generate a save playlist button
 * @param {Object} options
 * @param {boolean} options.isConnected - Whether connected to app
 * @param {'idle'|'saved'|'error'} options.state - Button state
 * @returns {string} Base64 encoded PNG image
 */
export function generateSaveButton({ isConnected, state = "idle" }) {
  const canvas = createCanvas(BUTTON_SIZE, BUTTON_SIZE);
  const ctx = canvas.getContext("2d");

  if (!isConnected) {
    ctx.fillStyle = "#2a2a2a";
    ctx.fillRect(0, 0, BUTTON_SIZE, BUTTON_SIZE);

    ctx.fillStyle = "#666666";
    ctx.font = `bold 14px ${FONT_FAMILY}`;
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    ctx.fillText("SAVE", BUTTON_SIZE / 2, BUTTON_SIZE / 2 - 10);
    ctx.fillText("OFFLINE", BUTTON_SIZE / 2, BUTTON_SIZE / 2 + 10);

    return canvas.toDataURL("image/png");
  }

  const cx = BUTTON_SIZE / 2;
  const cy = BUTTON_SIZE / 2 - 10;

  if (state === "saved") {
    // Success feedback
    ctx.fillStyle = "#1b5e20";
    ctx.fillRect(0, 0, BUTTON_SIZE, BUTTON_SIZE);

    // Checkmark
    ctx.strokeStyle = "#4caf50";
    ctx.lineWidth = 6;
    ctx.lineCap = "round";
    ctx.lineJoin = "round";
    ctx.beginPath();
    ctx.moveTo(cx - 20, cy);
    ctx.lineTo(cx - 5, cy + 18);
    ctx.lineTo(cx + 24, cy - 14);
    ctx.stroke();

    ctx.fillStyle = "#4caf50";
    ctx.font = `bold 14px ${FONT_FAMILY}`;
    ctx.textAlign = "center";
    ctx.textBaseline = "bottom";
    ctx.fillText("SAVED!", BUTTON_SIZE / 2, BUTTON_SIZE - 12);
  } else if (state === "error") {
    // Error feedback
    ctx.fillStyle = "#4a0000";
    ctx.fillRect(0, 0, BUTTON_SIZE, BUTTON_SIZE);

    // X mark
    ctx.strokeStyle = "#f44336";
    ctx.lineWidth = 6;
    ctx.lineCap = "round";
    ctx.beginPath();
    ctx.moveTo(cx - 16, cy - 16);
    ctx.lineTo(cx + 16, cy + 16);
    ctx.moveTo(cx + 16, cy - 16);
    ctx.lineTo(cx - 16, cy + 16);
    ctx.stroke();

    ctx.fillStyle = "#f44336";
    ctx.font = `bold 14px ${FONT_FAMILY}`;
    ctx.textAlign = "center";
    ctx.textBaseline = "bottom";
    ctx.fillText("ERROR", BUTTON_SIZE / 2, BUTTON_SIZE - 12);
  } else {
    // Idle state - floppy disk icon
    ctx.fillStyle = "#1a1a2e";
    ctx.fillRect(0, 0, BUTTON_SIZE, BUTTON_SIZE);

    const diskSize = 48;
    const dx = cx - diskSize / 2;
    const dy = cy - diskSize / 2;

    ctx.fillStyle = "#42a5f5";
    ctx.beginPath();
    ctx.roundRect(dx, dy, diskSize, diskSize, 4);
    ctx.fill();

    // Metal slider area (top)
    ctx.fillStyle = "#bbdefb";
    ctx.fillRect(dx + 12, dy, diskSize - 24, 20);

    // Label area (bottom)
    ctx.fillStyle = "#e3f2fd";
    ctx.fillRect(dx + 8, dy + diskSize - 18, diskSize - 16, 14);

    ctx.fillStyle = "#42a5f5";
    ctx.font = `bold 14px ${FONT_FAMILY}`;
    ctx.textAlign = "center";
    ctx.textBaseline = "bottom";
    ctx.fillText("SAVE", BUTTON_SIZE / 2, BUTTON_SIZE - 12);
  }

  return canvas.toDataURL("image/png");
}

/**
 * Generate a deck status button
 * @param {Object} options
 * @param {string} options.deckName - Name of the deck
 * @param {boolean} options.isConnected - Whether connected to app
 * @param {Object|null} options.currentTrack - Currently playing track
 * @param {string|null} options.deckImage - Base64 image of the deck type (vinyl, cd, etc.)
 * @returns {Promise<string>} Base64 encoded PNG image
 */
export async function generateDeckButton({ deckName, isConnected, currentTrack = null, deckImage = null }) {
  const canvas = createCanvas(BUTTON_SIZE, BUTTON_SIZE);
  const ctx = canvas.getContext("2d");

  if (!isConnected) {
    // Disconnected state
    ctx.fillStyle = "#2a2a2a";
    ctx.fillRect(0, 0, BUTTON_SIZE, BUTTON_SIZE);

    ctx.fillStyle = "#666666";
    ctx.font = `bold 14px ${FONT_FAMILY}`;
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    ctx.fillText(deckName, BUTTON_SIZE / 2, BUTTON_SIZE / 2 - 10);
    ctx.fillText("OFFLINE", BUTTON_SIZE / 2, BUTTON_SIZE / 2 + 10);

    return canvas.toDataURL("image/png");
  }

  if (currentTrack) {
    // Has a playing track - show it
    return generateButtonImage({
      title: currentTrack.title,
      artist: currentTrack.artist,
      image: currentTrack.image,
      isPlaying: true,
    });
  }

  // Connected but no track playing - show deck image if available
  ctx.fillStyle = "#1a1a2e";
  ctx.fillRect(0, 0, BUTTON_SIZE, BUTTON_SIZE);

  // Try to draw deck type image
  if (deckImage) {
    try {
      const img = await loadImage(deckImage);
      // Draw the deck image centered, smaller to leave room for text
      const imgSize = 64;
      const imgX = (BUTTON_SIZE - imgSize) / 2;
      const imgY = 20;
      ctx.drawImage(img, imgX, imgY, imgSize, imgSize);
    } catch (e) {
      // If image loading fails, continue without it
    }
  }

  // Deck name
  ctx.fillStyle = "#4fc3f7";
  ctx.font = `bold 14px ${FONT_FAMILY}`;
  ctx.textAlign = "center";
  ctx.textBaseline = "middle";
  ctx.fillText(deckName, BUTTON_SIZE / 2, BUTTON_SIZE - 40);

  // Ready indicator
  ctx.fillStyle = "#888888";
  ctx.font = `11px ${FONT_FAMILY}`;
  ctx.fillText("TAP TO SELECT", BUTTON_SIZE / 2, BUTTON_SIZE - 20);

  return canvas.toDataURL("image/png");
}

/**
 * Generate a reset session button
 * @param {Object} options
 * @param {boolean} options.isConnected - Whether connected to app
 * @returns {string} Base64 encoded PNG image
 */
export function generateResetButton({ isConnected }) {
  const canvas = createCanvas(BUTTON_SIZE, BUTTON_SIZE);
  const ctx = canvas.getContext("2d");

  if (!isConnected) {
    ctx.fillStyle = "#2a2a2a";
    ctx.fillRect(0, 0, BUTTON_SIZE, BUTTON_SIZE);

    ctx.fillStyle = "#666666";
    ctx.font = `bold 14px ${FONT_FAMILY}`;
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    ctx.fillText("RESET", BUTTON_SIZE / 2, BUTTON_SIZE / 2 - 10);
    ctx.fillText("OFFLINE", BUTTON_SIZE / 2, BUTTON_SIZE / 2 + 10);

    return canvas.toDataURL("image/png");
  }

  // Connected - draw reset button
  ctx.fillStyle = "#1a1a2e";
  ctx.fillRect(0, 0, BUTTON_SIZE, BUTTON_SIZE);

  // Draw undo arrow icon (curved arrow pointing left)
  const cx = BUTTON_SIZE / 2;
  const cy = BUTTON_SIZE / 2 - 10;
  const r = 28;

  ctx.strokeStyle = "#ff9800";
  ctx.lineWidth = 6;
  ctx.lineCap = "round";

  // Draw arc
  ctx.beginPath();
  ctx.arc(cx, cy, r, -Math.PI * 0.8, Math.PI * 0.1);
  ctx.stroke();

  // Arrowhead
  const arrowX = cx + r * Math.cos(-Math.PI * 0.8);
  const arrowY = cy + r * Math.sin(-Math.PI * 0.8);
  ctx.beginPath();
  ctx.moveTo(arrowX - 8, arrowY - 10);
  ctx.lineTo(arrowX, arrowY);
  ctx.lineTo(arrowX + 10, arrowY - 6);
  ctx.stroke();

  // Label
  ctx.fillStyle = "#ff9800";
  ctx.font = `bold 14px ${FONT_FAMILY}`;
  ctx.textAlign = "center";
  ctx.textBaseline = "bottom";
  ctx.fillText("RESET", BUTTON_SIZE / 2, BUTTON_SIZE - 12);

  return canvas.toDataURL("image/png");
}

/**
 * Generate a cancel/back button
 * @returns {string} Base64 encoded PNG image
 */
export function generateCancelButton() {
  const canvas = createCanvas(BUTTON_SIZE, BUTTON_SIZE);
  const ctx = canvas.getContext("2d");

  ctx.fillStyle = "#3a3a3a";
  ctx.fillRect(0, 0, BUTTON_SIZE, BUTTON_SIZE);

  // X icon
  ctx.strokeStyle = "#ff5555";
  ctx.lineWidth = 4;
  ctx.lineCap = "round";

  const margin = 45;
  ctx.beginPath();
  ctx.moveTo(margin, margin);
  ctx.lineTo(BUTTON_SIZE - margin, BUTTON_SIZE - margin);
  ctx.moveTo(BUTTON_SIZE - margin, margin);
  ctx.lineTo(margin, BUTTON_SIZE - margin);
  ctx.stroke();

  // Label
  ctx.fillStyle = "#ffffff";
  ctx.font = `bold 12px ${FONT_FAMILY}`;
  ctx.textAlign = "center";
  ctx.textBaseline = "bottom";
  ctx.fillText("CANCEL", BUTTON_SIZE / 2, BUTTON_SIZE - 10);

  return canvas.toDataURL("image/png");
}
