import { tryBuyLabEgg } from "./zoo.js";
import { GameConfig } from "./config.js";
import { eggTypeLabel, errorMessage, t } from "./texts-fr.js";

const EGG_EMOJI = "🥚";

/**
 * @param {{ state: import("./types.js").GameState, setError: (s: string) => void, playSound: (s: string) => void, setState: () => void, pendingTokenByEggType: Record<string, number> }} ctx
 * @param {{ eggType: string }} labOffer
 * @param {boolean} ok
 * @param {{ tokenId?: number } | string} result
 */
function handleLabOfferClick(ctx, labOffer, ok, result) {
  if (!ok) {
    const msg = errorMessage[result] ?? result;
    ctx.setError(String(t.buyFailed).replace("%s", msg));
    ctx.playSound("error");
    ctx.setState();
    return;
  }
  ctx.setError("");
  ctx.playSound("buy");
  ctx.pendingTokenByEggType[labOffer.eggType] = result.tokenId;
  ctx.setState();
}

/**
 * @param {{ eggType: string, price: number }} labOffer
 * @param {{ state: import("./types.js").GameState, setState: () => void, setError: (s: string) => void, playSound: (s: string) => void, pendingTokenByEggType: Record<string, number> }} ctx
 * @returns {HTMLElement}
 */
function createLabOfferButton(labOffer, ctx) {
  const { state } = ctx;
  const el = document.createElement("div");
  el.className = "offer-btn world-map-offer world-map-offer-single world-map-lab-offer";
  el.setAttribute("role", "button");
  el.setAttribute("tabindex", "0");
  el.setAttribute("draggable", "true");
  const name = eggTypeLabel[labOffer.eggType] ?? labOffer.eggType;
  el.innerHTML = `<span class="offer-emoji">${EGG_EMOJI}</span><span class="offer-label">${name}</span><span class="offer-price">${labOffer.price} pièces</span>`;
  let dragStarted = false;
  el.addEventListener("dragstart", (e) => {
    dragStarted = true;
    e.dataTransfer.setData("application/x-builazoo-eggtype", labOffer.eggType);
    e.dataTransfer.effectAllowed = "copy";
    el.classList.add("dragging");
  });
  el.addEventListener("dragend", () => { dragStarted = false; el.classList.remove("dragging"); });
  el.addEventListener("click", () => {
    if (dragStarted) return;
    const [ok, result] = tryBuyLabEgg(state, labOffer.eggType);
    handleLabOfferClick(ctx, labOffer, ok, result);
  });
  el.addEventListener("keydown", (e) => {
    if (e.key === "Enter" || e.key === " ") { e.preventDefault(); el.click(); }
  });
  return el;
}

/**
 * @param {{ worldMapEl: HTMLElement, state: import("./types.js").GameState, setState: () => void, setError: (s: string) => void, playSound: (s: string) => void, pendingTokenByEggType: Record<string, number> }} ctx
 */
export function renderLab(ctx) {
  const lab = GameConfig.WorldMap?.Laboratory;
  if (!lab) return;
  const { state, worldMapEl } = ctx;
  const labNode = document.createElement("div");
  labNode.className = "world-map-lab";
  labNode.style.left = `${lab.x}%`;
  labNode.style.top = `${lab.y}%`;
  labNode.dataset.poi = "laboratory";
  const labNameEl = document.createElement("div");
  labNameEl.className = "world-map-zoo-name";
  labNameEl.textContent = lab.name ?? "Laboratoire";
  labNode.appendChild(labNameEl);
  const labSlotEl = document.createElement("div");
  labSlotEl.className = "world-map-zoo-slot";
  const labOffer = state.laboratoryOffer;
  if (labOffer) {
    labSlotEl.appendChild(createLabOfferButton(labOffer, ctx));
  } else {
    const iconEl = document.createElement("span");
    iconEl.className = "world-map-zoo-icon";
    iconEl.setAttribute("aria-hidden", "true");
    iconEl.textContent = "🔬";
    labSlotEl.appendChild(iconEl);
  }
  labNode.appendChild(labSlotEl);
  worldMapEl.appendChild(labNode);
}

/**
 * @param {{ worldMapTruckEl: HTMLElement, state: import("./types.js").GameState, setState: () => void }} ctx
 * @param {Array<import("./types.js").WorldZoo>} zoos
 * @param {number} truckMs
 * @returns {boolean} true if truck was updated (need setTimeout)
 */
function updateTruckSale(ctx, zoos, truckMs) {
  const { worldMapTruckEl, state, setState } = ctx;
  const truckSale = state.truckSale;
  if (!truckSale || !truckSale.toZooId) return false;
  const elapsed = Date.now() - (truckSale.startAt || 0);
  if (elapsed >= truckMs) {
    delete state.truckSale;
    return false;
  }
  const fromZoo = zoos.find((z) => z.id === "player");
  const toZoo = zoos.find((z) => z.id === truckSale.toZooId);
  if (!fromZoo || !toZoo) return false;
  const progress = elapsed / truckMs;
  const x = fromZoo.x + (toZoo.x - fromZoo.x) * progress;
  const y = fromZoo.y + (toZoo.y - fromZoo.y) * progress;
  worldMapTruckEl.style.display = "block";
  worldMapTruckEl.style.left = `${x}%`;
  worldMapTruckEl.style.top = `${y}%`;
  worldMapTruckEl.textContent = "🚚";
  setTimeout(setState, 50);
  return true;
}

/**
 * @param {{ worldMapTruckEl: HTMLElement, state: import("./types.js").GameState, setState: () => void }} ctx
 * @param {Array<import("./types.js").WorldZoo>} zoos
 * @param {number} truckMs
 * @returns {boolean} true if truck was updated (need setTimeout)
 */
function updateEggPurchaseTruck(ctx, zoos, truckMs) {
  const { worldMapTruckEl, state, setState } = ctx;
  const eggPurchase = state.eggPurchaseTruck;
  const truckLevel = state.truckLevel ?? 1;
  if (!eggPurchase || !eggPurchase.startAt) return false;
  const durationMs = Math.max(1000, (truckMs * 2) / truckLevel);
  const elapsed = Date.now() - eggPurchase.startAt;
  if (elapsed >= durationMs) {
    delete state.eggPurchaseTruck;
    worldMapTruckEl.style.display = "none";
    return false;
  }
  const fromZoo = zoos.find((z) => z.id === eggPurchase.fromZooId);
  const toZoo = zoos.find((z) => z.id === eggPurchase.toZooId);
  if (!fromZoo || !toZoo) return false;
  const progress = elapsed / durationMs;
  const leg = progress < 0.5 ? progress * 2 : (progress - 0.5) * 2;
  const x = progress < 0.5
    ? fromZoo.x + (toZoo.x - fromZoo.x) * leg
    : toZoo.x + (fromZoo.x - toZoo.x) * leg;
  const y = progress < 0.5
    ? fromZoo.y + (toZoo.y - fromZoo.y) * leg
    : toZoo.y + (fromZoo.y - toZoo.y) * leg;
  worldMapTruckEl.style.display = "block";
  worldMapTruckEl.style.left = `${x}%`;
  worldMapTruckEl.style.top = `${y}%`;
  worldMapTruckEl.textContent = "🚚";
  setTimeout(setState, 50);
  return true;
}

/**
 * @param {{ worldMapTruckEl: HTMLElement, worldMapNpcTrucksEl: HTMLElement, state: import("./types.js").GameState, setState: () => void }} ctx
 * @param {Array<import("./types.js").WorldZoo>} zoos
 */
function updatePlayerTruck(ctx, zoos) {
  const { worldMapTruckEl } = ctx;
  const truckMs = (GameConfig.WorldMap && GameConfig.WorldMap.TruckAnimationMs) || 2500;
  if (updateTruckSale(ctx, zoos, truckMs)) return;
  if (updateEggPurchaseTruck(ctx, zoos, truckMs)) return;
  worldMapTruckEl.style.display = "none";
}

/**
 * @param {{ worldMapNpcTrucksEl: HTMLElement, state: import("./types.js").GameState, setState: () => void }} ctx
 * @param {Array<import("./types.js").WorldZoo>} zoos
 * @param {number} truckMs
 */
function renderNpcTrucks(ctx, zoos, truckMs) {
  const { worldMapNpcTrucksEl, state } = ctx;
  worldMapNpcTrucksEl.innerHTML = "";
  const npcTrucks = state.worldTruckSales ?? [];
  for (const truck of npcTrucks) {
    const fromZoo = zoos.find((z) => z.id === truck.fromZooId);
    const toZoo = zoos.find((z) => z.id === truck.toZooId);
    if (fromZoo && toZoo) {
      const elapsed = Date.now() - (truck.startAt || 0);
      if (elapsed < truckMs) {
        const progress = elapsed / truckMs;
        const x = fromZoo.x + (toZoo.x - fromZoo.x) * progress;
        const y = fromZoo.y + (toZoo.y - fromZoo.y) * progress;
        const truckDiv = document.createElement("div");
        truckDiv.className = "world-map-truck world-map-truck-npc";
        truckDiv.style.left = `${x}%`;
        truckDiv.style.top = `${y}%`;
        truckDiv.textContent = "🚚";
        worldMapNpcTrucksEl.appendChild(truckDiv);
      }
    }
  }
}

/**
 * @param {{ worldMapEl: HTMLElement, worldMapTruckEl: HTMLElement, worldMapNpcTrucksEl: HTMLElement, state: import("./types.js").GameState, setState: () => void }} ctx
 * @param {Array<import("./types.js").WorldZoo>} zoos
 */
export function renderTruckAndNpcTrucks(ctx, zoos) {
  const truckMs = (GameConfig.WorldMap && GameConfig.WorldMap.TruckAnimationMs) || 2500;
  const truckSale = ctx.state.truckSale;
  const eggPurchase = ctx.state.eggPurchaseTruck;
  updatePlayerTruck(ctx, zoos);
  renderNpcTrucks(ctx, zoos, truckMs);
  const npcTrucks = ctx.state.worldTruckSales ?? [];
  if (npcTrucks.length > 0 || (truckSale && truckSale.toZooId) || (eggPurchase && eggPurchase.startAt)) {
    setTimeout(ctx.setState, 50);
  }
}
