import { customElement, noShadowDOM } from "solid-element";
import { createSignal, onMount } from "solid-js";

export interface DiceProps {
  key?: string;
}

interface RollResult {
  total: number;
  rolls: number[];
  detail: string;
}

function rollDice(formula: string): RollResult {
  const allRolls: number[] = [];
  let total = 0;
  const details: string[] = [];

  // 解析骰子公式，支持 + 和 - 运算符
  // 先按 + 和 - 分割，但保留运算符
  const tokens = formula
    .split(/([+-])/)
    .map((t) => t.trim())
    .filter((t) => t.length > 0);

  let sign = 1;

  for (let i = 0; i < tokens.length; i++) {
    const token = tokens[i];

    if (token === "+") {
      sign = 1;
      continue;
    }
    if (token === "-") {
      sign = -1;
      continue;
    }

    // 处理 kh/kl/dh/dl 运算符
    let processedToken = token;
    let keepHigh = false;
    let keepLow = false;
    let dropHigh = false;
    let dropLow = false;
    let keepCount = 0;
    let dropCount = 0;

    const khMatch = token.match(/^(.+?)kh(\d+)$/i);
    const klMatch = token.match(/^(.+?)kl(\d+)$/i);
    const dhMatch = token.match(/^(.+?)dh(\d+)$/i);
    const dlMatch = token.match(/^(.+?)dl(\d+)$/i);

    if (khMatch) {
      processedToken = khMatch[1];
      keepHigh = true;
      keepCount = parseInt(khMatch[2]);
    } else if (klMatch) {
      processedToken = klMatch[1];
      keepLow = true;
      keepCount = parseInt(klMatch[2]);
    } else if (dhMatch) {
      processedToken = dhMatch[1];
      dropHigh = true;
      dropCount = parseInt(dhMatch[2]);
    } else if (dlMatch) {
      processedToken = dlMatch[1];
      dropLow = true;
      dropCount = parseInt(dlMatch[2]);
    }

    const match = processedToken.match(/^(\d+)?d(\d+)$/i);
    if (match) {
      const count = parseInt(match[1] || "1");
      const sides = parseInt(match[2]);
      const rolls: number[] = [];

      for (let j = 0; j < count; j++) {
        rolls.push(Math.floor(Math.random() * sides) + 1);
      }

      let processedRolls = [...rolls];
      let detail = `${count}d${sides}`;

      // 处理 keep/drop 运算符
      if (keepHigh || keepLow || dropHigh || dropLow) {
        const sorted = [...processedRolls].sort((a, b) => a - b);

        if (dropHigh && dropCount > 0) {
          processedRolls = sorted.slice(0, sorted.length - dropCount);
          detail += `d${dropCount}h`;
        } else if (dropLow && dropCount > 0) {
          processedRolls = sorted.slice(dropCount);
          detail += `d${dropCount}l`;
        } else if (keepHigh && keepCount > 0) {
          processedRolls = sorted.slice(-keepCount);
          detail += `kh${keepCount}`;
        } else if (keepLow && keepCount > 0) {
          processedRolls = sorted.slice(0, keepCount);
          detail += `kl${keepCount}`;
        }
      }

      const partTotal = processedRolls.reduce((a, b) => a + b, 0);
      total += sign * partTotal;
      allRolls.push(...processedRolls);
      details.push(
        `${detail}=[${processedRolls.join(",")}]${sign < 0 ? " (负)" : ""}`,
      );
    } else {
      // 处理固定数字
      const num = parseInt(token);
      if (!isNaN(num)) {
        total += sign * num;
        details.push(`${num}${sign < 0 ? " (负)" : ""}`);
      }
    }
  }

  return {
    total,
    rolls: allRolls,
    detail: details.join(" + "),
  };
}

// 从 URL 参数获取骰子结果
function getDiceResultFromUrl(key: string): number | null {
  if (typeof window === "undefined") return null;
  const params = new URLSearchParams(window.location.search);
  const value = params.get(`dice-${key}`);
  return value ? parseInt(value) : null;
}

function setDiceResultToUrl(key: string, value: number | null) {
  if (typeof window === "undefined") return;
  const params = new URLSearchParams(window.location.search);
  if (value === null) {
    params.delete(`dice-${key}`);
  } else {
    params.set(`dice-${key}`, value.toString());
  }
  const newUrl = `${window.location.pathname}${params.toString() ? `?${params.toString()}` : ""}${window.location.hash}`;
  window.history.pushState({}, "", newUrl);
}

customElement("md-dice", { key: "" }, (props, { element }) => {
  noShadowDOM();
  const [result, setResult] = createSignal<number | null>(null);
  const [isRolled, setIsRolled] = createSignal(false);
  const [rollDetail, setRollDetail] = createSignal<string>("");

  // 从 element 的 textContent 获取骰子公式
  const formula = element?.textContent?.trim() || "";
  
  // 隐藏原始文本内容
  if (element) {
    element.textContent = "";
  }

  // 使用的 key（如果没有提供则使用生成的 ID）
  const effectiveKey = () => props.key;

  onMount(() => {
    // 初始化时检查 URL 参数
    if (effectiveKey()) {
      const urlResult = getDiceResultFromUrl(effectiveKey());
      if (urlResult !== null) {
        setResult(urlResult);
        setIsRolled(true);
      }
    }
  });

  const handleRoll = () => {
    // 点击骰子图标：总是重 roll
    const rollResult = rollDice(formula);
    setResult(rollResult.total);
    setRollDetail(rollResult.detail);
    setIsRolled(true);
    if (effectiveKey()) {
      setDiceResultToUrl(effectiveKey(), rollResult.total);
    }
  };

  const handleTextClick = () => {
    // 点击文本：总是重置为公式
    setResult(null);
    setIsRolled(false);
    setRollDetail("");
    if (effectiveKey()) {
      setDiceResultToUrl(effectiveKey(), null);
    }
  };

  const displayText = () => (isRolled() ? `${result()}` : formula);

  return (
    <span class="inline-flex items-center px-1">
      <span
        onClick={(e) => {
          e.preventDefault();
          handleRoll();
        }}
        class="text-blue-600 hover:text-blue-800 cursor-pointer"
        title={rollDetail() || "掷骰子"}
      >
        🎲
      </span>
      <a
        onClick={handleTextClick}
        class="cursor-pointer text-gray-700 hover:text-gray-900"
        title={isRolled() ? "点击重置为公式" : formula}
      >
        {displayText()}
      </a>
    </span>
  );
});
