import * as plugins from '../plugins.js';
import { apiService, changeStreamService, type ICollectionStats, type IMongoChangeEvent } from '../services/index.js';
import { formatSize, formatCount } from '../utilities/index.js';
import { themeStyles } from '../styles/index.js';

const { html, css, cssManager, customElement, property, state, DeesElement } = plugins;

type TViewTab = 'documents' | 'indexes' | 'aggregation';

@customElement('tsview-mongo-browser')
export class TsviewMongoBrowser extends DeesElement {
  @property({ type: String })
  public accessor databaseName: string = '';

  @property({ type: String })
  public accessor collectionName: string = '';

  @state()
  private accessor activeTab: TViewTab = 'documents';

  @state()
  private accessor selectedDocumentId: string = '';

  @state()
  private accessor stats: ICollectionStats | null = null;

  @state()
  private accessor editorWidth: number = 700;

  @state()
  private accessor isResizingEditor: boolean = false;

  @state()
  private accessor recentChangeCount: number = 0;

  @state()
  private accessor isStreamConnected: boolean = false;

  private changeSubscription: plugins.smartrx.rxjs.Subscription | null = null;
  private connectionSubscription: plugins.smartrx.rxjs.Subscription | null = null;

  public static styles = [
    cssManager.defaultStyles,
    themeStyles,
    css`
      :host {
        display: block;
        height: 100%;
      }

      .browser-container {
        display: flex;
        flex-direction: column;
        height: 100%;
      }

      .header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 12px;
        background: rgba(0, 0, 0, 0.2);
        border-radius: 8px;
        margin-bottom: 16px;
      }

      .collection-info {
        display: flex;
        align-items: center;
        gap: 16px;
      }

      .collection-title {
        font-size: 16px;
        font-weight: 500;
      }

      .collection-stats {
        display: flex;
        gap: 16px;
        font-size: 13px;
        color: #888;
      }

      .stat-item {
        display: flex;
        align-items: center;
        gap: 4px;
      }

      .tabs {
        display: flex;
        gap: 4px;
      }

      .tab {
        padding: 8px 16px;
        background: transparent;
        border: none;
        color: #888;
        cursor: pointer;
        font-size: 14px;
        border-radius: 6px;
        transition: all 0.15s;
      }

      .tab:hover {
        background: rgba(255, 255, 255, 0.05);
        color: #aaa;
      }

      .tab.active {
        background: rgba(255, 255, 255, 0.1);
        color: #e0e0e0;
      }

      .content {
        flex: 1;
        display: grid;
        grid-template-columns: 1fr 4px var(--editor-width, 700px);
        gap: 0;
        overflow: hidden;
      }

      .resize-divider {
        width: 4px;
        background: transparent;
        cursor: col-resize;
        transition: background 0.2s;
      }

      .resize-divider:hover,
      .resize-divider.active {
        background: rgba(255, 255, 255, 0.2);
      }

      .main-panel {
        overflow: auto;
        background: rgba(0, 0, 0, 0.2);
        border-radius: 8px;
      }

      .detail-panel {
        background: rgba(0, 0, 0, 0.2);
        border-radius: 8px;
        overflow: hidden;
        margin-left: 12px;
      }

      @media (max-width: 1200px) {
        .content {
          grid-template-columns: 1fr;
        }

        .detail-panel,
        .resize-divider {
          display: none;
        }
      }

      .change-indicator {
        display: flex;
        align-items: center;
        gap: 6px;
        padding: 4px 8px;
        background: rgba(34, 197, 94, 0.2);
        border-radius: 4px;
        font-size: 11px;
        color: #4ade80;
      }

      .change-indicator.pulse {
        animation: pulse-green 1s ease-in-out;
      }

      @keyframes pulse-green {
        0% { background: rgba(34, 197, 94, 0.4); }
        100% { background: rgba(34, 197, 94, 0.2); }
      }

      .stream-status {
        display: flex;
        align-items: center;
        gap: 4px;
        font-size: 11px;
        color: #888;
      }

      .stream-dot {
        width: 6px;
        height: 6px;
        border-radius: 50%;
        background: #888;
      }

      .stream-dot.connected {
        background: #22c55e;
      }
    `,
  ];

  async connectedCallback() {
    super.connectedCallback();
    await this.loadStats();
    // Subscription is handled by updated() when databaseName/collectionName are set.
    // Only track connection status for UI indicator here.
    this.connectionSubscription = changeStreamService.connectionStatus$.subscribe((status) => {
      this.isStreamConnected = status === 'connected';
    });
  }

  disconnectedCallback() {
    super.disconnectedCallback();
    this.unsubscribeFromChanges();
    if (this.connectionSubscription) {
      this.connectionSubscription.unsubscribe();
      this.connectionSubscription = null;
    }
  }

  updated(changedProperties: Map<string, unknown>) {
    if (changedProperties.has('databaseName') || changedProperties.has('collectionName')) {
      this.loadStats();
      this.selectedDocumentId = '';
      this.recentChangeCount = 0;
      // Re-subscribe to the new collection
      this.unsubscribeFromChanges();
      this.subscribeToChanges();
    }
  }

  private async subscribeToChanges() {
    if (!this.databaseName || !this.collectionName) return;

    try {
      // Set up RxJS listener first so events aren't missed on reconnect
      if (!this.changeSubscription) {
        this.changeSubscription = changeStreamService
          .getCollectionChanges(this.databaseName, this.collectionName)
          .subscribe((event) => this.handleChange(event));
      }

      // Subscribe on the server side (will auto-connect if needed)
      const success = await changeStreamService.subscribeToCollection(this.databaseName, this.collectionName);
      this.isStreamConnected = success;
    } catch (error) {
      console.warn('[MongoBrowser] Failed to subscribe to changes:', error);
      this.isStreamConnected = false;
    }
  }

  private unsubscribeFromChanges() {
    if (this.changeSubscription) {
      this.changeSubscription.unsubscribe();
      this.changeSubscription = null;
    }
    if (this.databaseName && this.collectionName) {
      changeStreamService.unsubscribeFromCollection(this.databaseName, this.collectionName);
    }
    this.isStreamConnected = false;
  }

  private handleChange(event: IMongoChangeEvent) {
    console.log('[MongoBrowser] Received change:', event);
    this.recentChangeCount++;

    // Refresh stats to reflect changes
    this.loadStats();

    // Notify the documents component to refresh
    const documentsEl = this.shadowRoot?.querySelector('tsview-mongo-documents') as any;
    if (documentsEl?.refresh) {
      documentsEl.refresh();
    }
  }

  private async loadStats() {
    if (!this.databaseName || !this.collectionName) return;

    try {
      this.stats = await apiService.getCollectionStats(this.databaseName, this.collectionName);
    } catch (err) {
      console.error('Error loading stats:', err);
      this.stats = null;
    }
  }

  private setActiveTab(tab: TViewTab) {
    this.activeTab = tab;
  }

  private handleDocumentSelected(e: CustomEvent) {
    this.selectedDocumentId = e.detail.documentId;
  }

  private startEditorResize = (e: MouseEvent) => {
    e.preventDefault();
    this.isResizingEditor = true;
    document.addEventListener('mousemove', this.handleEditorResize);
    document.addEventListener('mouseup', this.endEditorResize);
  };

  private handleEditorResize = (e: MouseEvent) => {
    if (!this.isResizingEditor) return;
    const contentEl = this.shadowRoot?.querySelector('.content');
    if (!contentEl) return;
    const containerRect = contentEl.getBoundingClientRect();
    const newWidth = Math.min(Math.max(containerRect.right - e.clientX, 250), 1000);
    this.editorWidth = newWidth;
  };

  private endEditorResize = () => {
    this.isResizingEditor = false;
    document.removeEventListener('mousemove', this.handleEditorResize);
    document.removeEventListener('mouseup', this.endEditorResize);
  };

  render() {
    return html`
      <div class="browser-container">
        <div class="header">
          <div class="collection-info">
            <span class="collection-title">${this.collectionName}</span>
            ${this.stats
              ? html`
                  <div class="collection-stats">
                    <span class="stat-item">${formatCount(this.stats.count)} docs</span>
                    <span class="stat-item">${formatSize(this.stats.size)}</span>
                    <span class="stat-item">${this.stats.indexCount} indexes</span>
                  </div>
                `
              : ''}
            <div class="stream-status">
              <span class="stream-dot ${this.isStreamConnected ? 'connected' : ''}"></span>
              ${this.isStreamConnected ? 'Live' : 'Offline'}
            </div>
            ${this.recentChangeCount > 0
              ? html`
                  <div class="change-indicator pulse">
                    ${this.recentChangeCount} change${this.recentChangeCount > 1 ? 's' : ''}
                  </div>
                `
              : ''}
          </div>

          <div class="tabs">
            <button
              class="tab ${this.activeTab === 'documents' ? 'active' : ''}"
              @click=${() => this.setActiveTab('documents')}
            >
              Documents
            </button>
            <button
              class="tab ${this.activeTab === 'indexes' ? 'active' : ''}"
              @click=${() => this.setActiveTab('indexes')}
            >
              Indexes
            </button>
            <button
              class="tab ${this.activeTab === 'aggregation' ? 'active' : ''}"
              @click=${() => this.setActiveTab('aggregation')}
            >
              Aggregation
            </button>
          </div>
        </div>

        <div class="content" style="--editor-width: ${this.editorWidth}px">
          <div class="main-panel">
            ${this.activeTab === 'documents'
              ? html`
                  <tsview-mongo-documents
                    .databaseName=${this.databaseName}
                    .collectionName=${this.collectionName}
                    @document-selected=${this.handleDocumentSelected}
                  ></tsview-mongo-documents>
                `
              : this.activeTab === 'indexes'
                ? html`
                    <tsview-mongo-indexes
                      .databaseName=${this.databaseName}
                      .collectionName=${this.collectionName}
                    ></tsview-mongo-indexes>
                  `
                : html`
                    <div style="padding: 24px; text-align: center; color: #666;">
                      Aggregation pipeline builder coming soon
                    </div>
                  `}
          </div>

          <div
            class="resize-divider ${this.isResizingEditor ? 'active' : ''}"
            @mousedown=${this.startEditorResize}
          ></div>

          <div class="detail-panel">
            <tsview-mongo-document
              .databaseName=${this.databaseName}
              .collectionName=${this.collectionName}
              .documentId=${this.selectedDocumentId}
            ></tsview-mongo-document>
          </div>
        </div>
      </div>
    `;
  }
}
