// services/watermark.js
// Server-side watermark compositor using Sharp + SVG overlays

const sharp = require("sharp");
const crypto = require("crypto");

/**
 * Choose white or black text based on image brightness.
 * Uses Sharp stats (mean of all channels) as a simple heuristic.
 */
async function autoWatermarkColor(input) {
  const stats = await sharp(input).stats();
  // Average perceived brightness from RGB means
  const r = stats.channels[0].mean;
  const g = stats.channels[1].mean;
  const b = stats.channels[2].mean;
  const brightness = 0.2126 * r + 0.7152 * g + 0.0722 * b;
  // If background is bright, use black; otherwise white.
  return brightness > 140 ? "#000000" : "#FFFFFF";
}

/**
 * Make a 10-digit code from a string id (stable) or random if missing.
 */
function toTenDigitCode(seed) {
  if (!seed) {
    return (Math.floor(1e9 + Math.random() * 9e9).toString() + Math.floor(Math.random()*10)).slice(0,10);
  }
  const hash = crypto.createHash("sha256").update(String(seed)).digest("hex");
  // take 10 digits from hash
  const digits = hash.replace(/[a-f]/g, c => (parseInt(c,16) % 10).toString()).slice(0,10);
  return digits.padEnd(10, "0");
}

/**
 * Build an SVG overlay the same size as the image with:
 * - Big diagonal "IBrandBiz" in center
 * - Repeating smaller diagonal "IBrandBiz" around it
 * - Vertical left-edge "IBrandBiz | #10digits"
 *
 * @param {number} width
 * @param {number} height
 * @param {string} color - "#FFFFFF" or "#000000"
 * @param {number} opacity - 0..1
 * @param {string} stockCode - 10-digit string
 */
function buildWatermarkSVG(width, height, color, opacity, stockCode) {
  const bigFont = Math.round(Math.min(width, height) * 0.18);      // big center
  const smallFont = Math.round(Math.min(width, height) * 0.065);    // repeated
  const angle = -30;                                                // diagonal tilt
  const label = "IBrandBiz";
  const codeLabel = `IBrandBiz | #${stockCode}`;

  // Tile positions for the smaller diagonals
  const tiles = [];
  const cols = 3;
  const rows = 3;
  for (let r = -1; r <= rows; r++) {
    for (let c = -1; c <= cols; c++) {
      tiles.push({ x: (c + 0.5) * (width / cols), y: (r + 0.5) * (height / rows) });
    }
  }

  // Vertical code bar on the left
  const codeX = Math.round(width * 0.04);
  const codeY = Math.round(height * 0.5);
  const codeFont = Math.round(Math.min(width, height) * 0.05);

  const svg = `
<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}">
  <defs>
    <style><![CDATA[
      .wm-big { font-family: Arial, Helvetica, sans-serif; font-weight: 700; font-size: ${bigFont}px; fill: ${color}; opacity: ${opacity}; }
      .wm-small { font-family: Arial, Helvetica, sans-serif; font-weight: 700; font-size: ${smallFont}px; fill: ${color}; opacity: ${opacity}; }
      .wm-code { font-family: Arial, Helvetica, sans-serif; font-weight: 700; font-size: ${codeFont}px; fill: ${color}; opacity: ${opacity}; }
    ]]></style>
  </defs>

  <!-- Big center label -->
  <g transform="translate(${width/2}, ${height/2}) rotate(${angle})">
    <text class="wm-big" text-anchor="middle" dominant-baseline="middle">${label}</text>
  </g>

  <!-- Repeated small diagonals -->
  ${tiles.map(t => `
  <g transform="translate(${t.x}, ${t.y}) rotate(${angle})">
    <text class="wm-small" text-anchor="middle" dominant-baseline="middle">${label}</text>
  </g>`).join("")}

  <!-- Vertical stock code along left side -->
  <g transform="translate(${codeX}, ${codeY}) rotate(-90)">
    <text class="wm-code" text-anchor="middle" dominant-baseline="middle">${codeLabel}</text>
  </g>
</svg>`.trim();

  return Buffer.from(svg);
}

/**
 * Apply Adobe-style watermark overlay to an input image buffer/path.
 *
 * @param {Buffer|string} input - file path or buffer
 * @param {object} opts
 * @param {string} [opts.stockSeed] - stable id to derive 10-digit code
 * @param {number} [opts.opacity=0.15] - watermark opacity (0..1)
 * @returns {Promise<Buffer>} - watermarked image (same format as input)
 */
async function applyWatermark(input, opts = {}) {
  const { stockSeed, opacity = 0.15 } = opts;
  const img = sharp(input);
  const meta = await img.metadata();

  // Fallback size if metadata missing
  const width = meta.width || 2000;
  const height = meta.height || 1200;

  const color = await autoWatermarkColor(input);
  const code = toTenDigitCode(stockSeed);

  const overlay = buildWatermarkSVG(width, height, color, opacity, code);

  // Keep original format
  const pipeline = sharp(input)
    .composite([{ input: overlay, gravity: "center" }])
    .withMetadata();

  if (meta.format === "jpeg" || meta.format === "jpg") {
    return pipeline.jpeg({ quality: 90 }).toBuffer();
  } else if (meta.format === "png") {
    return pipeline.png({ compressionLevel: 9 }).toBuffer();
  } else if (meta.format === "webp") {
    return pipeline.webp({ quality: 90 }).toBuffer();
  } else if (meta.format === "avif") {
    return pipeline.avif({ quality: 50 }).toBuffer();
  }
  // Default to PNG if unknown
  return pipeline.png({ compressionLevel: 9 }).toBuffer();
}

module.exports = {
  applyWatermark,
  toTenDigitCode,
};
