import { PaywallConfig } from '@unified-video/core';
import { EmailAuthController, EmailAuthControllerOptions } from './EmailAuthController';

export type PaywallGateway = {
  id: string;
  name: string;
  description?: string;
  icon?: string;
  color?: string;
};

export type PaymentLinkConfig = {
  endpoint: string;
  method?: 'POST' | 'GET';
  headers?: Record<string, string>;
  mapRequest?: (paymentData: any) => any;
  mapResponse?: (response: any) => { url: string; orderId?: string; };
  popup?: {
    width?: number;
    height?: number;
    features?: string;
  };
};

export type PaywallControllerOptions = {
  getOverlayContainer: () => HTMLElement | null;
  onResume: (accessInfo?: { accessGranted?: boolean; paymentSuccessful?: boolean }) => void;
  onShow?: () => void;
  onClose?: () => void;
  // Custom payment handlers
  onPaymentRequested?: (gateway: PaywallGateway, paymentData: any) => Promise<void> | void;
  onPaymentSuccess?: (gateway: PaywallGateway, result: any) => void;
  onPaymentError?: (gateway: PaywallGateway, error: any) => void;
  onPaymentCancel?: (gateway: PaywallGateway) => void;
};

export class PaywallController {
  private config: PaywallConfig | null = null;
  private opts: PaywallControllerOptions;
  private overlayEl: HTMLElement | null = null;
  private gatewayStepEl: HTMLElement | null = null;
  private popup: Window | null = null;
  private emailAuth: EmailAuthController | null = null;
  private authenticatedUserId: string | null = null;
  private sessionToken: string | null = null;
  private currentGateway: PaywallGateway | null = null; // Track current payment gateway

  constructor(config: PaywallConfig | null, opts: PaywallControllerOptions) {
    this.config = config;
    this.opts = opts;
    
    // Initialize EmailAuthController if email auth is enabled
    this.initializeEmailAuth();
    
    // Don't check authentication immediately - allow free preview first
    // Authentication will be triggered when free preview ends
    
    try {
      window.addEventListener('message', this.onMessage, false);
    } catch (_) {}
  }

  updateConfig(config: PaywallConfig | null) {
    // Defensive logic: if new config is null/undefined but we have a working email auth,
    // preserve the email auth instance to prevent destruction during re-initialization
    const hadWorkingEmailAuth = this.config?.emailAuth?.enabled && !!this.emailAuth;
    const newConfigLacksEmailAuth = !config?.emailAuth?.enabled;
    
    if (hadWorkingEmailAuth && newConfigLacksEmailAuth) {
      console.log('[PaywallController] Preserving email auth instance during config update');
      // Only update non-email auth related config, keep the email auth part
      this.config = {
        ...config,
        emailAuth: this.config?.emailAuth // Preserve existing email auth config
      };
      
      if (this.emailAuth) {
        this.emailAuth.updateConfig(this.config);
      }
    } else {
      // Normal config update
      this.config = config;
      this.initializeEmailAuth();
      if (this.emailAuth) {
        this.emailAuth.updateConfig(config);
      }
    }
  }

  openOverlay() {
    console.log('[PaywallController] openOverlay called');
    console.log('[PaywallController] config enabled:', this.config?.enabled);
    console.log('[PaywallController] email auth enabled:', this.config?.emailAuth?.enabled);
    console.log('[PaywallController] emailAuth instance:', !!this.emailAuth);
    
    if (!this.config?.enabled) {
      console.log('[PaywallController] Paywall disabled, exiting');
      return;
    }
    
    // Check authentication first if email auth is enabled
    if (this.config.emailAuth?.enabled) {
      console.log('[PaywallController] Email auth is enabled, checking authentication');
      
      // If email auth is enabled but instance doesn't exist, try to initialize it
      if (!this.emailAuth) {
        console.log('[PaywallController] Email auth enabled but no instance found, initializing now');
        this.initializeEmailAuth();
      }
      
      // If still no instance after initialization, show error
      if (!this.emailAuth) {
        console.error('[PaywallController] Failed to initialize email auth, proceeding to payment overlay');
        // Continue to payment overlay as fallback
      } else {
        const isAuthenticated = this.emailAuth.isAuthenticated();
        console.log('[PaywallController] User authenticated:', isAuthenticated);
        
        if (!isAuthenticated) {
          console.log('[PaywallController] User not authenticated, opening email auth modal');
          // Show email authentication modal first
          this.emailAuth.openAuthModal();
          return;
        } else {
          console.log('[PaywallController] User already authenticated, proceeding to payment overlay');
          // Update userId for authenticated user
          this.authenticatedUserId = this.emailAuth.getAuthenticatedUserId() || this.config.userId || null;
          // Update config with authenticated userId for API calls
          if (this.authenticatedUserId && this.config) {
            this.config.userId = this.authenticatedUserId;
          }
        }
      }
    }
    
    // Show payment overlay
    console.log('[PaywallController] Showing payment overlay');
    const root = this.ensureOverlay();
    if (!root) {
      console.log('[PaywallController] Failed to create overlay');
      return;
    }
    
    // Show overlay with proper animation
    root.style.display = 'flex';
    root.classList.add('active');
    
    // Force reflow then fade in with animation
    void root.offsetWidth;
    root.style.opacity = '1';
    
    // Also animate the modal inside
    const modal = root.querySelector('.uvf-paywall-modal') as HTMLElement;
    if (modal) {
      modal.style.transform = 'translateY(0)';
      modal.style.opacity = '1';
    }
    
    console.log('[PaywallController] Payment overlay displayed successfully');
    this.opts.onShow?.();
  }

  closeOverlay() {
    console.log('[PaywallController] closeOverlay called');
    
    // First, close any auth modals that might be open
    if (this.emailAuth) {
      console.log('[PaywallController] Closing auth modal if open');
      this.emailAuth.closeAuthModal();
    }
    
    // Call onClose immediately before animation to ensure security state is reset
    this.opts.onClose?.();
    
    if (this.overlayEl) {
      console.log('[PaywallController] Animating paywall overlay out');
      
      // Immediately hide to prevent user interaction during animation
      this.overlayEl.style.pointerEvents = 'none';
      
      // Animate out
      this.overlayEl.style.opacity = '0';
      const modal = this.overlayEl.querySelector('.uvf-paywall-modal') as HTMLElement;
      if (modal) {
        modal.style.transform = 'translateY(20px)';
        modal.style.opacity = '0';
      }
      
      // Hide after animation
      setTimeout(() => {
        if (this.overlayEl) {
          this.overlayEl.classList.remove('active');
          this.overlayEl.style.display = 'none';
          this.overlayEl.style.pointerEvents = '';
          console.log('[PaywallController] Paywall overlay hidden after animation');
        }
      }, 300); // Match the CSS transition duration
    }
    
    // Also ensure any leftover overlays are cleaned up
    const container = this.opts.getOverlayContainer() || document.body;
    const allOverlays = container.querySelectorAll('.uvf-paywall-overlay, .uvf-auth-overlay');
    allOverlays.forEach((overlay: Element) => {
      const htmlOverlay = overlay as HTMLElement;
      if (htmlOverlay && htmlOverlay.style.display !== 'none') {
        console.log('[PaywallController] Force hiding leftover overlay:', htmlOverlay.className);
        htmlOverlay.style.display = 'none';
        htmlOverlay.classList.remove('active');
      }
    });
  }

  private ensureOverlay(): HTMLElement | null {
    if (this.overlayEl && document.body.contains(this.overlayEl)) return this.overlayEl;

    const container = this.opts.getOverlayContainer() || document.body;
    const ov = document.createElement('div');
    ov.className = 'uvf-paywall-overlay';
    ov.setAttribute('role', 'dialog');
    ov.setAttribute('aria-modal', 'true');
    ov.style.cssText = `
      position: absolute;
      inset: 0;
      background: rgba(0, 0, 0, 0.95);
      z-index: 2147483647;
      display: none;
      align-items: center;
      justify-content: center;
      opacity: 0;
      transition: opacity 0.3s ease;
    `;

    const modal = document.createElement('div');
    modal.className = 'uvf-paywall-modal';
    modal.style.cssText = `
      width: 90vw;
      height: 85vh;
      max-width: 1000px;
      max-height: 700px;
      background: #0f0f10;
      border: 1px solid rgba(255, 255, 255, 0.2);
      border-radius: 16px;
      display: flex;
      flex-direction: column;
      overflow: hidden;
      box-shadow: 
        0 20px 60px rgba(0, 0, 0, 0.7),
        0 0 0 1px rgba(255, 255, 255, 0.1);
      transform: translateY(20px);
      opacity: 0;
      transition: transform 0.3s ease, opacity 0.3s ease;
    `;

    const header = document.createElement('div');
    header.style.cssText = 'display:flex;gap:16px;align-items:center;padding:16px 20px;border-bottom:1px solid rgba(255,255,255,0.1)';
    const hTitle = document.createElement('div');
    hTitle.textContent = (this.config?.branding?.title || 'Continue watching');
    hTitle.style.cssText = 'color:#fff;font-size:18px;font-weight:700';
    const hDesc = document.createElement('div');
    hDesc.textContent = (this.config?.branding?.description || 'Rent to continue watching this video.');
    hDesc.style.cssText = 'color:rgba(255,255,255,0.75);font-size:14px;margin-top:4px';
    const headerTextWrap = document.createElement('div');
    headerTextWrap.appendChild(hTitle); headerTextWrap.appendChild(hDesc);

    header.appendChild(headerTextWrap);

    const content = document.createElement('div');
    content.style.cssText = 'flex:1;display:flex;align-items:center;justify-content:center;padding:20px;';

    const intro = document.createElement('div');
    intro.style.cssText = 'display:flex;flex-direction:column;gap:16px;align-items:center;justify-content:center;';
    const msg = document.createElement('div');
    msg.textContent = 'Free preview ended. Rent to continue watching.';
    msg.style.cssText = 'color:#fff;font-size:16px;';
    const rentBtn = document.createElement('button');
    rentBtn.textContent = 'Rent Now';
    rentBtn.className = 'uvf-btn-primary';
    rentBtn.style.cssText = 'background:linear-gradient(135deg,#ff4d4f,#d9363e);color:#fff;border:1px solid rgba(255,77,79,0.6);border-radius:999px;padding:10px 18px;cursor:pointer;';
    rentBtn.addEventListener('click', () => this.showGateways());
    intro.appendChild(msg); intro.appendChild(rentBtn);

    const step = document.createElement('div');
    step.style.cssText = 'display:none;flex-direction:column;gap:16px;align-items:center;justify-content:center;';
    this.gatewayStepEl = step;

    content.appendChild(intro);
    content.appendChild(step);
    modal.appendChild(header); modal.appendChild(content);
    ov.appendChild(modal);
    container.appendChild(ov);
    this.overlayEl = ov;
    return ov;
  }

  /**
   * Completely destroy and remove all overlays
   */
  destroyOverlays() {
    console.log('[PaywallController] destroyOverlays called');
    
    // Close and destroy auth modal
    if (this.emailAuth) {
      this.emailAuth.closeAuthModal();
    }
    
    // Remove paywall overlay
    if (this.overlayEl && this.overlayEl.parentNode) {
      this.overlayEl.parentNode.removeChild(this.overlayEl);
      this.overlayEl = null;
    }
    
    // Find and remove any leftover overlays
    const container = this.opts.getOverlayContainer() || document.body;
    const allOverlays = container.querySelectorAll('.uvf-paywall-overlay, .uvf-auth-overlay');
    allOverlays.forEach((overlay: Element) => {
      if (overlay.parentNode) {
        console.log('[PaywallController] Destroying leftover overlay:', overlay.className);
        overlay.parentNode.removeChild(overlay);
      }
    });
  }

  private showGateways() {
    if (!this.config) {
      console.error('[PaywallController] No config found in showGateways');
      return;
    }
    
    console.log('[PaywallController] showGateways called');
    console.log('[PaywallController] Config gateways:', this.config.gateways);
    
    this.gatewayStepEl!.innerHTML = '';
    this.gatewayStepEl!.style.display = 'flex';

    const title = document.createElement('div');
    title.textContent = this.config.branding?.paymentTitle || 'Choose a payment method';
    title.style.cssText = 'color:#fff;font-size:16px;margin-bottom:20px;';
    
    const wrap = document.createElement('div');
    wrap.style.cssText = 'display:flex;gap:12px;flex-wrap:wrap;justify-content:center;';

    // Support both legacy string array and new gateway objects
    const gateways = this.getGateways();
    console.log('[PaywallController] Processed gateways:', gateways);
    
    if (gateways.length === 0) {
      console.warn('[PaywallController] No gateways available');
      const errorMsg = document.createElement('div');
      errorMsg.textContent = 'No payment methods available. Please contact support.';
      errorMsg.style.cssText = 'color:#ff6b6b;font-size:14px;text-align:center;padding:20px;';
      wrap.appendChild(errorMsg);
    } else {
      let buttonsAdded = 0;
      for (const gateway of gateways) {
        console.log(`[PaywallController] Creating button for gateway:`, gateway);
        const btn = this.createGatewayButton(gateway);
        btn.addEventListener('click', () => this.handleGatewayClick(gateway));
        wrap.appendChild(btn);
        buttonsAdded++;
      }
      console.log(`[PaywallController] Added ${buttonsAdded} gateway buttons`);
    }
    
    // Hide intro step and show gateway step
    const intro = this.overlayEl?.querySelector('div[style*="display:flex;flex-direction:column;gap:16px;align-items:center;justify-content:center;"]') as HTMLElement;
    if (intro) {
      intro.style.display = 'none';
    }
    
    this.gatewayStepEl!.appendChild(title);
    this.gatewayStepEl!.appendChild(wrap);
    
    console.log('[PaywallController] Gateway step UI updated');
  }

  private getGateways(): PaywallGateway[] {
    if (!this.config?.gateways) return [];
    
    return this.config.gateways.map((g: any) => {
      if (typeof g === 'string') {
        // Legacy support for string arrays
        return this.getLegacyGateway(g);
      }
      // New gateway object format
      return g as PaywallGateway;
    });
  }
  
  private getLegacyGateway(id: string): PaywallGateway {
    const legacyGateways: Record<string, PaywallGateway> = {
      stripe: {
        id: 'stripe',
        name: 'Credit/Debit Card',
        description: 'Pay with Stripe',
        color: '#6772e5'
      },
      cashfree: {
        id: 'cashfree',
        name: 'UPI/Netbanking',
        description: 'Pay with Cashfree',
        color: '#00d4aa'
      },
      payu: {
        id: 'payu',
        name: 'PayU',
        description: 'Pay with PayU',
        color: '#17bf43'
      },
      custom: {
        id: 'custom',
        name: 'Pay Now',
        description: 'Secure Payment',
        color: '#4f9eff'
      }
    };
    
    console.log(`[PaywallController] Converting legacy gateway: ${id}`);
    const gateway = legacyGateways[id] || {
      id,
      name: id.charAt(0).toUpperCase() + id.slice(1),
      description: `Pay with ${id}`,
      color: '#666666'
    };
    console.log(`[PaywallController] Converted to:`, gateway);
    
    return gateway;
  }
  
  private createGatewayButton(gateway: PaywallGateway): HTMLButtonElement {
    const btn = document.createElement('button');
    btn.className = 'uvf-gateway-btn';
    
    // Create button content
    const content = document.createElement('div');
    content.style.cssText = 'display:flex;flex-direction:column;align-items:center;gap:8px;';
    
    // Icon or emoji
    if (gateway.icon) {
      const icon = document.createElement('div');
      icon.innerHTML = gateway.icon;
      icon.style.cssText = 'font-size:24px;';
      content.appendChild(icon);
    }
    
    // Gateway name
    const name = document.createElement('div');
    name.textContent = gateway.name;
    name.style.cssText = 'font-weight:600;font-size:14px;';
    content.appendChild(name);
    
    // Description (optional)
    if (gateway.description) {
      const desc = document.createElement('div');
      desc.textContent = gateway.description;
      desc.style.cssText = 'font-size:12px;opacity:0.8;';
      content.appendChild(desc);
    }
    
    btn.appendChild(content);
    
    // Styling
    const bgColor = gateway.color || '#4f9eff';
    btn.style.cssText = `
      background: linear-gradient(135deg, ${bgColor}, ${this.adjustBrightness(bgColor, -20)});
      color: #fff;
      border: none;
      border-radius: 12px;
      padding: 16px 20px;
      cursor: pointer;
      min-width: 140px;
      transition: transform 0.2s ease, box-shadow 0.2s ease;
      font-family: inherit;
    `;
    
    // Hover effects
    btn.addEventListener('mouseenter', () => {
      btn.style.transform = 'translateY(-2px)';
      btn.style.boxShadow = `0 8px 20px rgba(0,0,0,0.3), 0 4px 8px ${bgColor}40`;
    });
    
    btn.addEventListener('mouseleave', () => {
      btn.style.transform = 'translateY(0)';
      btn.style.boxShadow = 'none';
    });
    
    return btn;
  }
  
  private adjustBrightness(color: string, amount: number): string {
    // Simple color brightness adjustment
    if (!color.startsWith('#')) return color;
    
    const num = parseInt(color.slice(1), 16);
    const r = Math.max(0, Math.min(255, (num >> 16) + amount));
    const g = Math.max(0, Math.min(255, ((num >> 8) & 0x00FF) + amount));
    const b = Math.max(0, Math.min(255, (num & 0x0000FF) + amount));
    
    return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0')}`;
  }

  private async openGateway(gateway: 'stripe' | 'cashfree') {
    try {
      if (!this.config) return;
      const { apiBase, userId, videoId } = this.config;
      const w = Math.min(window.screen.width - 100, this.config.popup?.width || 1000);
      const h = Math.min(window.screen.height - 100, this.config.popup?.height || 800);
      const left = Math.max(0, Math.round((window.screen.width - w) / 2));
      const top = Math.max(0, Math.round((window.screen.height - h) / 2));

      if (gateway === 'stripe') {
        const res = await fetch(`${apiBase}/api/rentals/stripe/checkout-session`, {
          method: 'POST', headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            userId, videoId,
            successUrl: window.location.origin + window.location.pathname + '?rental=success&popup=1',
            cancelUrl: window.location.origin + window.location.pathname + '?rental=cancel&popup=1'
          })
        });
        const data = await res.json();
        if (data?.url) {
          try { this.popup && !this.popup.closed && this.popup.close(); } catch (_) {}
          this.popup = window.open(data.url, 'uvfCheckout', `popup=1,width=${w},height=${h},left=${left},top=${top}`);
          this.startPolling();
        }
        return;
      }

      if (gateway === 'cashfree') {
        const features = `popup=1,width=${w},height=${h},left=${left},top=${top}`;
        // Pre-open a blank popup in direct response to the click to avoid popup blockers
        let pre: Window | null = null;
        try { pre = window.open('', 'uvfCheckout', features); } catch(_) { pre = null; }
        const res = await fetch(`${apiBase}/api/rentals/cashfree/order`, {
          method: 'POST', headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ userId, videoId, returnUrl: window.location.origin + window.location.pathname })
        });
        const data = await res.json();
        if (data?.paymentLink && data?.orderId) {
          try { this.popup && !this.popup.closed && this.popup.close(); } catch (_) {}
          this.popup = pre && !pre.closed ? pre : window.open('', 'uvfCheckout', features);
          try { if (this.popup) this.popup.location.href = data.paymentLink; } catch(_) {}
          (window as any)._uvf_cfOrderId = data.orderId;
          this.startPolling();
        } else {
          // Close the pre-opened popup if we didn't get a link
          try { pre && !pre.closed && pre.close(); } catch(_) {}
        }
        return;
      }
    } catch (_) {
      // noop
    }
  }

  private startPolling() {
    // basic polling to detect entitlement or popup closed; the host page should also listen to postMessage
    const timer = setInterval(async () => {
      if (!this.config) { clearInterval(timer); return; }
      if (this.popup && this.popup.closed) {
        clearInterval(timer);
        // user cancelled; leave overlay open at gateway selection
        this.showGateways();
        return;
      }
    }, 3000);
  }

  // Handle gateway button clicks with flexible routing
  private async handleGatewayClick(gateway: PaywallGateway) {
    try {
      // Track current gateway for message handling
      this.currentGateway = gateway;
      
      console.log(`[PaywallController] Processing payment for gateway: ${gateway.id}`);
      
      // Check if user provided a custom payment handler
      if (this.opts.onPaymentRequested) {
        console.log(`[PaywallController] Using custom handler for gateway: ${gateway.id}`);
        const paymentData = {
          userId: this.authenticatedUserId || this.config?.userId,
          videoId: this.config?.videoId,
          amount: this.config?.pricing?.amount,
          currency: this.config?.pricing?.currency || 'INR',
          gateway: gateway.id,
          sessionToken: this.sessionToken
        };
        
        await this.opts.onPaymentRequested(gateway, paymentData);
        return;
      }
      
      // PRIORITY: Check for payment link configuration first
      // This allows users to override built-in gateways with their own APIs
      const paymentLinkConfig = (this.config as any)?.paymentLink;
      if (paymentLinkConfig?.endpoint) {
        console.log(`[PaywallController] Using payment link configuration for: ${gateway.id}`);
        await this.handlePaymentLink(gateway);
        return;
      }
      
      // Fallback: Handle built-in gateways (Stripe, Cashfree) only if no payment link config
      if (gateway.id === 'stripe' || gateway.id === 'cashfree') {
        console.log(`[PaywallController] Using built-in handler for: ${gateway.id}`);
        await this.openGateway(gateway.id);
        return;
      }
      
      // No handler available
      console.error(`[PaywallController] No payment handler configured for gateway: ${gateway.id}`);
      alert('Payment method not configured. Please contact support.');
      
    } catch (error) {
      console.error(`[PaywallController] Payment error for ${gateway.id}:`, error);
      
      // Notify user of payment error via callback
      if (this.opts.onPaymentError) {
        this.opts.onPaymentError(gateway, error);
      } else {
        alert('Payment failed. Please try again or contact support.');
      }
      
      // Return to gateway selection
      this.showGateways();
    }
  }

  // Option B: config-only payment link handler
  private async handlePaymentLink(gateway: PaywallGateway) {
    const cfg = (this.config as any).paymentLink as PaymentLinkConfig | undefined;
    if (!cfg?.endpoint) throw new Error('paymentLink.endpoint is required');

    const w = Math.min(window.screen.width - 100, cfg.popup?.width || this.config?.popup?.width || 1000);
    const h = Math.min(window.screen.height - 100, cfg.popup?.height || this.config?.popup?.height || 800);
    const left = Math.max(0, Math.round((window.screen.width - w) / 2));
    const top = Math.max(0, Math.round((window.screen.height - h) / 2));
    const features = cfg.popup?.features || `popup=1,width=${w},height=${h},left=${left},top=${top}`;

    // Pre-open popup to avoid blockers
    let pre: Window | null = null;
    try { pre = window.open('', 'uvfCheckout', features); } catch (_) { pre = null; }

    const paymentData = {
      userId: this.authenticatedUserId || this.config?.userId,
      videoId: this.config?.videoId,
      amount: this.config?.pricing?.amount,
      currency: this.config?.pricing?.currency || 'INR',
      metadata: { gateway: gateway.id, sessionToken: this.sessionToken, authenticatedUserId: this.authenticatedUserId }
    };

    // Use user's mapRequest function, or error if none provided
    if (!cfg.mapRequest) {
      throw new Error('paymentLink.mapRequest is required - please provide a function to map payment data to your API format');
    }
    
    console.log('[PaywallController] PaymentData passed to mapRequest:', paymentData);
    const body = cfg.mapRequest(paymentData);
    console.log('[PaywallController] Mapped request body:', body);

    const res = await fetch(cfg.endpoint, {
      method: cfg.method || 'POST',
      headers: { 'Content-Type': 'application/json', ...(cfg.headers || {}) },
      body: (cfg.method || 'POST') === 'POST' ? JSON.stringify(body) : undefined
    });
    
    console.log('[PaywallController] API response status:', res.status, res.statusText);

    const raw = await res.json();
    const mapped = cfg.mapResponse ? cfg.mapResponse(raw) : {
      url: raw?.Payment_Link_URL || raw?.paymentLink || raw?.link_url,
      orderId: raw?.order_id || raw?.orderId
    };

    if (!mapped?.url) {
      // Close pre-opened popup if failed
      try { pre && !pre.closed && pre.close(); } catch (_) {}
      throw new Error(raw?.message || 'Failed to create payment link');
    }

    try { this.popup && !this.popup.closed && this.popup.close(); } catch (_) {}
    this.popup = pre && !pre.closed ? pre : window.open('', 'uvfCheckout', features);
    try { if (this.popup) this.popup.location.href = mapped.url; } catch(_) {}

    // Store orderId and gateway context for later confirmation if needed
    (window as any)._uvf_orderId = mapped.orderId || null;
    (window as any)._uvf_gatewayId = gateway.id;

    // Rely on success_url page to postMessage back with { type:'uvfCheckout', status:'success', orderId, gatewayId }
    this.startPolling();
  }

  private onMessage = async (ev: MessageEvent) => {
    const d: any = ev?.data || {};
    if (!d || d.type !== 'uvfCheckout') return;
    
    try { if (this.popup && !this.popup.closed) this.popup.close(); } catch (_) {}
    this.popup = null;
    
    // Determine which gateway was used based on the message data
    const gateway = this.findGatewayById(d.gatewayId) || this.currentGateway || {
      id: 'unknown',
      name: 'Payment Gateway'
    };
    
    // Clear current gateway after processing
    if (d.status === 'success' || d.status === 'cancel' || d.status === 'error') {
      this.currentGateway = null;
    }
    
    if (d.status === 'cancel') {
      console.log(`[PaywallController] Payment cancelled for gateway: ${gateway.id}`);
      
      // Notify user callback of cancellation
      if (this.opts.onPaymentCancel) {
        this.opts.onPaymentCancel(gateway);
      }
      
      // Return to gateway selection
      this.showGateways();
      return;
    }
    
    if (d.status === 'success') {
      console.log(`[PaywallController] Payment successful for gateway: ${gateway.id}`);
      
      try {
        // Handle built-in gateway verification
        if (d.sessionId && this.config) {
          console.log('[PaywallController] Verifying Stripe session');
          await fetch(`${this.config.apiBase}/api/rentals/stripe/confirm`, {
            method: 'POST', 
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ 
              sessionId: d.sessionId,
              userId: this.authenticatedUserId || this.config.userId,
              videoId: this.config.videoId
            })
          });
        }
        
        if (d.orderId && this.config) {
          console.log('[PaywallController] Verifying Cashfree order');
          await fetch(`${this.config.apiBase}/api/rentals/cashfree/verify?orderId=${encodeURIComponent(d.orderId)}&userId=${encodeURIComponent(this.authenticatedUserId || this.config.userId || '')}&videoId=${encodeURIComponent(this.config.videoId || '')}`);
        }
        
        // For custom payment links or other gateways, verification might be handled differently
        // The success callback will be triggered regardless
        
      } catch (error) {
        console.error('[PaywallController] Payment verification failed:', error);
        
        // Notify error callback
        if (this.opts.onPaymentError) {
          this.opts.onPaymentError(gateway, error);
          return;
        }
      }
      
      console.log('[PaywallController] Payment verification completed, proceeding with success flow');
      
      // Notify success callback
      if (this.opts.onPaymentSuccess) {
        console.log('[PaywallController] Calling onPaymentSuccess callback');
        this.opts.onPaymentSuccess(gateway, {
          sessionId: d.sessionId,
          orderId: d.orderId,
          transactionId: d.transactionId,
          ...d // Pass all data from the message
        });
      }
      
      // Close overlay and resume playbook
      console.log('[PaywallController] Closing overlay and resuming playbook');
      
      // Use more aggressive cleanup to ensure all overlays are removed
      this.destroyOverlays();
      
      // Small delay to ensure DOM cleanup is complete before resuming
      setTimeout(() => {
        this.opts.onResume();
      }, 50);
      
      return;
    }
    
    // Handle error status
    if (d.status === 'error') {
      console.error(`[PaywallController] Payment error for gateway: ${gateway.id}`, d.error);
      
      if (this.opts.onPaymentError) {
        this.opts.onPaymentError(gateway, d.error || 'Payment failed');
      }
      
      // Return to gateway selection
      this.showGateways();
    }
  };
  
  // Helper method to find gateway by ID
  private findGatewayById(gatewayId?: string): PaywallGateway | null {
    if (!gatewayId) return null;
    
    const gateways = this.getGateways();
    return gateways.find(g => g.id === gatewayId) || null;
  }


  /**
   * Initialize EmailAuthController if email authentication is enabled
   */
  private initializeEmailAuth() {
    console.log('[PaywallController] initializeEmailAuth called');
    console.log('[PaywallController] email auth config:', this.config?.emailAuth);
    console.log('[PaywallController] config enabled:', this.config?.enabled);
    
    // If paywall is disabled entirely, clean up everything
    if (!this.config?.enabled) {
      console.log('[PaywallController] Paywall completely disabled, cleaning up email auth');
      if (this.emailAuth) {
        this.emailAuth.destroy();
        this.emailAuth = null;
      }
      return;
    }
    
    // If email auth specifically is disabled, clean up only email auth
    if (!this.config?.emailAuth?.enabled) {
      console.log('[PaywallController] Email auth disabled, cleaning up existing instance');
      if (this.emailAuth) {
        this.emailAuth.destroy();
        this.emailAuth = null;
      }
      return;
    }

    console.log('[PaywallController] Email auth enabled, checking for existing instance:', !!this.emailAuth);
    if (!this.emailAuth) {
      console.log('[PaywallController] Creating new EmailAuthController');
      const emailAuthOptions: EmailAuthControllerOptions = {
        getOverlayContainer: this.opts.getOverlayContainer,
        onAuthSuccess: (userId: string, sessionToken: string, accessData?: any) => {
          this.authenticatedUserId = userId;
          this.sessionToken = sessionToken;
          
          // Update config with authenticated userId
          if (this.config) {
            this.config.userId = userId;
          }
          
          // Close auth modal
          this.emailAuth?.closeAuthModal();
          
          // Handle access logic based on server response
          // Handle access logic based on server response
          if (accessData) {
            // Support both camelCase (from EmailAuthController) and snake_case (legacy)
            const access_granted = accessData.accessGranted ?? accessData.access_granted ?? false;
            const requires_payment = accessData.requiresPayment ?? accessData.requires_payment ?? false;
            const free_duration = accessData.freeDuration ?? accessData.free_duration ?? 0;
            const price = accessData.price ?? null;
            
            // Update price from server response if provided
            if (price && this.config) {
              this.config.pricing = {
                ...this.config.pricing,
                amount: parseFloat(price.toString().replace(/[^\d.]/g, ''))
              };
            }

            console.log('[PaywallController] Auth response:', { access_granted, requires_payment, free_duration });
            
            if (access_granted) {
              // Full access - play immediately
              console.log('[PaywallController] Access granted, cleaning up overlays and playing video');
              
              // Use more aggressive cleanup to ensure all overlays are removed
              this.destroyOverlays();
              
              // Small delay to ensure DOM cleanup is complete before resuming
              setTimeout(() => {
                // Pass access granted status to WebPlayer via onResume callback
                if (this.opts.onResume) {
                  this.opts.onResume({ accessGranted: true, paymentSuccessful: true });
                }
              }, 50);
            }
            else if (!access_granted && requires_payment) {
              if (free_duration > 0) {
                // Start free preview, show paywall after duration
                console.log(`[PaywallController] Starting ${free_duration}s preview`);
                this.opts.onResume();
                
                // Let preview play, WebPlayer will handle showing paywall
                // after free_duration via onFreePreviewEnded event
              } else {
                // No preview available - show paywall immediately
                console.log('[PaywallController] No preview available, showing paywall');
                setTimeout(() => {
                  this.openPaymentOverlay();
                }, 100);
              }
            } 
            else {
              // Default behavior - resume playback
              console.log('[PaywallController] Default behavior, resuming playback');
              this.opts.onResume();
            }
          } else {
            // Backward compatibility - use configured free duration
            console.log('[PaywallController] No access data, resuming with default preview');
            this.opts.onResume();
          }
        },
        onAuthCancel: () => {
          // User cancelled authentication, close everything
          this.emailAuth?.closeAuthModal();
          this.opts.onShow?.(); // Let parent know modal was shown (for cleanup)
        },
        onShow: this.opts.onShow,
        onClose: this.opts.onClose,
      };
      
      this.emailAuth = new EmailAuthController(this.config, emailAuthOptions);
      console.log('[PaywallController] EmailAuthController created successfully');
    }
  }

  /**
   * Open payment overlay directly (bypassing auth check)
   */
  private openPaymentOverlay() {
    console.log('[PaywallController] Opening payment overlay');
    const root = this.ensureOverlay();
    if (!root) {
      console.error('[PaywallController] Failed to create overlay');
      return;
    }

    try {
      root.style.display = 'flex';
      root.classList.add('active');
      
      // Force reflow then fade in with animation
      void root.offsetWidth;
      root.style.opacity = '1';
      
      // Also animate the modal inside
      const modal = root.querySelector('.uvf-paywall-modal') as HTMLElement;
      if (modal) {
        modal.style.transform = 'translateY(0)';
        modal.style.opacity = '1';
      }
      
      this.opts.onShow?.();
      console.log('[PaywallController] Payment overlay shown');
    } catch (err) {
      console.error('[PaywallController] Error showing overlay:', err);
    }
  }

  /**
   * Check if user is authenticated (for external use)
   */
  isAuthenticated(): boolean {
    if (!this.config?.emailAuth?.enabled) return true;
    return this.emailAuth?.isAuthenticated() || false;
  }

  /**
   * Get authenticated user ID (for external use)
   */
  getAuthenticatedUserId(): string | null {
    if (!this.config?.emailAuth?.enabled) return this.config?.userId || null;
    return this.emailAuth?.getAuthenticatedUserId() || this.config?.userId || null;
  }

  /**
   * Logout user (for external use)
   */
  async logout(): Promise<void> {
    if (this.emailAuth) {
      await this.emailAuth.logout();
    }
    this.authenticatedUserId = null;
    this.sessionToken = null;
  }

  /**
   * Add a custom payment gateway dynamically
   */
  addGateway(gateway: PaywallGateway) {
    if (!this.config) {
      console.warn('[PaywallController] Cannot add gateway: config is null');
      return;
    }
    
    if (!this.config.gateways) {
      this.config.gateways = [];
    }
    
    // Remove existing gateway with same ID
    this.config.gateways = this.config.gateways.filter((g: any) => {
      const id = typeof g === 'string' ? g : g.id;
      return id !== gateway.id;
    });
    
    // Add new gateway
    this.config.gateways.push(gateway);
    
    console.log(`[PaywallController] Added gateway: ${gateway.id}`);
  }
  
  /**
   * Remove a payment gateway by ID
   */
  removeGateway(gatewayId: string) {
    if (!this.config?.gateways) return;
    
    this.config.gateways = this.config.gateways.filter((g: any) => {
      const id = typeof g === 'string' ? g : g.id;
      return id !== gatewayId;
    });
    
    console.log(`[PaywallController] Removed gateway: ${gatewayId}`);
  }
  
  /**
   * Get all configured gateways (for external use)
   */
  getConfiguredGateways(): PaywallGateway[] {
    return this.getGateways();
  }

  /**
   * Cleanup on destroy
   */
  destroy() {
    if (this.emailAuth) {
      this.emailAuth.destroy();
      this.emailAuth = null;
    }
    
    if (this.overlayEl && this.overlayEl.parentElement) {
      this.overlayEl.parentElement.removeChild(this.overlayEl);
    }
    this.overlayEl = null;
    
    // Close any open popup
    try {
      if (this.popup && !this.popup.closed) {
        this.popup.close();
      }
    } catch (_) {}
    this.popup = null;
    
    // Clean up gateway tracking
    this.currentGateway = null;
    
    try {
      window.removeEventListener('message', this.onMessage, false);
    } catch (_) {}
  }
}
