import { BgLayer, BgType } from "../base/BgLayer";
import { BorderLayer } from "../base/BorderLayer";
import { BoxLayer } from "../base/BoxLayer";
import { DebugLayer } from "../base/DebugLayer";
import { FrameLayer } from "../base/FrameLayer";
import { TouchTracker } from "../base/Gesture";
import { ImageShaders } from "../base/ImageShaders";
import { Padding, Scene } from "../base/Scene";
import { TextureLayer } from "../base/TextureLayer";
import { loadImage } from "../base/utils";
import AudioPlayer, { AudioType } from "./Audio";
import { AreaGroup, AreaGroups, Color, Settings } from "./common";
import {
  FillerConfig,
  FillerData,
  FillerResource,
  FillerCallback,
} from "./FillerData";
import { FillerScene } from "./FillerScene";
import { HintLayer } from "./HintLayer";
import { LineArtLayer } from "./LineArtLayer";
import { NumberLayer } from "./NumberLayer";
import { WorkLayer } from "./WorkLayer";
import { LoadingController } from "./LoadingController";
import { FingerHint } from "./FingerHint";
import JSConfetti from "js-confetti";
import { initCta, ctaHighlight } from "./cta";
import { adPlatform } from "./ad-platform/current";
import { adAssets, adTheme } from "#ad-config";

window.addEventListener("load", () => {
  document.body.dataset.adPlatform = adPlatform.platform;
  adPlatform.init();
  initCta(adPlatform);
  init();
});

async function test() {
  let canvas = document.querySelector("#canvas") as HTMLCanvasElement;
  canvas.width = canvas.clientWidth * window.devicePixelRatio;
  canvas.height = canvas.clientHeight * window.devicePixelRatio;
  let resource = await loadResource();
  let ctx = canvas.getContext("2d")!;
  ctx.fillStyle = "red";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  ctx.drawImage(resource.page, 0, 0);
}

async function init() {
  // 应用主题
  const root = document.documentElement;
  root.style.setProperty("--ad-bg-gradient", adTheme.bgGradient);
  root.style.setProperty("--ad-cta-gradient", adTheme.ctaGradient);

  // CTA 光晕颜色 → RGB 分量（CSS 变量供 rgba() 使用）
  const glowHex = adTheme.ctaGlowColor || "#ff5f1f";
  root.style.setProperty("--cta-glow-r", parseInt(glowHex.slice(1, 3), 16));
  root.style.setProperty("--cta-glow-g", parseInt(glowHex.slice(3, 5), 16));
  root.style.setProperty("--cta-glow-b", parseInt(glowHex.slice(5, 7), 16));

  // 直接应用 CTA 文案和样式
  const ctaBtn = document.getElementById("cta-btn");
  if (ctaBtn) {
    ctaBtn.textContent = adTheme.ctaText || "PLAY NOW";
    ctaBtn.style.background = adTheme.ctaGradient || ctaBtn.style.background;
  }

  // 应用背景渐变到 body
  document.body.style.background = adTheme.bgGradient;

  const loadingController = new LoadingController({
    minDisplayTime: 1000, // 最小显示时间1秒
    fadeDuration: 300, // 淡出动画300ms
  });

  if (adPlatform.shouldUseCustomLoading()) {
    loadingController.show();
  }

  let canvas = document.querySelector("#canvas") as HTMLCanvasElement;
  let gl = canvas.getContext("webgl2", {
    premultipliedAlpha: false,
  }) as WebGL2RenderingContext;
  let pixelRatio = window.devicePixelRatio;

  /** 根据 game-area 的实际渲染尺寸同步 canvas 像素尺寸 */
  function syncCanvasSize() {
    const gameArea = document.getElementById("game-area")!;
    const w = Math.round(gameArea.clientWidth * pixelRatio);
    const h = Math.round(gameArea.clientHeight * pixelRatio);
    if (canvas.width !== w || canvas.height !== h) {
      canvas.width = w;
      canvas.height = h;
      scene?.updateViewport();
    }
  }

  canvas.width = canvas.clientWidth * pixelRatio;
  canvas.height = canvas.clientHeight * pixelRatio;
  let scene = new FillerScene(gl, pixelRatio);

  // 确保 canvas 像素尺寸与实际 flex 布局一致（body.onload 时 dvh 可能还未最终结算）
  syncCanvasSize();

  let audio = new AudioPlayer();

  // 加载设置项，学个新语法 ...
  let settings: Settings = {
    hintStyle: "default",
    sound: true,
    vibrate: true,
    autoNext: true,
  };

  window.addEventListener("resize", () => syncCanvasSize());

  let resource = await loadResource();

  if (adPlatform.shouldUseCustomLoading()) {
    loadingController.hide();
  }
  adPlatform.onResourcesLoaded();

  // 设置固定顶栏 logo（图标 + 文字）
  (document.getElementById("app-logo") as HTMLImageElement).src =
    adAssets.logoUrl;
  (document.getElementById("app-logo-txt") as HTMLImageElement).src =
    adAssets.logoTxtUrl;

  // 预加载 promo 图片，避免动画播放时图片刚加载导致布局跳变
  (document.getElementById("promo-coloring") as HTMLImageElement).src =
    adAssets.coloringPagesUrl;
  (document.getElementById("promo-slogon") as HTMLImageElement).src =
    adAssets.slogonUrl;

  let taskList: number[] = [];

  // fingerHint 先声明，init 末尾赋值后回调中就能使用
  let fingerHint: FingerHint | null = null;

  let fillerData = new FillerData(
    new FillerConfig(settings),
    resource,
    gl,
    taskList,
    {
      onFillFailed() {
        adPlatform.onGameStart();
        console.log("填充失败");
        fingerHint?.onUserInteraction();
      },
      onFillSuccess() {
        adPlatform.onGameStart();
        console.log("填充成功");
        fingerHint?.onUserInteraction();
        if (fillerData.config.settings.vibrate) {
          vibrate();
        }
        cssAdjustProgress(fillerData.data.coloredPercent);
        cssSetColorProgress(
          fillerData.currentGroupIndex,
          fillerData.currentGroup!.progressPercent,
        );
        if (fillerData.currentGroup?.isAllColored) {
          if (fillerData.config.settings.sound) {
            audio.playAudio(AudioType.ColorDone);
          }
          cssColorDone(fillerData);
        }
      },
      onSwitchGroup() {
        let currentGroupIndex = fillerData.currentGroupIndex;
        console.log(`切换到下一个group ${currentGroupIndex}`);
        cssSelectColor(currentGroupIndex);
        cssAdjustScroll(fillerData);
      },
      onFinish() {
        fingerHint?.stop();
        adPlatform.onGameEnd();
        cssOnFinish(scene, workLayer, hintLayer, numberLayer, audio);
      },
    },
  );

  scene.fillerData = fillerData;

  console.log("resource", resource);

  // canvas 区域与所有 UI 完全分离，只保留极小视觉边距
  scene.setContentPadding(new Padding(20, 20, 20, 20));

  //let page = await loadImage('/webgl/page.png')
  //let page = await loadImage('/assets/resources/friend/page_gray.png')

  let width = fillerData.width;
  let height = fillerData.height;
  scene.setContentSize(width, height);

  // // 最底层：透明背景，canvas 透出 body 渐变色，与整体 UI 融为一体
  // scene.addLayer(new BackgroundLayer(scene, scene.width, scene.height, [0, 0, 0, 0]));

  if (resource.bg) {
    scene.addLayer(
      new BgLayer(scene, resource.bg, scene.width, scene.height, BgType.Repeat),
    );
  }
  scene.addLayer(new BoxLayer(scene, 0, 0, width, height));

  let hintLayer = new HintLayer(scene, fillerData);
  scene.addLayer(hintLayer);

  let numberLayer = new NumberLayer(scene, resource.numberImage, fillerData, 1);
  scene.addLayer(numberLayer);

  let workLayer = new WorkLayer(scene, fillerData);

  scene.addLayer(workLayer);

  //scene.addLayer(new TextureLayer(scene, workLayer.mask.texture, fillerData.width, fillerData.height, fillerData.width, fillerData.height))

  scene.addLayer(new LineArtLayer(scene, resource.page, width, height));

  // scene.addLayer(
  //   new BorderLayer(
  //     scene,
  //     0,
  //     0,
  //     fillerData.width,
  //     fillerData.height,
  //     0xff222222,
  //   ),
  // );

  // let mask = new Mask(gl, fillerData)
  // resource.config[0].areas.forEach(area => mask.addArea(area))
  // mask.flush()

  //scene.addTestLayer(new TextureLayer(scene, mask.texture, fillerData.width, fillerData.height, width, height, ImageShaders.CommonGaussianBlurCut))
  //scene.addTestLayer(new TextureLayer(scene, mask.texture, fillerData.width, fillerData.height, width, height, ))

  //scene.addLayer(new TextureLayer(scene, hintLayer.mask.texture, fillerData.width, fillerData.height, width, height, ImageShaders.CommonGaussianBlur  ))
  //scene.addLayer(new DebugLayer(scene))

  //scene.addLayer(new ImageLayer(scene, resource.page, width, height, gl.LINEAR, ImageShaders.CommonGaussianBlur))
  //scene.addLayer(new TextureLayer(scene, fillerData.mapTexure, width, height, width, height))

  createButtons(fillerData);
  cssAdjustProgress(fillerData.data.coloredPercent);

  workLayer.initTask();

  if (fillerData.data.coloredPercent >= 100) {
    adPlatform.onGameEnd();
    cssOnFinish(scene, workLayer, hintLayer, numberLayer, null);
  } else {
    // 创建手指提示，全图未完成时启动引导
    fingerHint = new FingerHint(scene, fillerData, adAssets.fingerUrl);
    // 监听 group 切换，确保手指提示立即指向新颜色区块
    fillerData.addListener(fingerHint);
    fingerHint.start();
  }
}

async function loadResource(): Promise<FillerResource> {
  const config = JSON.parse(adAssets.configRaw) as AreaGroups;
  const [page, map, numberImage] = await Promise.all([
    loadImage(adAssets.pageUrl),
    loadImage(adAssets.mapUrl),
    loadImage(adAssets.numberFontUrl),
  ]);

  // special 图是可选的：用户可能未上传，平台生成的配置可能不含此字段
  let special: HTMLImageElement | undefined;
  if ("specialUrl" in adAssets && adAssets.specialUrl) {
    try {
      special = await loadImage(adAssets.specialUrl);
    } catch {
      // 加载失败时回退到程序化着色纹理
    }
  }

  return new FillerResource(
    config,
    page as HTMLImageElement,
    map as HTMLImageElement,
    numberImage as HTMLImageElement,
    [],
    special,
  );
}

function createButtons(fillerData: FillerData) {
  let data = fillerData.data.areaGroups;
  let htmlUndoned = [];
  let htmlDone = [];
  let html = [];
  let areaGroup: AreaGroup;
  let color: Color;
  for (var i = 0; i < data.length; i++) {
    areaGroup = data[i];
    color = new Color(areaGroup.color);
    if (areaGroup.isAllColored) {
      htmlDone.push(
        `<div id="color-btn-container-${i}" class="color-btn-container color-btn-done">`,
      );
      htmlDone.push(
        `<svg id="color-btn-progress-ring-${i}" class="color-btn-progress-ring" viewBox="0 0 48 48"><circle class="color-btn-progress-ring-track" cx="50%" cy="50%" r="45%" fill="transparent" stroke="#fff" stroke-width="5%" /> <circle id="color-btn-progress-ring-value-${i}" class="color-btn-progress-ring-value" cx="50%" cy="50%" r="45%" fill="transparent" stroke="#2ecc71" stroke-width="5%" stroke-linecap="round" /></svg>`,
      );
      htmlDone.push(
        `<div id="color-btn-${i}" class="color-btn" style="background-color:${color.css()}; color: ${color.gray < 192 ? "white" : "black"}">`,
      );
      htmlDone.push(`✓`);
      htmlDone.push(`</div>`);
      htmlDone.push(`</div>`);
    } else {
      if (
        areaGroup === fillerData.currentGroup ||
        areaGroup.progressPercent > 0.0
      ) {
      } // 需要展示circle progress
      htmlUndoned.push(
        `<div id="color-btn-container-${i}" class="color-btn-container" onclick="selectColor(this, event, ${i})">`,
      );
      htmlUndoned.push(
        `<svg id="color-btn-progress-ring-${i}" class="color-btn-progress-ring" viewBox="0 0 48 48"><circle class="color-btn-progress-ring-track" cx="50%" cy="50%" r="45%" fill="transparent" stroke="#fff" stroke-width="5%" /> <circle id="color-btn-progress-ring-value-${i}" class="color-btn-progress-ring-value" cx="50%" cy="50%" r="45%" fill="transparent" stroke="#2ecc71" stroke-width="5%" stroke-linecap="round" /></svg>`,
      );
      htmlUndoned.push(
        `<div id="color-btn-${i}" class="color-btn" style="background-color:${color.css()}; color: ${color.gray < 192 ? "white" : "black"}">`,
      );
      htmlUndoned.push(`${i + 1}`);
      htmlUndoned.push(`</div>`);
      htmlUndoned.push(`</div>`);
    }
  }
  html = htmlUndoned.concat(htmlDone);
  let c = document.querySelector("#color-btns");
  if (c != null) {
    c.innerHTML = html.join("");
  }

  // 选中当前color
  cssSelectColor(fillerData.currentGroupIndex);

  // 调整每个color item的进度
  for (var i = 0; i < data.length; i++) {
    let areaGroup = data[i];
    let percent = areaGroup.progressPercent;
    cssInitColorProgress(i, percent);
  }

  (window as any).selectColor = function (
    el: HTMLElement,
    event: MouseEvent,
    i: number,
  ) {
    console.log("select", el, event, i);
    // 已完成的颜色不可点击
    if (fillerData.data.areaGroups[i].isAllColored) return;
    fillerData.setCurrentGroup(i);
    document.querySelectorAll(".color-btn-container").forEach((item) => {
      item.classList.remove("color-btn-container-selected");
    });
    el.classList.add("color-btn-container-selected");
  };
}

/**
 * 调整整体完成进度条（已移除，保留接口兼容）
 */
function cssAdjustProgress(_percent: number) {
  // progress bar removed — no-op
}

// 选中某个color, 自动切换到下一个颜色的时候触发调用
function cssSelectColor(i: number) {
  document.querySelectorAll(".color-btn-container").forEach((item) => {
    item.classList.remove("color-btn-container-selected");
  });
  let elem = document.getElementById(`color-btn-container-${i}`);
  elem?.classList.add("color-btn-container-selected");
}

// 设置color button的进度，即areagroup的进度
// SVG viewBox 常量，所有strokeDasharray/offset计算均在此坐标系内
const COLOR_BTN_VIEWBOX = 48;
const COLOR_BTN_RING_RATIO = 0.45;
const COLOR_BTN_RADIUS = COLOR_BTN_VIEWBOX * COLOR_BTN_RING_RATIO; // 21.6
const COLOR_BTN_CIRCUMFERENCE = 2 * Math.PI * COLOR_BTN_RADIUS;

function cssSetColorProgress(i: number, percent: number) {
  const progressCircle = document.getElementById(
    `color-btn-progress-ring-value-${i}`,
  )!;

  const offset =
    COLOR_BTN_CIRCUMFERENCE - (percent * COLOR_BTN_CIRCUMFERENCE) / 100;
  progressCircle.style.strokeDashoffset = offset.toString();

  if (percent >= 100) {
    // 如果此color已经完成，文本变为✓, 同时移动到队列后面
    const item = document.getElementById(`color-btn-${i}`)!;
    item.innerText = "✓";
  }
}

// 初始化color button进度
function cssInitColorProgress(i: number, percent: number) {
  const progressCircle = document.getElementById(
    `color-btn-progress-ring-value-${i}`,
  )!;

  const offset =
    COLOR_BTN_CIRCUMFERENCE - (percent * COLOR_BTN_CIRCUMFERENCE) / 100;
  progressCircle.style.strokeDasharray = `${COLOR_BTN_CIRCUMFERENCE} ${COLOR_BTN_CIRCUMFERENCE}`;
  progressCircle.style.strokeDashoffset = offset.toString();
}

// 调整滚动条，将当前颜色按钮居中
function cssAdjustScroll(fd: FillerData) {
  let wrapper = document.getElementById("color-btns")!;
  let itemWidth = wrapper.scrollWidth / fd.data.areaGroups.length;
  let scrollpos =
    itemWidth * fd.currentGroupIndex + itemWidth / 2 - wrapper.clientWidth / 2;
  scrollpos = Math.max(0, scrollpos);
  try {
    wrapper.scroll({ left: scrollpos, top: 0, behavior: "smooth" });
  } catch (e) {
    wrapper.scrollLeft = scrollpos;
  }
}

// 某个颜色填充完毕
function cssColorDone(fillerData: FillerData) {
  let i = fillerData.currentGroupIndex;
  // 标记完成状态，不做爆破动画，不移动位置
  const buttonWrap = document.getElementById(`color-btn-container-${i}`)!;
  buttonWrap.classList.add("color-btn-done");
  buttonWrap.onclick = null;
}

// 全部填完
function cssOnFinish(
  scene: FillerScene,
  workLayer: WorkLayer,
  hintLayer: HintLayer,
  numberLayer: NumberLayer,
  audio: AudioPlayer | null,
) {
  // 立即将 canvas 底色改为透明，让 body 渐变色从绘图区域透出，避免 replay/消失动画中出现局部白色块
  scene.setClearTransparent();

  // 隐藏toolbar
  const toolbarBottom = document.getElementById(
    "toolbar-bottom",
  ) as HTMLDivElement;
  // 爆破动画结束后隐藏元素
  setTimeout(() => {
    if (scene.fillerData!.config.settings.sound) {
      audio?.playAudio(AudioType.AllDone);
    }
    scene.resetToResult();
    toolbarBottom.classList.add("hidden-toolbar-bottom"); // 添加 hidden 类，触发动画
    // 动画结束后隐藏元素
    setTimeout(() => {
      // toolbarBottom.style.display = 'none';
      const lw = adTheme.frameLineWidth || 16;
      const offset = lw / 4;
      scene.addLayer(
        new FrameLayer(
          scene,
          -offset,
          -offset,
          scene.fillerData!.width + offset * 2,
          scene.fillerData!.height + offset * 2,
          cssHexToFrameColor(adTheme.frameColor || "#edce9b"),
          lw,
        ),
      );
      hintLayer.enabled = false; // replay 期间隐藏 hint 覆盖层
      numberLayer.enabled = false; // replay 期间隐藏 number 覆盖层
      scene.invalidate();
      workLayer.replay().then(() => showPromoScreen());
    }, 500); // 过渡动画持续 0.5 秒
  }, 300); // 粒子爆破动画持续 0.3 秒

  setTimeout(() => {
    confetti();
  }, 300);
}

function showPromoScreen() {
  const canvas = document.getElementById("canvas") as HTMLCanvasElement;
  const promoScreen = document.getElementById("promo-screen") as HTMLDivElement;
  const promoColoring = document.getElementById(
    "promo-coloring",
  ) as HTMLImageElement;
  const promoSlogon = document.getElementById(
    "promo-slogon",
  ) as HTMLImageElement;

  // 预设图片资源（已在 init 阶段预加载，此处保留赋值保证兼容性）
  promoColoring.src = adAssets.coloringPagesUrl;
  promoSlogon.src = adAssets.slogonUrl;

  // 1. 将画布缩小至消失
  canvas.classList.add("canvas-shrink-out");

  // 2. canvas 过渡完成后（~600ms）展示宣传界面 + logo 淡入
  setTimeout(() => {
    canvas.style.display = "none";
    promoScreen.classList.add("visible");
    // 双 rAF：确保浏览器渲染初始态后再触发 transition
    requestAnimationFrame(() => {
      requestAnimationFrame(() => {
        promoColoring.classList.add("animate-in");
        promoSlogon.classList.add("animate-in");
        // 宣传界面出现后强化 CTA 按钮
        ctaHighlight();
      });
    });
  }, 620);
}

function onHint(audio: AudioPlayer, scene: FillerScene) {
  if (scene.fillerData?.config.settings.sound) {
    audio.playAudio(AudioType.Hint);
  }
  scene.hint();
}

function goback() {
  if (document.referrer.includes(window.location.hostname)) {
    window.history.back();
  } else {
    window.location.href = "/"; // 无来源时跳首页
  }
}

function vibrate() {
  // 判断浏览器是否支持震动
  var supportVibrate = "vibrate" in navigator;
  console.log("supportVibrate: " + supportVibrate);
  if (supportVibrate) {
    navigator.vibrate(30);
  }
}

function showToast(message: string) {
  const toast = document.getElementById("toast");
  if (toast) {
    toast.textContent = message;
    toast.classList.remove("toast-hidden");
    setTimeout(() => toast.classList.add("toast-hidden"), 2500);
  }
}

// 撒花动画，使用js-confetti库
/** CSS hex (#RRGGBB) → FrameLayer 颜色值 (0xAABBGGRR little-endian) */
function cssHexToFrameColor(hex: string): number {
  const r = parseInt(hex.slice(1, 3), 16);
  const g = parseInt(hex.slice(3, 5), 16);
  const b = parseInt(hex.slice(5, 7), 16);
  return (0xff << 24) | (b << 16) | (g << 8) | r;
}

function confetti() {
  const jsConfetti = new JSConfetti();
  jsConfetti.addConfetti({ confettiNumber: 80 });
}

function onActionSheetClick(evt: Event) {
  evt.stopPropagation();
}
