/**
 * CanvasEventLogger — silently logs TLDraw canvas activity during transcription sessions.
 * Attaches to the editor instance and buffers events, flushing to API every 5 seconds.
 */

import { Editor, TLStoreEventInfo } from '@tldraw/tldraw';
import { useTranscriptionStore } from '../../stores/transcriptionStore';

export class CanvasEventLogger {
  private editor: Editor | null = null;
  private sessionId: string | null = null;
  private buffer: Array<{
    eventType: string;
    payload: Record<string, any>;
    sessionElapsedSeconds?: number;
    pageId?: string;
    shapeIds?: string[];
    snapshotUrl?: string;
  }> = [];
  private flushInterval: ReturnType<typeof setInterval> | null = null;
  private snapshotInterval: ReturnType<typeof setInterval> | null = null;
  private snapshotIntervalMs: number = 60000; // 60 seconds default
  private isAttached: boolean = false;

  /**
   * Attach the logger to a TLDraw editor instance.
   * Starts buffering events and periodic snapshots.
   */
  attach(editor: Editor, sessionId: string): void {
    if (this.isAttached) {
      this.detach();
    }

    this.editor = editor;
    this.sessionId = sessionId;
    this.isAttached = true;

    // Listen to store changes for shape/page events
    const unsubscribe = editor.store.listen(
      (info: TLStoreEventInfo) => this.onStoreChange(info),
      { source: 'user' } // Only user-initiated changes, not programmatic
    );

    // Store unsubscribe function for cleanup
    (editor as any).__canvasEventLoggerUnsubscribe = unsubscribe;

    // Start periodic flush
    this.flushInterval = setInterval(() => this.flush(), 5000);

    // Start periodic snapshots
    this.snapshotInterval = setInterval(() => this.captureSnapshot(), this.snapshotIntervalMs);

    // Capture initial snapshot
    this.captureSnapshot();

    console.log('[CanvasEventLogger] Attached to editor for session', sessionId);
  }

  /**
   * Detach the logger from the editor.
   * Flushes any pending events and stops intervals.
   */
  detach(): void {
    if (!this.isAttached) return;

    // Flush remaining events
    this.flush();

    // Stop intervals
    if (this.flushInterval) {
      clearInterval(this.flushInterval);
      this.flushInterval = null;
    }
    if (this.snapshotInterval) {
      clearInterval(this.snapshotInterval);
      this.snapshotInterval = null;
    }

    // Unsubscribe from store listener
    if (this.editor && (this.editor as any).__canvasEventLoggerUnsubscribe) {
      (this.editor as any).__canvasEventLoggerUnsubscribe();
      delete (this.editor as any).__canvasEventLoggerUnsubscribe;
    }

    this.editor = null;
    this.sessionId = null;
    this.isAttached = false;

    console.log('[CanvasEventLogger] Detached from editor');
  }

  /**
   * Handle store changes to detect canvas events.
   */
  private onStoreChange(info: TLStoreEventInfo): void {
    if (!this.editor || !this.sessionId) return;

    const { added, removed, updated } = info;
    const elapsedSeconds = useTranscriptionStore.getState().elapsedSeconds;

    // Handle shape creation
    if (added.size > 0) {
      for (const [id, shape] of added) {
        this.buffer.push({
          eventType: 'shape_created',
          payload: {
            shapeId: id,
            shapeType: shape.type,
            pageId: this.editor?.currentPageId,
          },
          sessionElapsedSeconds: elapsedSeconds,
          pageId: this.editor?.currentPageId,
          shapeIds: [id],
        });
      }
    }

    // Handle shape deletion
    if (removed.size > 0) {
      for (const [id] of removed) {
        this.buffer.push({
          eventType: 'shape_deleted',
          payload: { shapeId: id },
          sessionElapsedSeconds: elapsedSeconds,
          shapeIds: [id],
        });
      }
    }

    // Handle page changes
    if (updated.size > 0) {
      for (const [id, { old, new: updatedItem }] of updated) {
        if (id === 'page' && old?.currentPageId !== updatedItem?.currentPageId) {
          this.buffer.push({
            eventType: 'page_changed',
            payload: {
              fromPageId: old?.currentPageId,
              toPageId: updatedItem?.currentPageId,
            },
            sessionElapsedSeconds: elapsedSeconds,
            pageId: updatedItem?.currentPageId,
          });

          // Capture snapshot on page change
          this.captureSnapshot();
        }
      }
    }

    // Handle ink/draw strokes
    for (const [id, shape] of added) {
      if (shape.type === 'draw') {
        this.buffer.push({
          eventType: 'ink_added',
          payload: { shapeId: id, strokeCount: (shape as any).points?.length || 0 },
          sessionElapsedSeconds: elapsedSeconds,
          shapeIds: [id],
        });
      }
    }

    // Flush immediately for significant events (page changes, ink)
    if (this.buffer.length >= 5) {
      this.flush();
    }
  }

  /**
   * Capture a snapshot of the current canvas state.
   * Uploads to Supabase Storage and returns the URL.
   */
  private async captureSnapshot(): Promise<string | null> {
    if (!this.editor || !this.sessionId) return null;

    try {
      // Get SVG element from editor
      const svgElement = this.editor.svg?.current;
      if (!svgElement) {
        console.warn('[CanvasEventLogger] No SVG element available for snapshot');
        return null;
      }

      // Serialize SVG to string
      const svgString = new XMLSerializer().serializeToString(svgElement);
      const blob = new Blob([svgString], { type: 'image/svg+xml' });

      // For now, store as base64 in the event payload
      // In Phase 3, upload to Supabase Storage
      const reader = new FileReader();
      const base64Data = await new Promise<string>((resolve) => {
        reader.onloadend = () => resolve(reader.result as string);
        reader.readAsDataURL(blob);
      });

      // Store snapshot URL reference (will be replaced with actual storage URL in Phase 3)
      const snapshotUrl = `canvas-snapshots/${this.sessionId}/${Date.now()}.svg`;

      this.buffer.push({
        eventType: 'canvas_snapshot',
        payload: { snapshotUrl, pageId: this.editor.currentPageId },
        sessionElapsedSeconds: useTranscriptionStore.getState().elapsedSeconds,
        pageId: this.editor.currentPageId,
        snapshotUrl,
      });

      console.log('[CanvasEventLogger] Snapshot captured:', snapshotUrl);
      return snapshotUrl;
    } catch (error) {
      console.error('[CanvasEventLogger] Failed to capture snapshot:', error);
      return null;
    }
  }

  /**
   * Flush buffered events to the API.
   */
  private async flush(): void {
    if (this.buffer.length === 0) return;

    const events = [...this.buffer];
    this.buffer = [];

    try {
      const response = await fetch('http://192.168.0.64:8000/transcribe/canvas-events', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          // TODO: Add auth header in Phase 3
        },
        body: JSON.stringify({ events }),
      });

      if (!response.ok) {
        console.error('[CanvasEventLogger] Failed to flush canvas events:', response.status);
      } else {
        console.log('[CanvasEventLogger] Flushed', events.length, 'events');
      }
    } catch (error) {
      console.error('[CanvasEventLogger] Error flushing canvas events:', error);
      // Re-queue events for retry
      this.buffer = [...events, ...this.buffer];
    }
  }

  /**
   * Manually trigger a snapshot capture.
   */
  async captureSnapshotNow(): Promise<string | null> {
    return this.captureSnapshot();
  }

  /**
   * Get the current buffer size (for debugging).
   */
  getBufferSize(): number {
    return this.buffer.length;
  }
}
