import { LitElement, html, css } from 'lit';
import { gameStateManager } from '../../core/GameStateManager.js';
import { theme, buttonStyles, cardStyles, gridStyles, badgeStyles, tabStyles, overlayStyles } from '../styles/theme.js';

/**
 * MissionBoard.js
 * Component for displaying and selecting available missions.
 * @class
 */
export class MissionBoard extends LitElement {
  static get styles() {
    return [
      theme,
      buttonStyles,
      cardStyles,
      gridStyles,
      badgeStyles,
      tabStyles,
      overlayStyles,
      css`
        :host {
          display: block;
          background: var(--color-bg-secondary);
          border: var(--border-width-medium) solid var(--color-border-default);
          padding: var(--spacing-xl);
          max-width: 1000px;
          max-height: 80vh;
          overflow-y: auto;
          color: var(--color-text-primary);
          font-family: var(--font-family);
        }

        .header {
          display: flex;
          justify-content: space-between;
          align-items: center;
          margin-bottom: var(--spacing-xl);
          border-bottom: var(--border-width-medium) solid var(--color-border-default);
          padding-bottom: var(--spacing-md);
        }

        .header h2 {
          margin: 0;
          color: var(--color-accent-gold);
          font-size: var(--font-size-4xl);
        }

        .missions-grid {
          display: grid;
          grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
          gap: var(--spacing-lg);
          margin-bottom: var(--spacing-lg);
        }

        .mission-card {
          background: var(--color-bg-card);
          border: var(--border-width-medium) solid var(--color-border-default);
          padding: var(--spacing-lg);
          cursor: pointer;
          transition: all var(--transition-normal);
          position: relative;
        }

        .mission-card:hover {
          border-color: var(--color-accent-gold);
          box-shadow: var(--shadow-glow-gold);
          transform: translateY(-2px);
        }

        .mission-card.completed {
          border-color: var(--color-accent-green);
          opacity: 0.7;
        }

        .mission-card.completed:hover {
          border-color: var(--color-accent-green);
          box-shadow: var(--shadow-glow-green);
          transform: translateY(-2px);
          cursor: pointer;
        }

        .mission-card.locked {
          opacity: 0.5;
          cursor: not-allowed;
          border-color: var(--color-border-dark);
        }

        .mission-card.locked:hover {
          transform: none;
          border-color: var(--color-border-dark);
          box-shadow: none;
        }

        .mission-header {
          display: flex;
          justify-content: space-between;
          align-items: start;
          margin-bottom: var(--spacing-md);
        }

        .mission-title {
          font-size: var(--font-size-2xl);
          font-weight: var(--font-weight-bold);
          color: var(--color-accent-cyan);
          margin: 0;
        }

        .mission-type {
          font-size: var(--font-size-xs);
          padding: 4px var(--spacing-sm);
          background: rgba(255, 255, 255, 0.1);
          border-radius: var(--border-radius-md);
          text-transform: uppercase;
        }

        .mission-type.STORY {
          background: rgba(255, 0, 0, 0.3);
          color: var(--color-accent-red);
        }

        .mission-type.SIDE_QUEST {
          background: rgba(255, 215, 0, 0.3);
          color: var(--color-accent-gold);
        }

        .mission-type.TUTORIAL {
          background: rgba(0, 255, 255, 0.3);
          color: var(--color-accent-cyan);
        }

        .mission-type.PROCEDURAL {
          background: rgba(0, 255, 0, 0.3);
          color: var(--color-accent-green);
        }

        .mission-description {
          font-size: var(--font-size-sm);
          color: var(--color-text-secondary);
          margin-bottom: var(--spacing-md);
          line-height: 1.5;
        }

        .mission-rewards {
          display: flex;
          gap: var(--spacing-sm);
          flex-wrap: wrap;
          margin-bottom: var(--spacing-sm);
        }

        .reward-item {
          display: flex;
          align-items: center;
          gap: var(--spacing-xs);
          font-size: var(--font-size-xs);
          color: var(--color-accent-gold);
        }

        .mission-footer {
          display: flex;
          justify-content: space-between;
          align-items: center;
          margin-top: var(--spacing-md);
          padding-top: var(--spacing-md);
          border-top: var(--border-width-thin) solid var(--color-border-default);
        }

        .difficulty {
          font-size: var(--font-size-xs);
          color: var(--color-text-secondary);
        }

        .select-button {
          background: #008800;
          border: var(--border-width-medium) solid var(--color-accent-green);
          color: white;
          padding: var(--spacing-sm) var(--spacing-lg);
          font-family: var(--font-family);
          font-size: var(--font-size-sm);
          font-weight: var(--font-weight-bold);
          cursor: pointer;
          transition: all var(--transition-normal);
          border-radius: var(--border-radius-md);
        }

        .select-button:hover:not(:disabled) {
          background: #00aa00;
          box-shadow: var(--shadow-glow-green);
        }

        .select-button:disabled {
          opacity: 0.5;
          cursor: not-allowed;
        }

        .empty-state {
          text-align: center;
          padding: var(--spacing-2xl);
          color: var(--color-text-muted);
        }

        .section-header {
          font-size: var(--font-size-xl);
          font-weight: var(--font-weight-bold);
          color: var(--color-accent-cyan);
          margin: var(--spacing-xl) 0 var(--spacing-md) 0;
          padding-bottom: var(--spacing-sm);
          border-bottom: var(--border-width-thin) solid var(--color-border-default);
        }

        .section-header:first-of-type {
          margin-top: 0;
        }

        .close-button {
          background: transparent;
          border: none;
          color: var(--color-text-primary);
          font-size: var(--font-size-2xl);
          cursor: pointer;
          padding: var(--spacing-xs);
          line-height: 1;
          transition: color var(--transition-normal);
        }

        .close-button:hover {
          color: var(--color-accent-red);
        }
      `
    ];
  }

  static get properties() {
    return {
      missions: { type: Array },
      completedMissions: { type: Set },
      activeTab: { type: String },
      reviewMission: { type: Object },
    };
  }

  constructor() {
    super();
    this.missions = [];
    this.completedMissions = new Set();
    this.activeTab = 'active';
    this.reviewMission = null;
    this._isLoading = false; // Guard to prevent infinite loops
  }

  connectedCallback() {
    super.connectedCallback();
    // Load missions and refresh procedural missions only on first open
    // Ensure we wait for GameStateManager to be ready (important after page refresh)
    this._initialLoad();
    
    // Listen for campaign data changes to refresh completed missions
    this._boundHandleCampaignChange = this._handleCampaignChange.bind(this);
    // Listen for mission updates (new missions added, missions refreshed)
    this._boundHandleMissionsUpdate = this._handleMissionsUpdate.bind(this);
    
    window.addEventListener('campaign-data-changed', this._boundHandleCampaignChange);
    window.addEventListener('gamestate-changed', this._boundHandleCampaignChange);
    window.addEventListener('missions-updated', this._boundHandleMissionsUpdate);
  }

  async _initialLoad() {
    // Guard to prevent multiple initial loads
    if (this._isLoading) {
      return;
    }
    this._isLoading = true;
    
    try {
      // Ensure missions are loaded before accessing registry
      await gameStateManager.missionManager._ensureMissionsLoaded();
      // Wait a bit to ensure campaign data has been loaded from persistence
      // This is important after page refresh when persistence loads campaign data asynchronously
      await new Promise(resolve => setTimeout(resolve, 50));
      // Refresh procedural missions if unlocked (to ensure board is populated on first open)
      // This only happens once when the board is first opened
      if (gameStateManager.missionManager.areProceduralMissionsUnlocked()) {
        gameStateManager.missionManager.refreshProceduralMissions();
      }
      // Then load the missions directly (bypass guard since we're already in a guarded context)
      await this._loadMissionsInternal();
    } finally {
      this._isLoading = false;
    }
  }

  disconnectedCallback() {
    super.disconnectedCallback();
    if (this._boundHandleCampaignChange) {
      window.removeEventListener('campaign-data-changed', this._boundHandleCampaignChange);
      window.removeEventListener('gamestate-changed', this._boundHandleCampaignChange);
    }
    if (this._boundHandleMissionsUpdate) {
      window.removeEventListener('missions-updated', this._boundHandleMissionsUpdate);
    }
  }

  _handleCampaignChange() {
    // Reload missions when campaign data changes (mission completed)
    // Force reload of completed missions from MissionManager
    this.completedMissions = gameStateManager.missionManager.completedMissions || new Set();
    this._loadMissions();
  }

  _handleMissionsUpdate() {
    // Reload missions when new missions are added or missions are refreshed
    // Use guard to prevent infinite loops
    if (!this._isLoading) {
      this._loadMissions();
    }
  }

  async _loadMissions() {
    // Guard to prevent infinite loops
    if (this._isLoading) {
      return;
    }
    this._isLoading = true;
    
    try {
      await this._loadMissionsInternal();
    } finally {
      this._isLoading = false;
    }
  }

  async _loadMissionsInternal() {
    // Internal method that actually loads missions (no guard check)
    // Ensure missions are loaded before accessing registry
    await gameStateManager.missionManager._ensureMissionsLoaded();
    // Don't automatically refresh procedural missions here - that causes infinite loops
    // Missions should be refreshed when the board is first opened, not on every update
    // Get all registered missions from MissionManager
    const missionRegistry = gameStateManager.missionManager.missionRegistry;
    this.missions = Array.from(missionRegistry.values());
    
    // Also include completed mission details (for procedural missions that were removed from registry)
    const completedMissionDetails = gameStateManager.missionManager.completedMissionDetails || new Map();
    for (const [missionId, missionDef] of completedMissionDetails.entries()) {
      // Only add if not already in registry (to avoid duplicates)
      if (!this.missions.find(m => m.id === missionId)) {
        this.missions.push(missionDef);
      }
    }
    
    // Always refresh completed missions from MissionManager to ensure we have the latest data
    // This is important after page refresh when persistence has loaded the data
    const managerCompletedMissions = gameStateManager.missionManager.completedMissions;
    if (managerCompletedMissions instanceof Set) {
      this.completedMissions = new Set(managerCompletedMissions);
    } else {
      this.completedMissions = new Set(managerCompletedMissions || []);
    }
    console.log('MissionBoard: Loaded completed missions:', Array.from(this.completedMissions));
    this.requestUpdate();
  }

  _isMissionAvailable(mission) {
    // Check if mission prerequisites are met
    const prerequisites = mission.config?.prerequisites || [];
    
    // If no prerequisites, mission is available
    if (prerequisites.length === 0) {
      return true;
    }
    
    // Check if all prerequisites are completed
    return prerequisites.every(prereqId => this.completedMissions.has(prereqId));
  }

  /**
   * Determines if a mission should be shown in the mission board.
   * Story missions are hidden until available, other types show as locked.
   * @param {Object} mission - Mission definition
   * @returns {boolean}
   */
  _shouldShowMission(mission) {
    const isAvailable = this._isMissionAvailable(mission);
    
    // If available, always show
    if (isAvailable) {
      return true;
    }
    
    // Check visibility setting (defaults based on mission type)
    const visibility = mission.config?.visibility_when_locked;
    
    // Default behavior: STORY missions are hidden, others show as locked
    if (visibility === undefined) {
      return mission.type !== "STORY";
    }
    
    // Explicit setting overrides default
    return visibility === "locked";
  }

  _isMissionCompleted(missionId) {
    return this.completedMissions.has(missionId);
  }

  _selectMission(mission) {
    if (!this._isMissionAvailable(mission)) {
      return;
    }

    // Dispatch mission-selected event
    this.dispatchEvent(
      new CustomEvent('mission-selected', {
        detail: { missionId: mission.id },
        bubbles: true,
        composed: true,
      })
    );
  }

  _reviewMission(mission) {
    this.reviewMission = mission;
    this.requestUpdate();
  }

  _closeReview(e) {
    if (e) {
      e.stopPropagation();
    }
    this.reviewMission = null;
    this.requestUpdate();
  }

  _formatRewards(rewards) {
    const rewardItems = [];
    
    if (rewards?.currency) {
      // Handle both snake_case (from JSON) and camelCase (from code)
      const shards = rewards.currency.aether_shards || rewards.currency.aetherShards || 0;
      const cores = rewards.currency.ancient_cores || rewards.currency.ancientCores || 0;
      
      if (shards > 0) {
        rewardItems.push({ icon: '💎', text: `${shards} Shards` });
      }
      if (cores > 0) {
        rewardItems.push({ icon: '⚙️', text: `${cores} Cores` });
      }
    }

    if (rewards?.xp) {
      rewardItems.push({ icon: '⭐', text: `${rewards.xp} XP` });
    }

    return rewardItems;
  }

  _getDifficultyLabel(config) {
    if (config?.difficulty_tier) {
      return `Tier ${config.difficulty_tier}`;
    }
    if (config?.difficulty) {
      return config.difficulty.toUpperCase();
    }
    if (config?.recommended_level) {
      return `Level ${config.recommended_level}`;
    }
    return 'Unknown';
  }

  _getActiveMissions() {
    return this.missions.filter(mission => {
      if (!this._shouldShowMission(mission)) {
        return false;
      }
      return !this._isMissionCompleted(mission.id);
    });
  }

  _getCompletedMissions() {
    // Get completed missions that are in the current registry
    const completedInRegistry = this.missions.filter(mission => {
      if (!this._shouldShowMission(mission)) {
        return false;
      }
      return this._isMissionCompleted(mission.id);
    });

    // Also include completed missions that are no longer in the registry
    // This is important for procedural missions (side quests) that get refreshed
    const completedNotInRegistry = [];
    for (const missionId of this.completedMissions) {
      // Check if this mission is not in the current registry
      const missionInRegistry = this.missions.find(m => m.id === missionId);
      if (!missionInRegistry) {
        // Create a stub mission object for display purposes
        // This handles procedural missions that were removed during refresh
        const stubMission = this._createStubMission(missionId);
        if (stubMission) {
          completedNotInRegistry.push(stubMission);
        }
      }
    }

    return [...completedInRegistry, ...completedNotInRegistry];
  }

  _createStubMission(missionId) {
    // First, check if we have saved mission details from persistence
    const completedMissionDetails = gameStateManager.missionManager.completedMissionDetails || new Map();
    const savedMission = completedMissionDetails.get(missionId);
    if (savedMission) {
      return savedMission;
    }
    
    // Fallback: Create a minimal mission object for completed missions that are no longer in the registry
    // This is primarily for procedural side quests that get refreshed
    if (missionId.startsWith('SIDE_OP_')) {
      // It's a procedural side quest - create a stub
      return {
        id: missionId,
        type: 'SIDE_QUEST',
        config: {
          title: missionId.replace('SIDE_OP_', '').replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase()),
          description: 'Completed procedural mission (no longer available)',
        },
        rewards: {
          guaranteed: {
            xp: 0,
            currency: { aether_shards: 0, ancient_cores: 0 },
          },
        },
      };
    }
    // For non-procedural missions, try to load from static mission files if possible
    // For now, return null - we could enhance this later to load from mission files
    return null;
  }

  _getCompletedMissionsByType() {
    const completed = this._getCompletedMissions();
    return {
      story: completed.filter(m => m.type === 'STORY' || m.type === 'TUTORIAL'),
      sideQuest: completed.filter(m => m.type === 'SIDE_QUEST'),
      other: completed.filter(m => m.type !== 'STORY' && m.type !== 'SIDE_QUEST' && m.type !== 'TUTORIAL'),
    };
  }

  _renderMissionCard(mission) {
    const isCompleted = this._isMissionCompleted(mission.id);
    const isAvailable = this._isMissionAvailable(mission);
    const rewards = this._formatRewards(mission.rewards?.guaranteed || mission.rewards || {});

    return html`
      <div
        class="mission-card ${isCompleted ? 'completed' : ''} ${!isAvailable ? 'locked' : ''}"
        @click=${() => {
          if (isCompleted) {
            this._reviewMission(mission);
          } else if (isAvailable) {
            this._selectMission(mission);
          }
        }}
      >
        <div class="mission-header">
          <h3 class="mission-title">${mission.config?.title || mission.id}</h3>
          <span class="mission-type ${mission.type || 'PROCEDURAL'}">
            ${mission.type || 'PROCEDURAL'}
          </span>
        </div>

        <p class="mission-description">
          ${mission.config?.description || 'No description available.'}
        </p>

        ${rewards.length > 0 ? html`
          <div class="mission-rewards">
            ${rewards.map((reward) => html`
              <div class="reward-item">
                <span>${reward.icon}</span>
                <span>${reward.text}</span>
              </div>
            `)}
          </div>
        ` : ''}

        <div class="mission-footer">
          <span class="difficulty">
            Difficulty: ${this._getDifficultyLabel(mission.config)}
          </span>
          ${isCompleted ? html`
            <span style="color: var(--color-accent-green); cursor: pointer;" title="Click to review mission">
              ✓ Completed - Click to Review
            </span>
          ` : ''}
          ${!isAvailable && !isCompleted ? html`
            <span style="color: var(--color-text-muted); font-size: var(--font-size-xs);">
              🔒 Requires: ${mission.config?.prerequisites?.map(id => {
                const prereqMission = this.missions.find(m => m.id === id);
                return prereqMission?.config?.title || id;
              }).join(', ') || 'Previous missions'}
            </span>
          ` : ''}
          ${isAvailable && !isCompleted ? html`
            <button
              class="btn btn-primary select-button"
              @click=${(e) => {
                e.stopPropagation();
                this._selectMission(mission);
              }}
            >
              SELECT
            </button>
          ` : ''}
        </div>
      </div>
    `;
  }

  render() {
    if (this.missions.length === 0) {
      return html`
        <div class="header">
          <h2>MISSION BOARD</h2>
          <button class="close-button" @click=${() => this.dispatchEvent(new CustomEvent('close', { bubbles: true, composed: true }))}>
            ×
          </button>
        </div>
        <div class="empty-state">
          <p>No missions available at this time.</p>
        </div>
      `;
    }

    const activeMissions = this._getActiveMissions();
    const completedByType = this._getCompletedMissionsByType();

    return html`
      <div class="header">
        <h2>MISSION BOARD</h2>
        <button class="close-button" @click=${() => this.dispatchEvent(new CustomEvent('close', { bubbles: true, composed: true }))}>
          ×
        </button>
      </div>

      <div class="tabs">
        <button
          class="tab-button ${this.activeTab === 'active' ? 'active' : ''}"
          @click=${() => {
            this.activeTab = 'active';
            this.requestUpdate();
          }}
        >
          Active
        </button>
        <button
          class="tab-button ${this.activeTab === 'completed' ? 'active' : ''}"
          @click=${() => {
            this.activeTab = 'completed';
            this.requestUpdate();
          }}
        >
          Completed
        </button>
      </div>

      <div class="tab-content">
        ${this.activeTab === 'active' ? html`
          ${activeMissions.length === 0 ? html`
            <div class="empty-state">
              <p>No active missions available at this time.</p>
            </div>
          ` : html`
            <div class="missions-grid">
              ${activeMissions.map(mission => this._renderMissionCard(mission))}
            </div>
          `}
        ` : html`
          ${completedByType.story.length === 0 && completedByType.sideQuest.length === 0 && completedByType.other.length === 0 ? html`
            <div class="empty-state">
              <p>No completed missions yet.</p>
            </div>
          ` : html`
            ${completedByType.story.length > 0 ? html`
              <h3 class="section-header">Story Missions</h3>
              <div class="missions-grid">
                ${completedByType.story.map(mission => this._renderMissionCard(mission))}
              </div>
            ` : ''}
            ${completedByType.sideQuest.length > 0 ? html`
              <h3 class="section-header">Side Quests</h3>
              <div class="missions-grid">
                ${completedByType.sideQuest.map(mission => this._renderMissionCard(mission))}
              </div>
            ` : ''}
            ${completedByType.other.length > 0 ? html`
              <h3 class="section-header">Other Missions</h3>
              <div class="missions-grid">
                ${completedByType.other.map(mission => this._renderMissionCard(mission))}
              </div>
            ` : ''}
          `}
        `}
      </div>

      ${this.reviewMission ? html`
        <div class="overlay-container active">
          <div class="overlay-backdrop" @click=${(e) => {
            e.stopPropagation();
            this._closeReview(e);
          }}></div>
          <div class="overlay-content" @click=${(e) => e.stopPropagation()}>
            <mission-review
              .mission=${this.reviewMission}
              @review-close=${(e) => {
                e.stopPropagation();
                this._closeReview(e);
              }}
            ></mission-review>
          </div>
        </div>
      ` : ''}
    `;
  }
}

customElements.define('mission-board', MissionBoard);

