/**
 * ds-visual-diff.js
 * Visual diff tool for comparing design changes using Pixelmatch
 */

import toolBridge from '../../services/tool-bridge.js';
import { ComponentHelpers } from '../../utils/component-helpers.js';

// Load Pixelmatch from CDN
let pixelmatch = null;

class DSVisualDiff extends HTMLElement {
  constructor() {
    super();
    this.screenshots = [];
    this.beforeImage = null;
    this.afterImage = null;
    this.diffResult = null;
    this.isComparing = false;
    this.pixelmatchLoaded = false;
  }

  async connectedCallback() {
    this.render();
    this.setupEventListeners();
    await this.loadPixelmatch();
    await this.loadScreenshots();
  }

  /**
   * Load Pixelmatch library from CDN
   */
  async loadPixelmatch() {
    if (this.pixelmatchLoaded) return;

    try {
      // Import pixelmatch from esm.sh CDN
      const module = await import('https://esm.sh/pixelmatch@5.3.0');
      pixelmatch = module.default;
      this.pixelmatchLoaded = true;
      console.log('[DSVisualDiff] Pixelmatch loaded successfully');
    } catch (error) {
      console.error('[DSVisualDiff] Failed to load Pixelmatch:', error);
      ComponentHelpers.showToast?.('Failed to load visual diff library', 'error');
    }
  }

  /**
   * Load screenshots from IndexedDB (shared with ds-screenshot-gallery)
   */
  async loadScreenshots() {
    try {
      const db = await this.openDB();
      this.screenshots = await this.getAllScreenshots(db);
      this.renderSelectors();
    } catch (error) {
      console.error('Failed to load screenshots:', error);
    }
  }

  async openDB() {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open('ds-screenshots', 1);
      request.onerror = () => reject(request.error);
      request.onsuccess = () => resolve(request.result);
    });
  }

  async getAllScreenshots(db) {
    return new Promise((resolve, reject) => {
      const transaction = db.transaction(['screenshots'], 'readonly');
      const store = transaction.objectStore('screenshots');
      const request = store.getAll();

      request.onsuccess = () => resolve(request.result.reverse());
      request.onerror = () => reject(request.error);
    });
  }

  setupEventListeners() {
    const compareBtn = this.querySelector('#visual-diff-compare-btn');
    if (compareBtn) {
      compareBtn.addEventListener('click', () => this.compareImages());
    }
  }

  /**
   * Load image data and decode to ImageData
   */
  async loadImageData(imageDataUrl) {
    return new Promise((resolve, reject) => {
      const img = new Image();
      img.crossOrigin = 'anonymous';

      img.onload = () => {
        const canvas = document.createElement('canvas');
        canvas.width = img.width;
        canvas.height = img.height;

        const ctx = canvas.getContext('2d');
        ctx.drawImage(img, 0, 0);

        const imageData = ctx.getImageData(0, 0, img.width, img.height);
        resolve(imageData);
      };

      img.onerror = () => reject(new Error('Failed to load image'));
      img.src = imageDataUrl;
    });
  }

  /**
   * Compare two images using Pixelmatch
   */
  async compareImages() {
    if (this.isComparing || !this.pixelmatchLoaded) return;

    const beforeSelect = this.querySelector('#before-image-select');
    const afterSelect = this.querySelector('#after-image-select');

    if (!beforeSelect || !afterSelect) return;

    const beforeId = parseInt(beforeSelect.value);
    const afterId = parseInt(afterSelect.value);

    if (!beforeId || !afterId) {
      ComponentHelpers.showToast?.('Please select both before and after images', 'error');
      return;
    }

    if (beforeId === afterId) {
      ComponentHelpers.showToast?.('Please select different images to compare', 'error');
      return;
    }

    this.isComparing = true;
    const compareBtn = this.querySelector('#visual-diff-compare-btn');

    if (compareBtn) {
      compareBtn.disabled = true;
      compareBtn.textContent = '🔍 Comparing...';
    }

    try {
      // Get screenshot objects
      this.beforeImage = this.screenshots.find(s => s.id === beforeId);
      this.afterImage = this.screenshots.find(s => s.id === afterId);

      if (!this.beforeImage || !this.afterImage) {
        throw new Error('Screenshots not found');
      }

      // Load image data
      const beforeData = await this.loadImageData(this.beforeImage.imageData);
      const afterData = await this.loadImageData(this.afterImage.imageData);

      // Ensure images are same size
      if (beforeData.width !== afterData.width || beforeData.height !== afterData.height) {
        throw new Error(`Image dimensions don't match: ${beforeData.width}x${beforeData.height} vs ${afterData.width}x${afterData.height}`);
      }

      // Create diff canvas
      const diffCanvas = document.createElement('canvas');
      diffCanvas.width = beforeData.width;
      diffCanvas.height = beforeData.height;
      const diffCtx = diffCanvas.getContext('2d');
      const diffImageData = diffCtx.createImageData(beforeData.width, beforeData.height);

      // Run pixelmatch comparison
      const numDiffPixels = pixelmatch(
        beforeData.data,
        afterData.data,
        diffImageData.data,
        beforeData.width,
        beforeData.height,
        {
          threshold: 0.1,
          includeAA: false,
          alpha: 0.1,
          diffColor: [255, 0, 0]
        }
      );

      // Put diff data on canvas
      diffCtx.putImageData(diffImageData, 0, 0);

      // Calculate difference percentage
      const totalPixels = beforeData.width * beforeData.height;
      const diffPercentage = ((numDiffPixels / totalPixels) * 100).toFixed(2);

      this.diffResult = {
        beforeImage: this.beforeImage,
        afterImage: this.afterImage,
        diffImageData: diffCanvas.toDataURL(),
        numDiffPixels,
        totalPixels,
        diffPercentage,
        timestamp: new Date()
      };

      this.renderDiffResult();

      ComponentHelpers.showToast?.(
        `Comparison complete: ${diffPercentage}% difference`,
        diffPercentage < 1 ? 'success' : diffPercentage < 10 ? 'warning' : 'error'
      );
    } catch (error) {
      console.error('Failed to compare images:', error);
      ComponentHelpers.showToast?.(`Comparison failed: ${error.message}`, 'error');

      const diffContent = this.querySelector('#diff-result-content');
      if (diffContent) {
        diffContent.innerHTML = ComponentHelpers.renderError('Comparison failed', error);
      }
    } finally {
      this.isComparing = false;
      if (compareBtn) {
        compareBtn.disabled = false;
        compareBtn.textContent = '🔍 Compare';
      }
    }
  }

  renderSelectors() {
    const beforeSelect = this.querySelector('#before-image-select');
    const afterSelect = this.querySelector('#after-image-select');

    if (!beforeSelect || !afterSelect) return;

    const options = this.screenshots.map(screenshot => {
      const timestamp = ComponentHelpers.formatTimestamp(new Date(screenshot.timestamp));
      return `<option value="${screenshot.id}">${ComponentHelpers.escapeHtml(screenshot.selector)} - ${timestamp}</option>`;
    }).join('');

    const emptyOption = '<option value="">-- Select Screenshot --</option>';

    beforeSelect.innerHTML = emptyOption + options;
    afterSelect.innerHTML = emptyOption + options;
  }

  renderDiffResult() {
    const diffContent = this.querySelector('#diff-result-content');
    if (!diffContent || !this.diffResult) return;

    const { diffPercentage, numDiffPixels, totalPixels } = this.diffResult;

    // Determine status badge
    let statusBadge;
    if (diffPercentage < 1) {
      statusBadge = ComponentHelpers.createBadge('Identical', 'success');
    } else if (diffPercentage < 10) {
      statusBadge = ComponentHelpers.createBadge('Minor Changes', 'warning');
    } else {
      statusBadge = ComponentHelpers.createBadge('Significant Changes', 'error');
    }

    diffContent.innerHTML = `
      <!-- Stats Card -->
      <div style="background-color: var(--vscode-sidebar); border: 1px solid var(--vscode-border); border-radius: 4px; padding: 16px; margin-bottom: 16px;">
        <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;">
          <h4 style="font-size: 12px; font-weight: 600;">Comparison Result</h4>
          ${statusBadge}
        </div>

        <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; font-size: 11px;">
          <div style="text-align: center;">
            <div style="font-size: 24px; font-weight: 600; color: var(--vscode-text);">${diffPercentage}%</div>
            <div style="color: var(--vscode-text-dim); margin-top: 4px;">Difference</div>
          </div>
          <div style="text-align: center;">
            <div style="font-size: 24px; font-weight: 600; color: var(--vscode-text);">${numDiffPixels.toLocaleString()}</div>
            <div style="color: var(--vscode-text-dim); margin-top: 4px;">Pixels Changed</div>
          </div>
          <div style="text-align: center;">
            <div style="font-size: 24px; font-weight: 600; color: var(--vscode-text);">${totalPixels.toLocaleString()}</div>
            <div style="color: var(--vscode-text-dim); margin-top: 4px;">Total Pixels</div>
          </div>
        </div>
      </div>

      <!-- Image Comparison Grid -->
      <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 16px;">
        <!-- Before Image -->
        <div style="background-color: var(--vscode-sidebar); border: 1px solid var(--vscode-border); border-radius: 4px; overflow: hidden;">
          <div style="padding: 12px; border-bottom: 1px solid var(--vscode-border);">
            <div style="font-size: 11px; font-weight: 600; margin-bottom: 4px;">Before</div>
            <div style="font-size: 10px; color: var(--vscode-text-dim);">${ComponentHelpers.escapeHtml(this.diffResult.beforeImage.selector)}</div>
            <div style="font-size: 10px; color: var(--vscode-text-dim);">${ComponentHelpers.formatRelativeTime(new Date(this.diffResult.beforeImage.timestamp))}</div>
          </div>
          <div style="aspect-ratio: 16/9; overflow: hidden; background: var(--vscode-bg);">
            <img src="${this.diffResult.beforeImage.imageData}" style="width: 100%; height: 100%; object-fit: contain;" alt="Before" />
          </div>
        </div>

        <!-- After Image -->
        <div style="background-color: var(--vscode-sidebar); border: 1px solid var(--vscode-border); border-radius: 4px; overflow: hidden;">
          <div style="padding: 12px; border-bottom: 1px solid var(--vscode-border);">
            <div style="font-size: 11px; font-weight: 600; margin-bottom: 4px;">After</div>
            <div style="font-size: 10px; color: var(--vscode-text-dim);">${ComponentHelpers.escapeHtml(this.diffResult.afterImage.selector)}</div>
            <div style="font-size: 10px; color: var(--vscode-text-dim);">${ComponentHelpers.formatRelativeTime(new Date(this.diffResult.afterImage.timestamp))}</div>
          </div>
          <div style="aspect-ratio: 16/9; overflow: hidden; background: var(--vscode-bg);">
            <img src="${this.diffResult.afterImage.imageData}" style="width: 100%; height: 100%; object-fit: contain;" alt="After" />
          </div>
        </div>

        <!-- Diff Image -->
        <div style="background-color: var(--vscode-sidebar); border: 1px solid var(--vscode-border); border-radius: 4px; overflow: hidden; grid-column: span 2;">
          <div style="padding: 12px; border-bottom: 1px solid var(--vscode-border);">
            <div style="font-size: 11px; font-weight: 600; margin-bottom: 4px;">Visual Diff</div>
            <div style="font-size: 10px; color: var(--vscode-text-dim);">Red pixels indicate changes</div>
          </div>
          <div style="aspect-ratio: 16/9; overflow: hidden; background: var(--vscode-bg);">
            <img src="${this.diffResult.diffImageData}" style="width: 100%; height: 100%; object-fit: contain;" alt="Diff" />
          </div>
        </div>
      </div>

      <div style="margin-top: 12px; padding: 8px; background-color: var(--vscode-sidebar); border-radius: 4px; font-size: 10px; color: var(--vscode-text-dim);">
        💡 Red pixels show where the images differ. Lower percentages indicate more similarity.
      </div>
    `;
  }

  render() {
    this.innerHTML = `
      <div style="padding: 16px; height: 100%; display: flex; flex-direction: column;">
        <!-- Selector Controls -->
        <div style="margin-bottom: 16px; background-color: var(--vscode-sidebar); border: 1px solid var(--vscode-border); border-radius: 4px; padding: 16px;">
          <h3 style="font-size: 14px; font-weight: 600; margin-bottom: 12px;">Visual Diff Comparison</h3>

          <div style="display: grid; grid-template-columns: 1fr 1fr auto; gap: 12px; align-items: end;">
            <div>
              <label style="display: block; font-size: 11px; margin-bottom: 4px; color: var(--vscode-text-dim);">
                Before Image
              </label>
              <select id="before-image-select" class="input" style="width: 100%; font-size: 11px;">
                <option value="">-- Select Screenshot --</option>
              </select>
            </div>

            <div>
              <label style="display: block; font-size: 11px; margin-bottom: 4px; color: var(--vscode-text-dim);">
                After Image
              </label>
              <select id="after-image-select" class="input" style="width: 100%; font-size: 11px;">
                <option value="">-- Select Screenshot --</option>
              </select>
            </div>

            <button id="visual-diff-compare-btn" class="button" style="padding: 4px 12px; font-size: 11px;">
              🔍 Compare
            </button>
          </div>

          ${this.screenshots.length === 0 ? `
            <div style="margin-top: 12px; padding: 12px; background-color: rgba(255, 191, 0, 0.1); border-radius: 4px;">
              <div style="font-size: 11px; color: #ffbf00;">
                ⚠️ No screenshots available. Capture screenshots using the Screenshot Gallery tool first.
              </div>
            </div>
          ` : ''}
        </div>

        <!-- Diff Result -->
        <div id="diff-result-content" style="flex: 1; overflow-y: auto;">
          <div style="text-align: center; padding: 48px; color: var(--vscode-text-dim);">
            <div style="font-size: 48px; margin-bottom: 16px;">🔍</div>
            <h3 style="font-size: 14px; font-weight: 600; margin-bottom: 8px;">Ready to Compare</h3>
            <p style="font-size: 12px;">
              Select two screenshots above and click "Compare" to see the visual differences.
            </p>
          </div>
        </div>
      </div>
    `;
  }
}

customElements.define('ds-visual-diff', DSVisualDiff);

export default DSVisualDiff;
