// src/flow/viewers/ErrorViewer.ts
//
// ErrorViewer - Displays errors with stack traces.

import { MatrixActorHtmlElement } from '../../framework/MatrixActorHtmlElement';
import { ShellRegistry } from '../ShellRegistry';

/**
 * ErrorViewer - Displays error information with stack traces.
 *
 * Accepts:
 *   - setError: { message: string, stack?: string, code?: string, details?: any }
 *   - retry: {}
 *   - copyStack: {}
 *   - dismiss: {}
 *
 * Emits:
 *   - retried: {}
 *   - dismissed: {}
 *   - copied: {}
 */
export class ErrorViewer extends MatrixActorHtmlElement {
  static accepts = {
    setError: {
      message: 'string',
      stack: 'string?',
      code: 'string?',
      details: 'any?',
    },
    retry: {},
    copyStack: {},
    dismiss: {},
  };

  static emits = {
    retried: {},
    dismissed: {},
    copied: {},
  };

  static template = `
    <div class="error-viewer">
      <div class="error-header">
        <span class="error-icon">!</span>
        <span id="errorCode" class="error-code"></span>
        <span class="error-title">Error</span>
        <div class="actions">
          <button id="retryBtn" title="Retry">Retry</button>
          <button id="copyBtn" title="Copy stack trace">Copy</button>
          <button id="dismissBtn" title="Dismiss">X</button>
        </div>
      </div>
      <div class="error-body">
        <div id="message" class="error-message"></div>
        <details id="stackDetails" class="stack-details">
          <summary>Stack Trace</summary>
          <pre id="stack" class="stack-trace"></pre>
        </details>
        <details id="detailsSection" class="details-section" style="display:none">
          <summary>Details</summary>
          <pre id="details" class="details-content"></pre>
        </details>
      </div>
    </div>
    <style>
      :host { display: block; }
      .error-viewer {
        border: 2px solid var(--mx-color-error, #f44336);
        border-radius: 8px;
        background: var(--mx-color-surface-hover, #ffebee);
        overflow: hidden;
      }
      .error-header {
        padding: 10px 12px;
        background: var(--mx-color-error, #f44336);
        color: white;
        display: flex;
        align-items: center;
        gap: 8px;
      }
      .error-icon {
        width: 20px;
        height: 20px;
        border-radius: 50%;
        background: white;
        color: var(--mx-color-error, #f44336);
        display: flex;
        align-items: center;
        justify-content: center;
        font-weight: bold;
        font-size: 14px;
      }
      .error-code {
        background: rgba(255,255,255,0.2);
        padding: 2px 8px;
        border-radius: 4px;
        font-size: 11px;
        font-family: monospace;
      }
      .error-title {
        font-weight: 600;
        flex: 1;
      }
      .actions {
        display: flex;
        gap: 4px;
      }
      .actions button {
        padding: 4px 10px;
        border: 1px solid rgba(255,255,255,0.5);
        border-radius: 4px;
        background: transparent;
        color: white;
        cursor: pointer;
        font-size: 11px;
      }
      .actions button:hover {
        background: rgba(255,255,255,0.2);
      }
      .error-body {
        padding: 12px;
      }
      .error-message {
        font-size: 14px;
        color: var(--mx-color-error, #c62828);
        margin-bottom: 12px;
        font-weight: 500;
      }
      .stack-details, .details-section {
        margin-top: 8px;
      }
      summary {
        cursor: pointer;
        font-size: 12px;
        color: var(--mx-color-text-secondary, #666);
        padding: 4px 0;
      }
      summary:hover {
        color: var(--mx-color-text, #333);
      }
      .stack-trace, .details-content {
        font-family: 'Consolas', 'Monaco', monospace;
        font-size: 11px;
        background: var(--mx-color-surface, #fff);
        padding: 10px;
        border-radius: 4px;
        border: 1px solid var(--mx-color-error, #ffcdd2);
        overflow-x: auto;
        white-space: pre-wrap;
        word-break: break-word;
        margin-top: 8px;
        max-height: 200px;
        overflow-y: auto;
      }
    </style>
  `;

  private _error: {
    message: string;
    stack?: string;
    code?: string;
    details?: unknown;
  } | null = null;

  get error() {
    return this._error;
  }

  async onBootstrap(): Promise<void> {

    // Initialize from props if passed
    // Note: _initialProps is dynamically set by parent during child creation
    const props = (this as unknown as { _initialProps?: { data?: Record<string, unknown>; label?: string } })._initialProps;
    if (props?.data !== undefined) {
      // For errors, extract error info from the data object
      this.onSetError({
        message: String(props.data.message || props.label || 'Error'),
        stack: typeof props.data.stack === 'string' ? props.data.stack : undefined,
        code: typeof props.data.code === 'string' ? props.data.code : undefined,
        details: props.data.details,
      });
    }

    // Wire up button handlers
    const retryBtn = this.shadowRoot?.getElementById('retryBtn');
    const copyBtn = this.shadowRoot?.getElementById('copyBtn');
    const dismissBtn = this.shadowRoot?.getElementById('dismissBtn');

    retryBtn?.addEventListener('click', () => this.onRetry());
    dismissBtn?.addEventListener('click', () => this.onDismiss());
    copyBtn?.addEventListener('click', () => {
      if (this._error?.stack) {
        navigator.clipboard?.writeText(this._error.stack);
      }
      this.onCopyStack();
    });

    // Initial render
    this.render();
  }

  onSetError(params: {
    message: string;
    stack?: string;
    code?: string;
    details?: unknown;
  }): void {
    this._error = params;
    this.render();
  }

  onRetry(): void {
    this.emit('retried', {});
  }

  onCopyStack(): void {
    this.emit('copied', {});
  }

  onDismiss(): void {
    this.emit('dismissed', {});
  }

  /**
   * Render the error display
   */
  render(): void {
    const messageEl = this.shadowRoot?.getElementById('message');
    const stackEl = this.shadowRoot?.getElementById('stack');
    const stackDetails = this.shadowRoot?.getElementById('stackDetails');
    const errorCodeEl = this.shadowRoot?.getElementById('errorCode');
    const detailsSection = this.shadowRoot?.getElementById('detailsSection');
    const detailsEl = this.shadowRoot?.getElementById('details');

    const error = this._error;
    if (!error) return;

    if (messageEl) messageEl.textContent = error.message;
    if (errorCodeEl) {
      errorCodeEl.textContent = error.code || '';
      errorCodeEl.style.display = error.code ? 'inline' : 'none';
    }
    if (stackEl) stackEl.textContent = error.stack || '';
    if (stackDetails) {
      stackDetails.style.display = error.stack ? 'block' : 'none';
    }
    if (detailsSection && detailsEl) {
      if (error.details) {
        detailsSection.style.display = 'block';
        detailsEl.textContent = JSON.stringify(error.details, null, 2);
      } else {
        detailsSection.style.display = 'none';
      }
    }
  }
}

// Keep ErrorViewerShell as alias for backwards compatibility
export const ErrorViewerShell = ErrorViewer;

// Register with ShellRegistry
ShellRegistry.register('ErrorViewer', {
  shellTag: 'error-viewer',
  moduleUrl: import.meta.url,
});

// Register custom element
if (typeof customElements !== 'undefined' && !customElements.get('error-viewer')) {
  customElements.define('error-viewer', ErrorViewer);
}
