import { LitElement, html, css } from "lit";
import "./skill-tree-ui.js";

/**
 * CharacterSheet.js
 * The Explorer's Dossier - UI component for viewing and managing an Explorer unit.
 * Combines Stat visualization, Inventory management (Paper Doll), and Skill Tree progression.
 */
export class CharacterSheet extends LitElement {
  static get styles() {
    return css`
      * {
        box-sizing: border-box;
      }
      :host {
        display: block;
        font-family: "Courier New", monospace;
        color: white;
      }

      dialog {
        width: 80vw;
        height: 80vh;
        max-width: 1200px;
        max-height: 900px;
        background: rgba(10, 10, 20, 0.95);
        border: 3px solid #555;
        box-shadow: 0 0 30px rgba(0, 0, 0, 0.8);
        padding: 0;
        margin: auto;
        font-family: inherit;
        color: inherit;
      }

      dialog::backdrop {
        background: rgba(0, 0, 0, 0.7);
        backdrop-filter: blur(4px);
      }

      .container {
        display: grid;
        grid-template-columns: 250px 1fr 350px;
        grid-template-rows: auto 1fr;
        grid-template-areas:
          "header header header"
          "stats paper-doll tabs";
        height: 100%;
        width: 100%;
        min-height: 0; /* Allow grid items to shrink below content size */
      }

      /* --- HEADER --- */
      .header {
        grid-area: header;
        display: grid;
        grid-template-columns: 100px 1fr auto;
        align-items: center;
        padding: 15px 20px;
        background: rgba(0, 0, 0, 0.5);
        border-bottom: 2px solid #555;
        gap: 20px;
        height: fit-content;
      }

      .portrait {
        width: 90px;
        height: 90px;
        border: 2px solid #00ffff;
        border-radius: 4px;
        background: rgba(0, 0, 0, 0.8);
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 48px;
        overflow: hidden;
      }

      .portrait img {
        width: 100%;
        height: 100%;
        object-fit: cover;
      }

      .identity {
        display: flex;
        flex-direction: column;
        gap: 8px;
        min-width: 0; /* Allow flex item to shrink */
      }

      .name {
        font-size: 24px;
        font-weight: bold;
        color: #00ffff;
        margin: 0;
      }

      .class-title {
        font-size: 16px;
        color: #888;
        margin: 0;
      }

      .level {
        font-size: 14px;
        color: #aaa;
        margin: 0;
      }

      .xp-section {
        display: flex;
        flex-direction: column;
        gap: 5px;
        margin-top: 10px;
        width: 100%;
        min-width: 0; /* Prevent overflow */
      }

      .xp-bar-container {
        width: 100%;
        height: 20px;
        background: rgba(0, 0, 0, 0.5);
        border: 1px solid #555;
        position: relative;
        overflow: hidden;
      }

      .xp-bar-fill {
        height: 100%;
        background: linear-gradient(90deg, #ffd700, #ffaa00);
        transition: width 0.3s;
      }

      .xp-label {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        font-size: 11px;
        color: white;
        text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8);
        z-index: 1;
      }

      .sp-badge {
        display: inline-block;
        background: #00ff00;
        color: #000;
        padding: 2px 8px;
        border-radius: 10px;
        font-size: 12px;
        font-weight: bold;
        margin-top: 5px;
      }

      .close-button {
        background: transparent;
        border: 2px solid #ff6666;
        color: #ff6666;
        width: 40px;
        height: 40px;
        font-size: 24px;
        cursor: pointer;
        transition: all 0.2s;
        display: flex;
        align-items: center;
        justify-content: center;
      }

      .close-button:hover {
        background: #ff6666;
        color: white;
      }

      /* --- LEFT PANEL: STATS --- */
      .stats-panel {
        grid-area: stats;
        background: rgba(20, 20, 30, 0.9);
        border-right: 2px solid #555;
        padding: 20px;
        overflow-y: auto;
        display: flex;
        flex-direction: column;
        gap: 15px;
        min-height: 0; /* Allow grid item to shrink */
        height: 100%; /* Fill grid area */
        max-height: 100%; /* Constrain to grid area */
      }

      .stats-panel dl {
        display: flex;
        flex-direction: column;
        gap: 15px;
        margin: 0;
        padding: 0;
        min-height: 0; /* Allow flex container to shrink */
        flex: 1 1 0; /* Grow, shrink, basis 0 - fill available space but allow shrinking */
      }

      .stat-item {
        position: relative;
        background: rgba(0, 0, 0, 0.5);
        border: 1px solid #444;
        padding: 10px;
        cursor: pointer;
        transition: all 0.2s;
        margin: 0;
        list-style: none;
        anchor-name: --stat-item;
      }

      .stat-item:hover {
        border-color: #00ffff;
        background: rgba(0, 255, 255, 0.1);
      }

      .stat-item.buffed {
        border-color: #00ff00;
      }

      .stat-item.debuffed {
        border-color: #ff0000;
      }

      .stat-label {
        font-size: 12px;
        color: #aaa;
        margin-bottom: 5px;
        margin-top: 0;
        font-weight: normal;
      }

      .stat-value-container {
        margin: 0;
      }

      .stat-trigger {
        background: none;
        border: none;
        padding: 0;
        margin: 0;
        width: 100%;
        cursor: pointer;
        font-family: inherit;
        color: inherit;
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 5px;
        position: relative;
      }

      .stat-trigger:hover {
        opacity: 0.8;
      }

      .stat-trigger:focus-visible {
        outline: 2px solid #00ffff;
        outline-offset: 2px;
      }

      .stat-value {
        font-size: 20px;
        font-weight: bold;
        color: white;
      }

      .stat-value.buffed {
        color: #00ff00;
      }

      .stat-value.debuffed {
        color: #ff6666;
      }

      .health-bar-container {
        width: 100%;
        height: 24px;
        background: rgba(0, 0, 0, 0.5);
        border: 1px solid #555;
        position: relative;
        overflow: hidden;
      }

      .health-bar-fill {
        height: 100%;
        background: linear-gradient(90deg, #ff0000, #ff6666);
        transition: width 0.3s;
      }

      .health-label {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        font-size: 12px;
        color: white;
        text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8);
        z-index: 1;
      }

      .ap-icons {
        display: flex;
        gap: 5px;
        flex-wrap: wrap;
      }

      .ap-icon {
        width: 20px;
        height: 20px;
        background: #00ffff;
        border: 1px solid #00aaff;
        border-radius: 2px;
      }

      .ap-icon.empty {
        background: rgba(0, 170, 255, 0.3);
      }

      .tooltip {
        background: rgba(0, 0, 0, 0.95);
        border: 2px solid #00ffff;
        padding: 10px;
        min-width: 200px;
        z-index: 1000;
        color: #ffffff;
        /* CSS Anchor Positioning - positioning set via inline styles per tooltip */
        position: fixed;
        margin: 0;
        left: anchor(left);
        top: anchor(top);
        transform: translateY(-100%);
      }

      /* Popover API styling */
      .tooltip::backdrop {
        background: transparent;
      }

      .tooltip-title {
        font-weight: bold;
        margin-bottom: 8px;
        margin-top: 0;
        color: #00ffff;
        font-size: 14px;
      }

      .tooltip-breakdown {
        display: flex;
        flex-direction: column;
        gap: 4px;
        font-size: 12px;
        margin: 0;
        color: #ffffff;
      }

      .tooltip-row {
        display: flex;
        justify-content: space-between;
        color: #ffffff;
      }

      .tooltip-row dt,
      .tooltip-row dd {
        margin: 0;
        color: #ffffff;
      }

      .tooltip-total {
        margin-top: 8px;
        padding-top: 8px;
        border-top: 1px solid #555;
        font-weight: bold;
        color: #ffffff;
      }

      /* --- CENTER PANEL: PAPER DOLL --- */
      .paper-doll-panel {
        grid-area: paper-doll;
        background: rgba(15, 15, 25, 0.9);
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        padding: 20px;
        position: relative;
        container-type: inline-size;
        container-name: paper-doll;
        min-width: 0;
        min-height: 0; /* Allow grid item to shrink */
        height: 100%; /* Fill grid area */
      }

      .paper-doll-container {
        position: relative;
        width: 100%;
        height: 100%;
        max-width: 100%;
        max-height: 100%;
        aspect-ratio: 2/3;
        display: grid;
        grid-template-columns: 1fr 1.5fr 1fr;
        grid-template-rows: 1fr 1.5fr 1fr;
        grid-template-areas:
          ". . ."
          "mainHand body accessory"
          "offHand belt1 belt2";
        align-items: center;
        justify-items: center;
        /* Fit within container while maintaining aspect ratio */
        object-fit: contain;
      }

      /* Ensure container fits within panel bounds */
      @container paper-doll {
        .paper-doll-container {
          width: min(100cqw - 40px, (100cqh - 40px) * 2 / 3);
          height: min((100cqw - 40px) * 3 / 2, 100cqh - 40px);
        }
      }

      .unit-silhouette {
        grid-area: body;
        width: 60%;
        aspect-ratio: 2/3;
        background: rgba(50, 50, 70, 0.5);
        border: 2px dashed #666;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: clamp(24px, 4cqw, 48px);
        color: #666;
      }

      .equipment-slot {
        width: clamp(50px, 7cqw, 70px);
        height: clamp(50px, 7cqw, 70px);
        background: rgba(0, 0, 0, 0.6);
        border: 2px solid #555;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        transition: all 0.2s;
        position: relative;
      }

      .equipment-slot:hover {
        border-color: #00ffff;
        background: rgba(0, 255, 255, 0.1);
        transform: scale(1.1);
      }

      .equipment-slot.selected {
        border-color: #00ff00;
        background: rgba(0, 255, 0, 0.2);
      }

      .equipment-slot.mainHand {
        grid-area: mainHand;
      }

      .equipment-slot.offHand {
        grid-area: offHand;
      }

      .equipment-slot.body {
        grid-area: body;
        z-index: 1;
      }

      .equipment-slot.accessory {
        grid-area: accessory;
      }

      .equipment-slot.belt1 {
        grid-area: belt1;
      }

      .equipment-slot.belt2 {
        grid-area: belt2;
      }

      /* Legacy class names for backward compatibility */
      .equipment-slot.weapon {
        grid-area: mainHand;
      }

      .equipment-slot.armor {
        grid-area: body;
        z-index: 1;
      }

      .equipment-slot.relic {
        grid-area: accessory;
      }

      .equipment-slot.utility {
        grid-area: offHand;
      }

      .slot-icon {
        font-size: clamp(20px, 3cqw, 32px);
        color: #666;
      }

      .item-icon {
        width: 100%;
        height: 100%;
        object-fit: contain;
        padding: 5px;
      }

      .slot-label {
        position: absolute;
        bottom: -20px;
        left: 50%;
        transform: translateX(-50%);
        font-size: 10px;
        color: #aaa;
        white-space: nowrap;
      }

      /* --- RIGHT PANEL: TABS --- */
      .tabs-panel {
        grid-area: tabs;
        background: rgba(20, 20, 30, 0.9);
        border-left: 2px solid #555;
        display: flex;
        flex-direction: column;
        min-height: 0; /* Allow flex item to shrink */
        height: 100%; /* Fill grid area */
      }

      .tab-buttons {
        display: flex;
        border-bottom: 2px solid #555;
      }

      .tab-button {
        flex: 1;
        background: rgba(0, 0, 0, 0.5);
        border: none;
        border-right: 1px solid #555;
        color: #aaa;
        padding: 12px;
        cursor: pointer;
        font-family: inherit;
        font-size: 14px;
        transition: all 0.2s;
      }

      .tab-button:last-child {
        border-right: none;
      }

      .tab-button:hover {
        background: rgba(0, 255, 255, 0.1);
        color: white;
      }

      .tab-button.active {
        background: rgba(0, 255, 255, 0.2);
        color: #00ffff;
        border-bottom: 2px solid #00ffff;
        margin-bottom: -2px;
      }

      .tab-content {
        flex: 1;
        overflow-y: auto;
        overflow-x: hidden;
        padding: 20px;
        min-height: 0; /* Allow flex item to shrink */
      }

      .inventory-grid {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
        gap: 10px;
      }

      .item-card {
        width: 80px;
        height: 80px;
        background: rgba(0, 0, 0, 0.6);
        border: 2px solid #555;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        transition: all 0.2s;
        position: relative;
      }

      .item-card:hover {
        border-color: #00ffff;
        transform: scale(1.1);
      }

      .item-card.can-equip {
        border-color: #00ff00;
        box-shadow: 0 0 10px rgba(0, 255, 0, 0.5);
      }

      .item-card.can-equip:hover {
        border-color: #00ff00;
        box-shadow: 0 0 15px rgba(0, 255, 0, 0.8);
        transform: scale(1.15);
      }

      .item-card.cannot-equip {
        opacity: 0.5;
        border-color: #ff6666;
        cursor: not-allowed;
      }

      .item-card.cannot-equip:hover {
        border-color: #ff6666;
        box-shadow: 0 0 10px rgba(255, 102, 102, 0.5);
        transform: none;
      }

      .item-card:disabled {
        opacity: 0.5;
        cursor: not-allowed;
      }

      .item-card img {
        width: 100%;
        height: 100%;
        object-fit: contain;
        padding: 5px;
      }

      .skills-container {
        height: 100%;
        min-height: 0; /* Allow container to shrink */
        max-height: 100%; /* Constrain to parent */
        display: flex;
        flex-direction: column;
      }

      .mastery-container {
        display: flex;
        flex-direction: column;
        gap: 15px;
      }

      .mastery-class {
        background: rgba(0, 0, 0, 0.5);
        border: 1px solid #555;
        padding: 15px;
      }

      .mastery-class-name {
        font-weight: bold;
        margin-bottom: 10px;
        margin-top: 0;
        color: #00ffff;
        font-size: 16px;
      }

      .mastery-class p {
        margin: 5px 0;
      }

      .mastery-progress {
        width: 100%;
        height: 20px;
        background: rgba(0, 0, 0, 0.5);
        border: 1px solid #555;
        position: relative;
        overflow: hidden;
      }

      .mastery-progress-fill {
        height: 100%;
        background: linear-gradient(90deg, #00ffff, #00aaff);
        transition: width 0.3s;
      }
    `;
  }

  static get properties() {
    return {
      unit: { type: Object },
      readOnly: { type: Boolean },
      activeTab: { type: String },
      selectedSlot: { type: String },
      inventory: { type: Array },
      gameMode: { type: String }, // "DUNGEON" or "HUB"
      inventoryManager: { type: Object }, // InventoryManager instance
      treeDef: { type: Object }, // Skill tree definition
    };
  }

  constructor() {
    super();
    this.unit = null;
    this.readOnly = false;
    this.activeTab = "INVENTORY";
    this.selectedSlot = null;
    this.inventory = [];
    this.gameMode = "HUB";
    this.inventoryManager = null;
    this.treeDef = null;
  }

  /**
   * Gets or creates a simple tree definition from unit
   * @returns {Object|null}
   */
  _getTreeDefinition() {
    if (this.treeDef) {
      return this.treeDef;
    }

    if (!this.unit) {
      return null;
    }

    // Create a simple mock tree for demonstration
    // In production, this would come from SkillTreeFactory
    // This matches the mock tree in SkillTreeUI.js
    return {
      id: `TREE_${this.unit.activeClassId}`,
      nodes: {
        ROOT: {
          id: "ROOT",
          tier: 1,
          type: "STAT_BOOST",
          children: ["NODE_1", "NODE_2"],
          data: { stat: "health", value: 10 },
          req: 1,
          cost: 1,
        },
        NODE_1: {
          id: "NODE_1",
          tier: 2,
          type: "ACTIVE_SKILL",
          children: ["NODE_3"],
          data: { name: "Shield Bash", id: "SKILL_SHIELD_BASH" },
          req: 2,
          cost: 1,
        },
        NODE_2: {
          id: "NODE_2",
          tier: 2,
          type: "STAT_BOOST",
          children: [],
          data: { stat: "defense", value: 5 },
          req: 2,
          cost: 1,
        },
        NODE_3: {
          id: "NODE_3",
          tier: 3,
          type: "PASSIVE_ABILITY",
          children: [],
          data: { name: "Iron Skin", id: "PASSIVE_IRON_SKIN" },
          req: 3,
          cost: 2,
        },
      },
    };
  }

  /**
   * Calculates effective stat value with breakdown
   * @param {string} statName - Name of the stat
   * @returns {Object} - { total, breakdown }
   */
  _getEffectiveStat(statName) {
    if (!this.unit) {
      return { total: 0, breakdown: [] };
    }

    const breakdown = [];
    let total = 0;

    // Base stat - always show, even if 0
    const baseValue = this.unit.baseStats?.[statName] || 0;
    breakdown.push({ source: "Base", value: baseValue });
    total += baseValue;

    // Equipment stats from loadout (new system)
    if (this.unit.loadout && this.inventoryManager) {
      const loadoutSlots = ["mainHand", "offHand", "body", "accessory"];
      for (const slot of loadoutSlots) {
        const itemInstance = this.unit.loadout[slot];
        if (itemInstance) {
          const itemDef = this.inventoryManager.itemRegistry.get(
            itemInstance.defId
          );
          if (itemDef && itemDef.stats) {
            const itemValue = itemDef.stats[statName] || 0;
            if (itemValue !== 0) {
              breakdown.push({
                source: itemDef.name || slot,
                value: itemValue,
              });
              total += itemValue;
            }
          }
        }
      }
    } else if (this.unit.equipment) {
      // Fallback to legacy equipment system
      const slots = ["weapon", "armor", "utility", "relic"];
      for (const slot of slots) {
        const item = this.unit.equipment[slot];
        if (item && item.stats) {
          const itemValue =
            item.getStat?.(statName) || item.stats[statName] || 0;
          if (itemValue !== 0) {
            breakdown.push({ source: item.name || slot, value: itemValue });
            total += itemValue;
          }
        }
      }
    }

    // Skill tree stat boosts from unlocked nodes
    if (this.unit.classMastery) {
      const mastery = this.unit.classMastery[this.unit.activeClassId];
      if (mastery && mastery.unlockedNodes) {
        const tree = this._getTreeDefinition();
        if (tree) {
          for (const nodeId of mastery.unlockedNodes) {
            const nodeDef = tree.nodes[nodeId];
            if (
              nodeDef &&
              nodeDef.type === "STAT_BOOST" &&
              nodeDef.data &&
              nodeDef.data.stat === statName
            ) {
              const boostValue = nodeDef.data.value || 0;
              if (boostValue !== 0) {
                breakdown.push({
                  source: `Skill Tree: ${this._getNodeName(nodeDef)}`,
                  value: boostValue,
                });
                total += boostValue;
              }
            }
          }
        }
      }
    }

    // Status effects (buffs/debuffs)
    if (this.unit.statusEffects) {
      for (const effect of this.unit.statusEffects) {
        if (effect.statModifiers && effect.statModifiers[statName]) {
          const modValue = effect.statModifiers[statName];
          if (modValue !== 0) {
            breakdown.push({
              source: effect.name || effect.id || "Status Effect",
              value: modValue,
            });
            total += modValue;
          }
        }
      }
    }

    return { total, breakdown };
  }

  /**
   * Gets node name/title for skill tree nodes
   * @param {Object} nodeDef - Node definition
   * @returns {string}
   */
  _getNodeName(nodeDef) {
    if (nodeDef.data?.name) {
      return nodeDef.data.name;
    }
    if (nodeDef.type === "STAT_BOOST" && nodeDef.data?.stat) {
      return `${nodeDef.data.stat} +${nodeDef.data.value || 0}`;
    }
    return nodeDef.type || "Unknown";
  }

  /**
   * Determines if a stat is buffed or debuffed
   * @param {string} statName - Name of the stat
   * @returns {string} - "buffed", "debuffed", or ""
   */
  _getStatModifierState(statName) {
    if (!this.unit || !this.unit.statusEffects) {
      return "";
    }

    let hasBuff = false;
    let hasDebuff = false;

    for (const effect of this.unit.statusEffects) {
      if (effect.statModifiers && effect.statModifiers[statName]) {
        const modValue = effect.statModifiers[statName];
        if (modValue > 0) {
          hasBuff = true;
        } else if (modValue < 0) {
          hasDebuff = true;
        }
      }
    }

    if (hasBuff && !hasDebuff) return "buffed";
    if (hasDebuff && !hasBuff) return "debuffed";
    return "";
  }

  /**
   * Renders a stat item with tooltip
   * @param {string} label - Stat label
   * @param {string} statName - Stat name in unit.stats
   * @returns {TemplateResult}
   */
  _renderStat(label, statName) {
    const { total, breakdown } = this._getEffectiveStat(statName);
    const modifierState = this._getStatModifierState(statName);
    const tooltipId = `tooltip-${statName}`;

    // Special handling for Health
    const isHealth = statName === "health";
    let current = 0;
    let max = total;
    let percent = 0;
    if (isHealth) {
      current = this.unit?.currentHealth || 0;
      max = this.unit?.maxHealth || total;
      percent = max > 0 ? (current / max) * 100 : 0;
    }

    // Special handling for Speed/AP
    const isSpeed = statName === "speed";
    let maxAP = 0;
    let currentAP = 0;
    const apIcons = [];
    if (isSpeed) {
      maxAP = 3 + Math.floor(total / 5);
      currentAP = this.unit?.currentAP || 0;
      for (let i = 0; i < maxAP; i++) {
        apIcons.push(
          html`<div class="ap-icon ${i < currentAP ? "" : "empty"}"></div>`
        );
      }
    }

    return html`
      <div
        class="stat-item ${modifierState}"
        style="anchor-name: --stat-item-${statName};"
      >
        <dt class="stat-label">${label}</dt>
        <dd class="stat-value-container">
          <button
            class="stat-trigger"
            popovertarget="${tooltipId}"
            popovertargetaction="toggle"
            aria-label="Show ${label} breakdown"
          >
            ${isHealth
              ? html`
                  <div
                    class="health-bar-container"
                    role="progressbar"
                    aria-valuenow="${current}"
                    aria-valuemin="0"
                    aria-valuemax="${max}"
                    aria-label="${label}: ${current} out of ${max}"
                  >
                    <div
                      class="health-bar-fill"
                      style="width: ${percent}%"
                    ></div>
                    <div class="health-label">${current} / ${max}</div>
                  </div>
                `
              : html`
                  <div class="stat-value ${modifierState}">${total}</div>
                  ${isSpeed
                    ? html`
                        <div
                          class="ap-icons"
                          aria-label="Action Points: ${currentAP} out of ${maxAP}"
                        >
                          ${apIcons}
                        </div>
                      `
                    : ""}
                `}
          </button>
        </dd>
        <div
          class="tooltip"
          id="${tooltipId}"
          popover="auto"
          role="tooltip"
          style="position-anchor: --stat-item-${statName};"
        >
          <h3 class="tooltip-title">${label} Breakdown</h3>
          <dl class="tooltip-breakdown">
            ${breakdown && breakdown.length > 0
              ? breakdown.map(
                  (item) => html`
                    <div class="tooltip-row">
                      <dt>${item.source}</dt>
                      <dd>${item.value > 0 ? "+" : ""}${item.value}</dd>
                    </div>
                  `
                )
              : html`
                  <div class="tooltip-row">
                    <dt>Base</dt>
                    <dd>0</dd>
                  </div>
                `}
            <div class="tooltip-row tooltip-total">
              <dt>Total</dt>
              <dd>${total}</dd>
            </div>
          </dl>
        </div>
      </div>
    `;
  }

  /**
   * Gets item definition from loadout slot
   * @param {string} slotName - Loadout slot name (mainHand, offHand, body, accessory, belt[index])
   * @returns {Object|null} - Item definition or null
   */
  _getItemFromLoadout(slotName) {
    if (!this.unit.loadout || !this.inventoryManager) {
      return null;
    }

    let itemInstance = null;
    if (slotName.startsWith("belt")) {
      const index = parseInt(slotName.replace("belt", "")) || 0;
      itemInstance = this.unit.loadout.belt?.[index];
    } else {
      itemInstance = this.unit.loadout[slotName];
    }

    if (!itemInstance) {
      return null;
    }

    return this.inventoryManager.itemRegistry.get(itemInstance.defId);
  }

  /**
   * Renders an equipment slot button
   * @param {string} slotType - Slot type (MAIN_HAND, OFF_HAND, BODY, ACCESSORY)
   * @param {string} loadoutSlot - Loadout slot name (mainHand, offHand, body, accessory)
   * @param {string} defaultIcon - Default icon emoji
   * @param {string} label - Slot label
   * @returns {TemplateResult}
   */
  _renderEquipmentSlot(slotType, loadoutSlot, defaultIcon, label) {
    const itemDef = this._getItemFromLoadout(loadoutSlot);
    const isSelected = this.selectedSlot === slotType;
    const slotClass = loadoutSlot; // mainHand, offHand, body, accessory

    return html`
      <button
        class="equipment-slot ${slotClass} ${isSelected ? "selected" : ""}"
        @click="${(e) => this._handleSlotClick(slotType, e)}"
        @contextmenu="${(e) => {
          e.preventDefault();
          this._handleUnequip(slotType);
        }}"
        ?disabled="${this.readOnly}"
        aria-label="${label} slot${itemDef
          ? `: ${itemDef.name}`
          : " (empty)"}${itemDef ? " - Right-click to unequip" : ""}"
        title="${itemDef
          ? `${itemDef.name} - Right-click to unequip`
          : `${label} slot - Click to select, right-click to unequip`}"
      >
        ${itemDef
          ? html`<img
              src="${itemDef.icon || ""}"
              alt="${itemDef.name}"
              class="item-icon"
            />`
          : html`<span class="slot-icon" aria-hidden="true"
              >${defaultIcon}</span
            >`}
        <span class="slot-label">${label}</span>
      </button>
    `;
  }

  /**
   * Renders a belt slot button
   * @param {number} index - Belt slot index (0 or 1)
   * @returns {TemplateResult}
   */
  _renderBeltSlot(index) {
    const slotType = `BELT_${index}`;
    const isSelected = this.selectedSlot === slotType;
    const itemDef = this._getItemFromLoadout(`belt${index}`);

    return html`
      <button
        class="equipment-slot belt${index + 1} ${isSelected ? "selected" : ""}"
        @click="${(e) => this._handleSlotClick(slotType, e)}"
        @contextmenu="${(e) => {
          e.preventDefault();
          this._handleUnequip(slotType);
        }}"
        ?disabled="${this.readOnly}"
        aria-label="Belt slot ${index + 1}${itemDef
          ? `: ${itemDef.name} - Right-click to unequip`
          : " (empty)"}"
        title="${itemDef
          ? `${itemDef.name} - Right-click to unequip`
          : `Belt slot ${index + 1} - Click to select, right-click to unequip`}"
      >
        ${itemDef
          ? html`<img
              src="${itemDef.icon || ""}"
              alt="${itemDef.name}"
              class="item-icon"
            />`
          : html`<span class="slot-icon" aria-hidden="true">🧪</span>`}
        <span class="slot-label">Belt ${index + 1}</span>
      </button>
    `;
  }

  /**
   * Handles equipment slot click
   * @param {string} slotType - Type of slot clicked
   * @param {MouseEvent} event - Mouse event (for right-click detection)
   */
  _handleSlotClick(slotType, event) {
    if (this.readOnly) return;

    // Right-click to unequip
    if (event && event.button === 2) {
      event.preventDefault();
      this._handleUnequip(slotType);
      return;
    }

    if (this.selectedSlot === slotType) {
      this.selectedSlot = null;
    } else {
      this.selectedSlot = slotType;
      this.activeTab = "INVENTORY";
    }
    this.requestUpdate();
  }

  /**
   * Handles unequipping an item from a slot
   * @param {string} slotType - Type of slot to unequip
   */
  _handleUnequip(slotType) {
    if (!this.inventoryManager || !this.unit) return;

    // Map slot types to InventoryManager slot names
    const slotMap = {
      MAIN_HAND: "MAIN_HAND",
      OFF_HAND: "OFF_HAND",
      BODY: "BODY",
      ACCESSORY: "ACCESSORY",
      BELT_0: "BELT",
      BELT_1: "BELT",
    };

    let slot = slotMap[slotType] || slotType;
    let beltIndex = undefined;

    // Handle belt slots
    if (slotType === "BELT_0" || slotType === "BELT_1") {
      beltIndex = slotType === "BELT_0" ? 0 : 1;
    }

    const success = this.inventoryManager.unequipItem(
      this.unit,
      slot,
      beltIndex
    );

    if (success) {
      // Dispatch unequip event
      this.dispatchEvent(
        new CustomEvent("unequip-item", {
          detail: {
            unitId: this.unit.id,
            slot: slot,
          },
          bubbles: true,
          composed: true,
        })
      );

      this.selectedSlot = null;
      this.requestUpdate();
    }
  }

  /**
   * Handles item click in inventory
   * @param {Object} item - Item to equip
   */
  _handleItemClick(item) {
    if (this.readOnly || !this.selectedSlot) return;

    // Check if item can be equipped (class restrictions, etc.)
    if (item.canEquipCheck === false) {
      // Item cannot be equipped - show feedback
      console.warn(
        `Cannot equip ${item.name} - class restriction or requirements not met`
      );
      return;
    }

    // Use inventoryManager if available
    if (this.inventoryManager && item.uid) {
      // Map slot types to InventoryManager slot names
      const slotMap = {
        WEAPON: "MAIN_HAND",
        ARMOR: "BODY",
        UTILITY: "OFF_HAND",
        RELIC: "ACCESSORY",
        MAIN_HAND: "MAIN_HAND",
        OFF_HAND: "OFF_HAND",
        BODY: "BODY",
        ACCESSORY: "ACCESSORY",
        BELT_0: "BELT",
        BELT_1: "BELT",
      };

      let slot = slotMap[this.selectedSlot] || this.selectedSlot;
      let beltIndex = undefined;

      // Handle belt slots
      if (this.selectedSlot === "BELT_0" || this.selectedSlot === "BELT_1") {
        beltIndex = this.selectedSlot === "BELT_0" ? 0 : 1;
      }

      // Create ItemInstance from item
      const itemInstance = {
        uid: item.uid,
        defId: item.defId,
        isNew: item.isNew || false,
        quantity: item.quantity || 1,
      };

      // Double-check with InventoryManager before equipping (safety check)
      if (!this.inventoryManager.canEquip(this.unit, itemInstance)) {
        console.warn(
          `Cannot equip ${item.name} - class restriction or requirements not met`
        );
        alert(
          `Cannot equip ${item.name} - This item has class restrictions or requirements you don't meet.`
        );
        return;
      }

      // Use InventoryManager to equip
      const success = this.inventoryManager.equipItem(
        this.unit,
        itemInstance,
        slot,
        beltIndex
      );

      if (success) {
        // Dispatch equip event
        this.dispatchEvent(
          new CustomEvent("equip-item", {
            detail: {
              unitId: this.unit.id,
              slot: slot,
              item: item,
            },
            bubbles: true,
            composed: true,
          })
        );

        this.selectedSlot = null;
        this.requestUpdate();
      }
      return;
    }

    // Fallback to legacy equipment system
    const slotMap = {
      WEAPON: "weapon",
      ARMOR: "armor",
      UTILITY: "utility",
      RELIC: "relic",
    };

    const equipmentKey = slotMap[this.selectedSlot];
    if (!equipmentKey) return;

    // Check if item can be equipped
    if (item.canEquip && !item.canEquip(this.unit)) {
      return;
    }

    // Swap items
    const oldItem = this.unit.equipment[equipmentKey];
    this.unit.equipment[equipmentKey] = item;

    // Remove item from inventory
    const itemIndex = this.inventory.indexOf(item);
    if (itemIndex !== -1) {
      this.inventory.splice(itemIndex, 1);
    }

    // Add old item to inventory if it exists
    if (oldItem) {
      this.inventory.push(oldItem);
    }

    // Dispatch equip event
    this.dispatchEvent(
      new CustomEvent("equip-item", {
        detail: {
          unitId: this.unit.id,
          slot: this.selectedSlot,
          item: item,
          oldItem: oldItem,
        },
        bubbles: true,
        composed: true,
      })
    );

    this.selectedSlot = null;
    this.requestUpdate();
  }

  /**
   * Gets filtered inventory based on selected slot
   * @returns {Array}
   */
  _getFilteredInventory() {
    // Use inventoryManager if available
    if (this.inventoryManager) {
      const stash =
        this.gameMode === "DUNGEON"
          ? this.inventoryManager.runStash
          : this.inventoryManager.hubStash;

      // Defensive check: ensure stash exists and has getAllItems method
      if (!stash || typeof stash.getAllItems !== "function") {
        return this.inventory || [];
      }

      const items = stash.getAllItems();

      // Ensure items is an array
      if (!Array.isArray(items)) {
        return this.inventory || [];
      }

      // Convert ItemInstance to UI format
      const uiItems = items.map((itemInstance) => {
        const itemDef = this.inventoryManager.itemRegistry?.get(
          itemInstance.defId
        );
        // Check if unit can equip this item using InventoryManager
        const canEquip =
          this.unit && this.inventoryManager
            ? this.inventoryManager.canEquip(this.unit, itemInstance)
            : true; // Default to true if we can't check

        return {
          uid: itemInstance.uid,
          defId: itemInstance.defId,
          name: itemDef?.name || itemInstance.defId,
          type: itemDef?.type || "UTILITY",
          stats: itemDef?.stats || {},
          canEquip: itemDef ? (unit) => itemDef.canEquip(unit) : () => true,
          canEquipCheck: canEquip, // Store the result of the check
          quantity: itemInstance.quantity,
          isNew: itemInstance.isNew,
          icon: itemDef?.icon || null,
        };
      });

      if (!this.selectedSlot) {
        return uiItems;
      }

      const typeMap = {
        WEAPON: "WEAPON",
        ARMOR: "ARMOR",
        UTILITY: "UTILITY",
        RELIC: "RELIC",
        MAIN_HAND: "WEAPON",
        OFF_HAND: "UTILITY",
        BODY: "ARMOR",
        ACCESSORY: "RELIC",
      };

      const filterType = typeMap[this.selectedSlot];
      if (!filterType) return uiItems;

      return uiItems.filter((item) => item.type === filterType);
    }

    // Fallback to legacy inventory array
    // Ensure inventory is always an array
    const inventory = Array.isArray(this.inventory) ? this.inventory : [];

    if (!this.selectedSlot) {
      return inventory;
    }

    const typeMap = {
      WEAPON: "WEAPON",
      ARMOR: "ARMOR",
      UTILITY: "UTILITY",
      RELIC: "RELIC",
    };

    const filterType = typeMap[this.selectedSlot];
    if (!filterType) return inventory;

    return inventory.filter((item) => item.type === filterType);
  }

  /**
   * Gets XP percentage for current class
   * @returns {number}
   */
  _getXPPercent() {
    if (!this.unit || !this.unit.classMastery) return 0;
    const mastery = this.unit.classMastery[this.unit.activeClassId];
    if (!mastery) return 0;

    // Simplified: assume 100 XP per level for now
    const xpForNextLevel = mastery.level * 100;
    return mastery.xp / xpForNextLevel;
  }

  /**
   * Gets skill points for current class
   * @returns {number}
   */
  _getSkillPoints() {
    if (!this.unit || !this.unit.classMastery) return 0;
    const mastery = this.unit.classMastery[this.unit.activeClassId];
    return mastery?.skillPoints || 0;
  }

  /**
   * Gets a human-readable label for a slot type
   * @param {string} slotType - Slot type (MAIN_HAND, OFF_HAND, etc.)
   * @returns {string}
   */
  _getSlotLabel(slotType) {
    const labels = {
      MAIN_HAND: "Main Hand",
      OFF_HAND: "Off Hand",
      BODY: "Body",
      ACCESSORY: "Accessory",
      BELT_0: "Belt Slot 1",
      BELT_1: "Belt Slot 2",
      WEAPON: "Weapon",
      ARMOR: "Armor",
      UTILITY: "Utility",
      RELIC: "Relic",
    };
    return labels[slotType] || slotType;
  }

  /**
   * Gets class name from class ID
   * @returns {string}
   */
  _getClassName() {
    if (!this.unit) return "";
    const classId = this.unit.activeClassId;
    // Simple mapping - could be enhanced with a registry
    const classNames = {
      CLASS_VANGUARD: "Vanguard",
      CLASS_WEAVER: "Aether Weaver",
      CLASS_SCAVENGER: "Scavenger",
      CLASS_TINKER: "Tinker",
      CLASS_CUSTODIAN: "Custodian",
    };
    return classNames[classId] || classId;
  }

  render() {
    if (!this.unit) {
      return html``;
    }

    const mastery = this.unit.classMastery?.[this.unit.activeClassId] || {
      level: 1,
      xp: 0,
      skillPoints: 0,
    };

    const xpPercent = Math.min(this._getXPPercent() * 100, 100);
    const skillPoints = this._getSkillPoints();
    const filteredInventory = this._getFilteredInventory();

    return html`
      <dialog>
        <div class="container">
          <!-- HEADER -->
          <header class="header">
            <div class="portrait">
              ${this.unit.portrait || this.unit.image
                ? html`<img
                    src="${this.unit.portrait || this.unit.image}"
                    alt="Portrait of ${this.unit.name}"
                  />`
                : html`<span aria-label="Portrait placeholder">👤</span>`}
            </div>
            <div class="identity">
              <h1 class="name">${this.unit.name}</h1>
              <p class="class-title">${this._getClassName()}</p>
              <p class="level">Level ${mastery.level}</p>
              <div class="xp-section">
                <div
                  class="xp-bar-container"
                  role="progressbar"
                  aria-valuenow="${mastery.xp}"
                  aria-valuemin="0"
                  aria-valuemax="${mastery.level * 100}"
                  aria-label="Experience points"
                >
                  <div class="xp-bar-fill" style="width: ${xpPercent}%"></div>
                  <div class="xp-label">XP: ${mastery.xp}</div>
                </div>
                ${skillPoints > 0
                  ? html`<span
                      class="sp-badge"
                      aria-label="Skill points available"
                      >SP: ${skillPoints}</span
                    >`
                  : ""}
              </div>
            </div>
            <button
              class="close-button"
              @click="${this._handleClose}"
              aria-label="Close character sheet"
            >
              ×
            </button>
          </header>

          <!-- LEFT PANEL: STATS -->
          <aside class="stats-panel" aria-label="Character statistics">
            <dl>
              ${this._renderStat("Health", "health")}
              ${this._renderStat("AP", "speed")}
              ${this._renderStat("Attack", "attack")}
              ${this._renderStat("Defense", "defense")}
              ${this._renderStat("Magic", "magic")}
              ${this._renderStat("Willpower", "willpower")}
              ${this._renderStat("Tech", "tech")}
            </dl>
          </aside>

          <!-- CENTER PANEL: PAPER DOLL -->
          <section class="paper-doll-panel" aria-label="Equipment slots">
            <div class="paper-doll-container">
              <div class="unit-silhouette">👤</div>
              ${this._renderEquipmentSlot(
                "MAIN_HAND",
                "mainHand",
                "⚔️",
                "Main Hand"
              )}
              ${this._renderEquipmentSlot(
                "OFF_HAND",
                "offHand",
                "🛡️",
                "Off Hand"
              )}
              ${this._renderEquipmentSlot("BODY", "body", "🛡️", "Body")}
              ${this._renderEquipmentSlot(
                "ACCESSORY",
                "accessory",
                "💎",
                "Accessory"
              )}
              ${this._renderBeltSlot(0)} ${this._renderBeltSlot(1)}
            </div>
          </section>

          <!-- RIGHT PANEL: TABS -->
          <section class="tabs-panel" aria-label="Character management">
            <nav
              class="tab-buttons"
              role="tablist"
              aria-label="Character sheet tabs"
            >
              <button
                class="tab-button ${this.activeTab === "INVENTORY"
                  ? "active"
                  : ""}"
                @click="${() => {
                  this.activeTab = "INVENTORY";
                  this.requestUpdate();
                }}"
                role="tab"
                aria-selected="${this.activeTab === "INVENTORY"}"
                aria-controls="inventory-panel"
                id="inventory-tab"
              >
                Inventory
              </button>
              <button
                class="tab-button ${this.activeTab === "SKILLS"
                  ? "active"
                  : ""}"
                @click="${() => {
                  this.activeTab = "SKILLS";
                  this.requestUpdate();
                }}"
                role="tab"
                aria-selected="${this.activeTab === "SKILLS"}"
                aria-controls="skills-panel"
                id="skills-tab"
              >
                Skills
              </button>
              <button
                class="tab-button ${this.activeTab === "MASTERY"
                  ? "active"
                  : ""}"
                @click="${() => {
                  this.activeTab = "MASTERY";
                  this.requestUpdate();
                }}"
                role="tab"
                aria-selected="${this.activeTab === "MASTERY"}"
                aria-controls="mastery-panel"
                id="mastery-tab"
              >
                Mastery
              </button>
            </nav>

            <div class="tab-content">
              ${this.activeTab === "INVENTORY"
                ? html`
                    <div
                      class="inventory-grid"
                      id="inventory-panel"
                      role="tabpanel"
                      aria-labelledby="inventory-tab"
                    >
                      ${this.selectedSlot
                        ? html`
                            <div
                              class="equip-hint"
                              style="grid-column: 1/-1; padding: 10px; background: rgba(0, 255, 0, 0.1); border: 1px solid #00ff00; border-radius: 4px; margin-bottom: 10px; text-align: center; color: #00ff00; font-size: 12px;"
                            >
                              <strong>Slot Selected:</strong>
                              ${this._getSlotLabel(this.selectedSlot)} - Click
                              an item below to equip it
                            </div>
                          `
                        : html`
                            <div
                              class="equip-hint"
                              style="grid-column: 1/-1; padding: 10px; background: rgba(0, 255, 255, 0.1); border: 1px solid #00ffff; border-radius: 4px; margin-bottom: 10px; text-align: center; color: #00ffff; font-size: 12px;"
                            >
                              <strong>Tip:</strong> Click an equipment slot on
                              the left, then click an item here to equip it
                            </div>
                          `}
                      ${filteredInventory.map((item) => {
                        // Check if item can actually be equipped (class restrictions, etc.)
                        const canEquipItem = item.canEquipCheck !== false;
                        const isEquippable = this.selectedSlot && canEquipItem;

                        return html`
                          <button
                            class="item-card ${isEquippable
                              ? "can-equip"
                              : ""} ${!canEquipItem && this.selectedSlot
                              ? "cannot-equip"
                              : ""}"
                            @click="${() => this._handleItemClick(item)}"
                            ?disabled="${!canEquipItem && this.selectedSlot}"
                            title="${item.name}${this.selectedSlot
                              ? ` - Click to equip to ${this._getSlotLabel(
                                  this.selectedSlot
                                )}`
                              : ""}${!canEquipItem && this.selectedSlot
                              ? " (Cannot equip - class restriction)"
                              : ""}"
                            aria-label="Equip ${item.name}${!canEquipItem
                              ? " (Cannot equip)"
                              : ""}"
                          >
                            ${item.icon
                              ? html`<img
                                  src="${item.icon}"
                                  alt="${item.name}"
                                />`
                              : html`<span aria-hidden="true">📦</span>`}
                          </button>
                        `;
                      })}
                      ${filteredInventory.length === 0
                        ? html`<p
                            style="grid-column: 1/-1; text-align: center; color: #666;"
                          >
                            ${this.selectedSlot
                              ? `No items available for ${this._getSlotLabel(
                                  this.selectedSlot
                                )}`
                              : "No items available"}
                          </p>`
                        : ""}
                    </div>
                  `
                : ""}
              ${this.activeTab === "SKILLS"
                ? html`
                    <div
                      class="skills-container"
                      id="skills-panel"
                      role="tabpanel"
                      aria-labelledby="skills-tab"
                    >
                      ${this.unit
                        ? html`<skill-tree-ui
                            .unit="${this.unit}"
                            .treeDef="${this.treeDef}"
                            @unlock-request="${this._handleUnlockRequest}"
                          ></skill-tree-ui>`
                        : html`<p>No unit selected</p>`}
                    </div>
                  `
                : ""}
              ${this.activeTab === "MASTERY"
                ? html`
                    <div
                      class="mastery-container"
                      id="mastery-panel"
                      role="tabpanel"
                      aria-labelledby="mastery-tab"
                    >
                      ${Object.entries(this.unit.classMastery || {}).map(
                        ([classId, masteryData]) => html`
                          <article class="mastery-class">
                            <h2 class="mastery-class-name">${classId}</h2>
                            <p>Level ${masteryData.level}</p>
                            <div
                              class="mastery-progress"
                              role="progressbar"
                              aria-valuenow="${masteryData.xp}"
                              aria-valuemin="0"
                              aria-valuemax="${masteryData.level * 100}"
                              aria-label="Mastery progress for ${classId}"
                            >
                              <div
                                class="mastery-progress-fill"
                                style="width: ${(masteryData.xp /
                                  (masteryData.level * 100)) *
                                100}%"
                              ></div>
                            </div>
                          </article>
                        `
                      )}
                    </div>
                  `
                : ""}
            </div>
          </section>
        </div>
      </dialog>
    `;
  }

  firstUpdated() {
    const dialog = this.shadowRoot.querySelector("dialog");
    if (dialog) {
      dialog.showModal();
      // Handle ESC key and backdrop clicks
      dialog.addEventListener("cancel", (e) => {
        e.preventDefault();
        this._handleClose();
      });
      dialog.addEventListener("click", (e) => {
        if (e.target === dialog) {
          this._handleClose();
        }
      });
    }
  }

  _handleClose() {
    const dialog = this.shadowRoot.querySelector("dialog");
    if (dialog) {
      dialog.close();
    }
    this.dispatchEvent(
      new CustomEvent("close", {
        bubbles: true,
        composed: true,
      })
    );
  }

  /**
   * Handles unlock-request event from SkillTreeUI
   * @param {CustomEvent} event - Unlock request event
   */
  _handleUnlockRequest(event) {
    const { nodeId, cost } = event.detail;

    if (!this.unit || !this.unit.classMastery) {
      return;
    }

    const mastery = this.unit.classMastery[this.unit.activeClassId];
    if (!mastery) {
      return;
    }

    if (mastery.skillPoints < cost) {
      console.warn("Insufficient skill points");
      return;
    }

    // Deduct skill points and unlock node
    mastery.skillPoints -= cost;
    if (!mastery.unlockedNodes) {
      mastery.unlockedNodes = [];
    }
    if (!mastery.unlockedNodes.includes(nodeId)) {
      mastery.unlockedNodes.push(nodeId);
    }

    // Recalculate unit stats to include the new skill tree boost
    const tree = this._getTreeDefinition();
    if (
      this.unit.recalculateStats &&
      typeof this.unit.recalculateStats === "function"
    ) {
      this.unit.recalculateStats(
        this.inventoryManager?.itemRegistry || null,
        tree
      );
    }

    // Update the view
    this.requestUpdate();

    // Force SkillTreeUI to update by finding it and incrementing updateTrigger
    // This is needed because we mutated nested properties which LitElement doesn't detect
    setTimeout(() => {
      const skillTreeUI = this.shadowRoot?.querySelector("skill-tree-ui");
      if (skillTreeUI) {
        // Increment updateTrigger to force a re-render
        skillTreeUI.updateTrigger = (skillTreeUI.updateTrigger || 0) + 1;
      }
    }, 0);

    // Dispatch event for persistence/other systems
    this.dispatchEvent(
      new CustomEvent("skill-unlocked", {
        detail: {
          unitId: this.unit.id,
          nodeId: nodeId,
          cost: cost,
        },
        bubbles: true,
        composed: true,
      })
    );
  }
}

customElements.define("character-sheet", CharacterSheet);
