import * as shared from './shared/index.js';
import * as appstate from '../appstate.js';

import {
  DeesElement,
  customElement,
  html,
  state,
  css,
  cssManager,
} from '@design.estate/dees-element';

@customElement('ops-view-logs')
export class OpsViewLogs extends DeesElement {
  @state()
  accessor logState: appstate.ILogState = {
    recentLogs: [],
    isStreaming: false,
    filters: {},
  };

  private lastPushedCount = 0;

  constructor() {
    super();
    const subscription = appstate.logStatePart
      .select((stateArg) => stateArg)
      .subscribe((logState) => {
        this.logState = logState;
      });
    this.rxSubscriptions.push(subscription);
  }

  public static styles = [
    cssManager.defaultStyles,
    shared.viewHostCss,
    css``,
  ];

  public render() {
    return html`
      <dees-heading level="3">Logs</dees-heading>

      <dees-chart-log
        .label=${'Application Logs'}
        .autoScroll=${true}
        .maxEntries=${2000}
        .showMetrics=${true}
      ></dees-chart-log>
    `;
  }

  async connectedCallback() {
    super.connectedCallback();
    this.lastPushedCount = 0;
    // Only fetch if state is empty (streaming will handle new entries)
    if (this.logState.recentLogs.length === 0) {
      await appstate.logStatePart.dispatchAction(appstate.fetchRecentLogsAction, { limit: 100 });
    }
  }

  async updated(changedProperties: Map<string, any>) {
    super.updated(changedProperties);
    if (changedProperties.has('logState')) {
      this.pushLogsToChart();
    }
  }

  private async pushLogsToChart() {
    const chartLog = this.shadowRoot?.querySelector('dees-chart-log') as any;
    if (!chartLog) return;

    // Ensure the chart element has finished its own initialization
    await chartLog.updateComplete;

    // Wait for xterm terminal to finish initializing (CDN load)
    if (!chartLog.terminalReady) {
      await new Promise<void>((resolve) => {
        let attempts = 0;
        const maxAttempts = 200; // 200 * 50ms = 10 seconds
        const check = () => {
          if (chartLog.terminalReady) { resolve(); return; }
          if (++attempts >= maxAttempts) {
            console.warn('ops-view-logs: terminal ready timeout after 10s');
            resolve(); // resolve gracefully to avoid blocking
            return;
          }
          setTimeout(check, 50);
        };
        check();
      });
    }

    const allEntries = this.getMappedLogEntries();
    if (this.lastPushedCount === 0 && allEntries.length > 0) {
      // Initial load: push all entries
      chartLog.updateLog(allEntries);
      this.lastPushedCount = allEntries.length;
    } else if (allEntries.length > this.lastPushedCount) {
      // Incremental: only push new entries
      const newEntries = allEntries.slice(this.lastPushedCount);
      chartLog.updateLog(newEntries);
      this.lastPushedCount = allEntries.length;
    }
  }

  private getMappedLogEntries() {
    return this.logState.recentLogs.map((log) => ({
      timestamp: new Date(log.timestamp).toISOString(),
      level: log.level as 'debug' | 'info' | 'warn' | 'error',
      message: log.message,
      source: log.category,
    }));
  }

}
