/**
 * ElectronCheckoutConfirmationAdapter
 * Implements ICheckoutConfirmationPort using Electron IPC for main-renderer communication.
 */

import type { BrowserWindow } from 'electron';
import { ipcMain } from 'electron';
import { Result } from '@core/shared/application/Result';
import type { CheckoutConfirmationPort } from '../../../application/ports/CheckoutConfirmationPort';
import type { CheckoutConfirmationRequestDTO } from '../../../application/dto/CheckoutConfirmationRequestDTO';
import { CheckoutConfirmation } from '../../../domain/value-objects/CheckoutConfirmation';

export class ElectronCheckoutConfirmationAdapter implements CheckoutConfirmationPort {
  private mainWindow: BrowserWindow;
  private pendingConfirmation: {
    resolve: (confirmation: CheckoutConfirmation) => void;
    reject: (error: Error) => void;
    timeoutId: NodeJS.Timeout;
  } | null = null;

  constructor(mainWindow: BrowserWindow) {
    this.mainWindow = mainWindow;
    this.setupIpcHandlers();
  }

  private setupIpcHandlers(): void {
    // Listen for confirmation response from renderer
    ipcMain.on('checkout:confirm', (_event, decision: 'confirmed' | 'cancelled' | 'timeout') => {
      if (!this.pendingConfirmation) {
        return;
      }

      // Clear timeout
      clearTimeout(this.pendingConfirmation.timeoutId);

      // Create confirmation based on decision
      const confirmation = CheckoutConfirmation.create(decision);
      this.pendingConfirmation.resolve(confirmation);
      this.pendingConfirmation = null;
    });
  }

  async requestCheckoutConfirmation(
    request: CheckoutConfirmationRequestDTO
  ): Promise<Result<CheckoutConfirmation>> {
    try {
      // Only allow one pending confirmation at a time
      if (this.pendingConfirmation) {
        return Result.err(new Error('Confirmation already pending'));
      }

      // Send request to renderer
      this.mainWindow.webContents.send('checkout:request-confirmation', {
        price: request.price.toDisplayString(),
        state: request.state.isReady() ? 'ready' : 'insufficient_funds',
        sessionMetadata: request.sessionMetadata,
        timeoutMs: request.timeoutMs,
      });

      // Wait for response with timeout
      const confirmation = await new Promise<CheckoutConfirmation>((resolve, reject) => {
        const timeoutId = setTimeout(() => {
          this.pendingConfirmation = null;
          const timeoutConfirmation = CheckoutConfirmation.create('timeout');
          resolve(timeoutConfirmation);
        }, request.timeoutMs);

        this.pendingConfirmation = {
          resolve,
          reject,
          timeoutId,
        };
      });

      return Result.ok(confirmation);
    } catch (error) {
      this.pendingConfirmation = null;
      return Result.err(
        error instanceof Error ? error : new Error('Failed to request confirmation')
      );
    }
  }

  public cleanup(): void {
    if (this.pendingConfirmation) {
      clearTimeout(this.pendingConfirmation.timeoutId);
      this.pendingConfirmation = null;
    }
    ipcMain.removeAllListeners('checkout:confirm');
  }
}