import * as plugins from '../plugins.js';
import { apiService, changeStreamService, type IS3ChangeEvent } from '../services/index.js';
import { themeStyles } from '../styles/index.js';

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

type TViewType = 'columns' | 'keys';

@customElement('tsview-s3-browser')
export class TsviewS3Browser extends DeesElement {
  @property({ type: String })
  public accessor bucketName: string = '';

  @state()
  private accessor viewType: TViewType = 'columns';

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

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

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

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

  @state()
  private accessor isResizingPreview: 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%;
      }

      .toolbar {
        display: flex;
        align-items: center;
        gap: 12px;
        padding: 12px;
        background: rgba(0, 0, 0, 0.2);
        border-radius: 8px;
        margin-bottom: 16px;
      }

      .breadcrumb {
        display: flex;
        align-items: center;
        gap: 4px;
        flex: 1;
        font-size: 14px;
        color: #999;
      }

      .breadcrumb-item {
        cursor: pointer;
        padding: 4px 8px;
        border-radius: 4px;
        transition: background 0.15s;
      }

      .breadcrumb-item:hover {
        background: rgba(255, 255, 255, 0.1);
        color: #fff;
      }

      .breadcrumb-separator {
        color: #555;
      }

      .view-toggle {
        display: flex;
        gap: 4px;
      }

      .view-btn {
        padding: 6px 12px;
        background: transparent;
        border: 1px solid #444;
        color: #888;
        border-radius: 4px;
        cursor: pointer;
        font-size: 13px;
        transition: all 0.15s;
      }

      .view-btn:hover {
        border-color: #666;
        color: #aaa;
      }

      .view-btn.active {
        background: rgba(255, 255, 255, 0.1);
        border-color: #404040;
        color: #e0e0e0;
      }

      .content {
        flex: 1;
        display: grid;
        grid-template-columns: 1fr;
        gap: 0;
        overflow: hidden;
      }

      .content.has-preview {
        grid-template-columns: 1fr 4px var(--preview-width, 700px);
      }

      .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-view {
        overflow: auto;
        background: rgba(0, 0, 0, 0.2);
        border-radius: 8px;
      }

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

      @media (max-width: 1024px) {
        .content,
        .content.has-preview {
          grid-template-columns: 1fr;
        }

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

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

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

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

      .change-indicator {
        display: flex;
        align-items: center;
        gap: 6px;
        padding: 4px 8px;
        background: rgba(245, 158, 11, 0.2);
        border-radius: 4px;
        font-size: 11px;
        color: #f59e0b;
        margin-right: 12px;
      }

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

      @keyframes pulse-orange {
        0% { background: rgba(245, 158, 11, 0.4); }
        100% { background: rgba(245, 158, 11, 0.2); }
      }
    `,
  ];

  async connectedCallback() {
    super.connectedCallback();
    // Subscription is handled by updated() when bucketName is 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;
    }
  }

  private setViewType(type: TViewType) {
    this.viewType = type;
  }

  private navigateToPrefix(prefix: string) {
    this.currentPrefix = prefix;
    this.selectedKey = '';
  }

  private handleKeySelected(e: CustomEvent) {
    this.selectedKey = e.detail.key;
  }

  private handleNavigate(e: CustomEvent) {
    this.navigateToPrefix(e.detail.prefix);
  }

  private handleObjectDeleted(e: CustomEvent) {
    this.selectedKey = '';
    // Increment refresh key to trigger re-render of child components
    this.refreshKey++;
  }

  updated(changedProperties: Map<string, unknown>) {
    if (changedProperties.has('bucketName')) {
      // Clear selection when bucket changes
      this.selectedKey = '';
      this.currentPrefix = '';
      this.recentChangeCount = 0;
      // Re-subscribe to the new bucket
      this.unsubscribeFromChanges();
      this.subscribeToChanges();
    }
  }

  private async subscribeToChanges() {
    if (!this.bucketName) return;

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

      // Subscribe on the server side (will auto-connect if needed)
      const success = await changeStreamService.subscribeToBucket(this.bucketName, this.currentPrefix || undefined);
      this.isStreamConnected = success;
    } catch (error) {
      console.warn('[S3Browser] Failed to subscribe to changes:', error);
      this.isStreamConnected = false;
    }
  }

  private unsubscribeFromChanges() {
    if (this.changeSubscription) {
      this.changeSubscription.unsubscribe();
      this.changeSubscription = null;
    }
    if (this.bucketName) {
      changeStreamService.unsubscribeFromBucket(this.bucketName, this.currentPrefix || undefined);
    }
    this.isStreamConnected = false;
  }

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

    // Trigger refresh of child components
    this.refreshKey++;
  }

  private startPreviewResize = (e: MouseEvent) => {
    e.preventDefault();
    this.isResizingPreview = true;
    document.addEventListener('mousemove', this.handlePreviewResize);
    document.addEventListener('mouseup', this.endPreviewResize);
  };

  private handlePreviewResize = (e: MouseEvent) => {
    if (!this.isResizingPreview) 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.previewWidth = newWidth;
  };

  private endPreviewResize = () => {
    this.isResizingPreview = false;
    document.removeEventListener('mousemove', this.handlePreviewResize);
    document.removeEventListener('mouseup', this.endPreviewResize);
  };

  render() {
    const breadcrumbParts = this.currentPrefix
      ? this.currentPrefix.split('/').filter(Boolean)
      : [];

    return html`
      <div class="browser-container">
        <div class="toolbar">
          <div class="breadcrumb">
            <span
              class="breadcrumb-item"
              @click=${() => this.navigateToPrefix('')}
            >
              ${this.bucketName}
            </span>
            ${breadcrumbParts.map((part, index) => {
              const prefix = breadcrumbParts.slice(0, index + 1).join('/') + '/';
              return html`
                <span class="breadcrumb-separator">/</span>
                <span
                  class="breadcrumb-item"
                  @click=${() => this.navigateToPrefix(prefix)}
                >
                  ${part}
                </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 class="view-toggle">
            <button
              class="view-btn ${this.viewType === 'columns' ? 'active' : ''}"
              @click=${() => this.setViewType('columns')}
            >
              Columns
            </button>
            <button
              class="view-btn ${this.viewType === 'keys' ? 'active' : ''}"
              @click=${() => this.setViewType('keys')}
            >
              List
            </button>
          </div>
        </div>

        <div class="content ${this.selectedKey ? 'has-preview' : ''}" style="--preview-width: ${this.previewWidth}px">
          <div class="main-view">
            ${this.viewType === 'columns'
              ? html`
                  <tsview-s3-columns
                    .bucketName=${this.bucketName}
                    .currentPrefix=${this.currentPrefix}
                    .refreshKey=${this.refreshKey}
                    @key-selected=${this.handleKeySelected}
                    @navigate=${this.handleNavigate}
                  ></tsview-s3-columns>
                `
              : html`
                  <tsview-s3-keys
                    .bucketName=${this.bucketName}
                    .currentPrefix=${this.currentPrefix}
                    .refreshKey=${this.refreshKey}
                    @key-selected=${this.handleKeySelected}
                    @navigate=${this.handleNavigate}
                  ></tsview-s3-keys>
                `}
          </div>

          ${this.selectedKey
            ? html`
                <div
                  class="resize-divider ${this.isResizingPreview ? 'active' : ''}"
                  @mousedown=${this.startPreviewResize}
                ></div>
                <div class="preview-panel">
                  <tsview-s3-preview
                    .bucketName=${this.bucketName}
                    .objectKey=${this.selectedKey}
                    @object-deleted=${this.handleObjectDeleted}
                  ></tsview-s3-preview>
                </div>
              `
            : ''}
        </div>
      </div>
    `;
  }
}
