import { clampRect, type LayoutRect } from "./layoutProfile.js";
import type { Bitmap } from "./ocrPreprocess.js";

// EXPERIMENTAL, read-only lock-status detection (nice-to-have). Genshin shows a
// padlock at the top-right of the artifact detail card: a highlighted red/pink
// lock in the current UI when locked, and a dim grey/white button when not.
// Older UI captures may still use gold highlights. This estimates that icon
// region and measures the fraction of active lock-colour pixels; above a
// threshold the piece is considered locked.
//
// The crop position and threshold were validated with unlocked=false and
// locked=true live samples on 2026-07-09. It never drives any in-game action -
// it only reads state for triage and export.

export function lockIconCropRect(detailRect: LayoutRect, imageSize: { width: number; height: number }): LayoutRect {
  return clampRect(
    {
      x: Math.round(detailRect.x + detailRect.width * 0.735),
      y: Math.round(detailRect.y + detailRect.height * 0.355),
      width: Math.round(detailRect.width * 0.105),
      height: Math.round(detailRect.height * 0.07),
    },
    imageSize,
  );
}

// A gold/highlighted lock pixel: red high, green mid-high, blue low.
function isLockGold(b: number, g: number, r: number): boolean {
  return r >= 180 && g >= 140 && b <= 120 && r > b + 40 && g > b + 20;
}

// Current Genshin detail lock indicator: pink/red lock glyph and dark button
// when the selected artifact is locked. Unlocked buttons are mostly grey/white.
function isLockRed(b: number, g: number, r: number): boolean {
  return r >= 180 && g <= 145 && b <= 145 && r > g + 35 && r > b + 35;
}

function isActiveLockPixel(c0: number, c1: number, c2: number): boolean {
  const colorMatches = (left: number, middle: number, right: number) =>
    isLockGold(left, middle, right) ||
    isLockRed(left, middle, right) ||
    isLockGold(right, middle, left) ||
    isLockRed(right, middle, left);
  return colorMatches(c0, c1, c2);
}

function inferAlphaChannel(data: Buffer | Uint8Array, pixels: number): number | null {
  const highCounts = [0, 0, 0, 0];
  for (let pixel = 0; pixel < pixels; pixel++) {
    const index = pixel * 4;
    for (let channel = 0; channel < 4; channel++) {
      if (data[index + channel] >= 245) highCounts[channel]++;
    }
  }
  const ranked = highCounts
    .map((count, channel) => ({ count, channel }))
    .sort((left, right) => right.count - left.count);
  const best = ranked[0];
  const second = ranked[1];
  if (best.count / pixels < 0.9) return null;
  if (second && second.count / pixels > 0.8) return null;
  return best.channel;
}

export function lockSignalRatio(bitmap: Bitmap): number {
  const { data, width, height } = bitmap;
  const pixels = width * height;
  if (pixels === 0) return 0;
  const alphaChannel = inferAlphaChannel(data, pixels);
  let gold = 0;
  for (let pixel = 0; pixel < pixels; pixel++) {
    const index = pixel * 4;
    const colorChannels = [0, 1, 2, 3]
      .filter((channel) => channel !== alphaChannel)
      .map((channel) => data[index + channel])
      .slice(0, 3);
    if (colorChannels.length === 3 && isActiveLockPixel(colorChannels[0], colorChannels[1], colorChannels[2])) gold++;
  }
  return gold / pixels;
}

export const DEFAULT_LOCK_THRESHOLD = 0.06;

export function isLocked(signalRatio: number, threshold: number = DEFAULT_LOCK_THRESHOLD): boolean {
  return signalRatio >= threshold;
}

export function detectLockState(bitmap: Bitmap, threshold: number = DEFAULT_LOCK_THRESHOLD): boolean {
  return isLocked(lockSignalRatio(bitmap), threshold);
}
