/**
 * StatsView — table view of all stat key-value pairs.
 *
 * Groups stats by scope (global, then per-player). Shows computed values
 * (base + modifiers) and inline roll buttons for stats with roll/table/formula.
 */

import { Component, For, createMemo, Show } from "solid-js";
import { useJournalStream } from "../stores/journalStream";
import { useJournalCompletions } from "./completions";
import { fullKey, modifierLabel } from "./stat-helpers";
import type { StatDef } from "./completions";

export const StatsView: Component = () => {
  const stream = useJournalStream();
  const comp = useJournalCompletions();

  const statDefs = createMemo(() => comp.data.stats);
  const values = createMemo(() => stream.stats);

  /** Build a lookup: fullKey -> StatDef */
  const defMap = createMemo(() => {
    const map = new Map<string, StatDef>();
    for (const def of statDefs()) {
      const fk = fullKey(def, stream.myName);
      map.set(fk, def);
    }
    return map;
  });

  /** Compute the effective value of a stat (base + modifiers) */
  function computedValue(key: string): string {
    const def = defMap().get(key);
    if (!def) return values()[key] ?? "";

    const base = values()[key] ?? def.default ?? "";
    const baseNum = parseFloat(base);

    if (def.type === "number" || def.type === "derived") {
      // Sum modifiers that target this key (fullKey matching)
      const modKeys: string[] = [];
      for (const [fk, d] of defMap()) {
        if (
          d.type === "modifier" &&
          d.target &&
          fullKeyTarget(d.target, d, def)
        ) {
          modKeys.push(fk);
        }
      }
      let total = isNaN(baseNum) ? 0 : baseNum;
      for (const mk of modKeys) {
        const mv = parseFloat(values()[mk] ?? defMap().get(mk)?.default ?? "0");
        if (!isNaN(mv)) total += mv;
      }
      return String(total);
    }

    return base || "—";
  }

  /** Check if a modifier's target matches a given def (scoped correctly). */
  function fullKeyTarget(
    target: string,
    modDef: StatDef,
    targetDef: StatDef,
  ): boolean {
    if (modDef.scope === targetDef.scope) {
      return (
        fullKey({ ...modDef, key: target }, stream.myName) ===
        fullKey(targetDef, stream.myName)
      );
    }
    return false;
  }

  /** Group stats by scope */
  const groups = createMemo(() => {
    const result: {
      scope: string;
      label: string;
      entries: { fullKey: string; def: StatDef }[];
    }[] = [];
    const globalEntries: { fullKey: string; def: StatDef }[] = [];
    const playerEntries: { fullKey: string; def: StatDef }[] = [];

    for (const def of statDefs()) {
      const fk = fullKey(def, stream.myName);
      if (def.scope === "global") {
        globalEntries.push({ fullKey: fk, def });
      } else {
        playerEntries.push({ fullKey: fk, def });
      }
    }

    if (globalEntries.length > 0) {
      result.push({ scope: "global", label: "全局", entries: globalEntries });
    }

    if (playerEntries.length > 0) {
      result.push({
        scope: "player",
        label: `玩家 (${stream.myName})`,
        entries: playerEntries,
      });
    }

    return result;
  });

  return (
    <div class="h-full overflow-y-auto bg-gray-50">
      <Show
        when={statDefs().length > 0}
        fallback={
          <p class="text-center text-gray-400 text-xs py-8">
            暂无属性定义。在文档中使用 ```yaml role=stat 代码块定义属性。
          </p>
        }
      >
        <For each={groups()}>
          {(group) => (
            <div class="mb-3">
              <div class="sticky top-0 bg-gray-100 px-3 py-1.5 border-b border-gray-200">
                <span class="text-xs font-semibold text-gray-600">
                  {group.label}
                </span>
              </div>
              <div class="divide-y divide-gray-100">
                <For each={group.entries}>
                  {({ fullKey: fk, def }) => {
                    const val = () => values()[fk];
                    const comp = () => computedValue(fk);
                    const hasModifiers = () => {
                      for (const [mfk, md] of defMap()) {
                        if (
                          md.type === "modifier" &&
                          md.target &&
                          fullKeyTarget(md.target, md, def)
                        ) {
                          return true;
                        }
                      }
                      return false;
                    };
                    const canRoll = () =>
                      def.roll ||
                      def.formula ||
                      def.type === "enum" ||
                      def.type === "template";

                    return (
                      <div class="flex items-center px-3 py-1.5 hover:bg-white/50 transition-colors">
                        <div class="flex-1 min-w-0 flex items-center gap-1.5">
                          <span class="text-sm text-gray-800 truncate">
                            {modifierLabel(def, statDefs())}
                          </span>
                          <span class="text-[10px] text-gray-400 bg-gray-100 px-1 rounded shrink-0">
                            {def.key}
                          </span>
                          <Show when={def.type === "modifier"}>
                            <span class="text-[10px] text-blue-400 bg-blue-50 px-1 rounded shrink-0">
                              →{def.target}
                            </span>
                          </Show>
                        </div>

                        <div class="flex items-center gap-2 shrink-0">
                          <Show
                            when={val() !== undefined}
                            fallback={
                              <span class="text-sm text-gray-300">
                                {def.default ?? "—"}
                              </span>
                            }
                          >
                            <span class="text-sm font-mono text-gray-700">
                              {val()}
                            </span>
                          </Show>

                          <Show
                            when={
                              hasModifiers() &&
                              comp() !== (val() ?? def.default ?? "")
                            }
                          >
                            <span class="text-xs text-gray-400">
                              = {comp()}
                            </span>
                          </Show>

                          <Show when={canRoll()}>
                            <button
                              class="text-[10px] bg-green-100 text-green-700 hover:bg-green-200 px-1.5 py-0.5 rounded transition-colors"
                              title="掷骰"
                              onClick={() => {
                                const textarea =
                                  document.querySelector<HTMLTextAreaElement>(
                                    "#journal-input-textarea",
                                  );
                                if (textarea) {
                                  const nativeInputValueSetter =
                                    Object.getOwnPropertyDescriptor(
                                      window.HTMLTextAreaElement.prototype,
                                      "value",
                                    )?.set;
                                  nativeInputValueSetter?.call(
                                    textarea,
                                    `/stat roll ${def.key}`,
                                  );
                                  textarea.dispatchEvent(
                                    new Event("input", { bubbles: true }),
                                  );
                                  textarea.focus();
                                }
                              }}
                            >
                              🎲
                            </button>
                          </Show>
                        </div>
                      </div>
                    );
                  }}
                </For>
              </div>
            </div>
          )}
        </For>
      </Show>
    </div>
  );
};
