import { test, expect, Page } from '@playwright/test';

/**
 * Stripe Connect Onboarding E2E Tests
 *
 * Tests the complete Stripe Connect onboarding flow including:
 * - Payment settings page display
 * - Starting embedded onboarding
 * - Completing Stripe test account setup
 * - Status refresh after onboarding
 * - Active account display
 *
 * Note: These tests interact with Stripe's test mode sandbox.
 * Test credentials use Stripe's test data (000000000 for EIN, etc.)
 */

// Helper to login as business owner
async function loginAsBusinessOwner(page: Page, subdomain: string = 'acme') {
  await page.goto(`http://${subdomain}.lvh.me:5173`);
  await page.waitForLoadState('networkidle');

  // Check if login is needed
  const loginHeading = page.getByRole('heading', { name: /sign in/i });
  if (await loginHeading.isVisible({ timeout: 3000 }).catch(() => false)) {
    await page.getByPlaceholder(/username/i).fill(`${subdomain}_owner`);
    await page.getByPlaceholder(/password/i).fill('testpass123');
    await page.getByRole('button', { name: /sign in/i }).click();
    await page.waitForLoadState('networkidle');
  }
}

// Helper to navigate to payments settings
async function navigateToPayments(page: Page) {
  // Look for payments/billing link in sidebar or navigation
  const paymentsLink = page.getByRole('link', { name: /payments|billing|plan/i });
  if (await paymentsLink.isVisible({ timeout: 3000 }).catch(() => false)) {
    await paymentsLink.click();
    await page.waitForLoadState('networkidle');
  } else {
    // Try direct navigation
    await page.goto(`http://acme.lvh.me:5173/payments`);
    await page.waitForLoadState('networkidle');
  }
}

test.describe('Stripe Connect Onboarding Flow', () => {
  test.describe.configure({ mode: 'serial' });

  test.beforeEach(async ({ page }) => {
    // Clear storage before each test
    await page.context().clearCookies();
    await page.evaluate(() => {
      localStorage.clear();
      sessionStorage.clear();
    });
  });

  test('should display payment settings page for business owner', async ({ page }) => {
    await loginAsBusinessOwner(page);
    await navigateToPayments(page);

    // Should show the Plan & Billing heading
    await expect(page.getByRole('heading', { name: /plan.*billing/i })).toBeVisible();

    // Should show payment configuration section
    const paymentSection = page.getByText(/payment.*config|stripe.*connect|set up payments/i);
    await expect(paymentSection.first()).toBeVisible();
  });

  test('should show Connect setup for paid tier business', async ({ page }) => {
    await loginAsBusinessOwner(page);
    await navigateToPayments(page);

    // For paid tier, should show Stripe Connect setup option
    // Look for setup button or connected status
    const setupButton = page.getByRole('button', { name: /start payment setup|connect.*stripe|set up/i });
    const connectedStatus = page.getByText(/stripe connected|payments.*enabled/i);

    const hasSetupButton = await setupButton.isVisible({ timeout: 5000 }).catch(() => false);
    const hasConnectedStatus = await connectedStatus.isVisible({ timeout: 5000 }).catch(() => false);

    // Should show either setup option or connected status
    expect(hasSetupButton || hasConnectedStatus).toBeTruthy();
  });

  test('should initialize embedded onboarding when clicking setup', async ({ page }) => {
    await loginAsBusinessOwner(page);
    await navigateToPayments(page);

    // Find and click setup button
    const setupButton = page.getByRole('button', { name: /start payment setup/i });

    if (await setupButton.isVisible({ timeout: 5000 }).catch(() => false)) {
      await setupButton.click();

      // Should show loading state
      const loadingIndicator = page.getByText(/initializing|loading/i);
      await expect(loadingIndicator).toBeVisible({ timeout: 10000 });

      // Wait for Stripe component to load (may take time)
      // The Stripe iframe should appear
      await page.waitForTimeout(5000); // Allow time for Stripe to load

      // Look for Stripe onboarding content or container
      const stripeFrame = page.frameLocator('iframe[name*="stripe"]').first();
      const onboardingContainer = page.getByText(/complete.*account.*setup|fill out.*information/i);

      const hasStripeFrame = await stripeFrame.locator('body').isVisible({ timeout: 10000 }).catch(() => false);
      const hasOnboardingText = await onboardingContainer.isVisible({ timeout: 5000 }).catch(() => false);

      expect(hasStripeFrame || hasOnboardingText).toBeTruthy();
    }
  });

  test('should display account details when Connect is already active', async ({ page }) => {
    await loginAsBusinessOwner(page);
    await navigateToPayments(page);

    // If account is already connected, should show status details
    const connectedBadge = page.getByText(/stripe connected/i);

    if (await connectedBadge.isVisible({ timeout: 5000 }).catch(() => false)) {
      // Should show account type
      await expect(page.getByText(/standard connect|express connect|custom connect/i)).toBeVisible();

      // Should show charges enabled status
      await expect(page.getByText(/charges.*enabled|enabled/i).first()).toBeVisible();

      // Should show payouts status
      await expect(page.getByText(/payouts/i)).toBeVisible();
    }
  });

  test('should handle onboarding errors gracefully', async ({ page }) => {
    await loginAsBusinessOwner(page);
    await navigateToPayments(page);

    // Mock a failed API response
    await page.route('**/api/payments/connect/account-session/**', (route) => {
      route.fulfill({
        status: 500,
        body: JSON.stringify({ error: 'Failed to create session' }),
      });
    });

    const setupButton = page.getByRole('button', { name: /start payment setup/i });
    if (await setupButton.isVisible({ timeout: 5000 }).catch(() => false)) {
      await setupButton.click();

      // Should show error state
      await expect(page.getByText(/failed|error|setup failed/i)).toBeVisible({ timeout: 10000 });

      // Should show try again button
      await expect(page.getByRole('button', { name: /try again/i })).toBeVisible();
    }
  });
});

test.describe('Stripe Connect Onboarding - Full Flow', () => {
  // This test walks through the complete Stripe test account setup
  // Uses Stripe's test mode data

  test('should complete full onboarding with test data', async ({ page }) => {
    test.setTimeout(120000); // Allow 2 minutes for full Stripe flow

    await loginAsBusinessOwner(page);
    await navigateToPayments(page);

    const setupButton = page.getByRole('button', { name: /start payment setup/i });

    if (!await setupButton.isVisible({ timeout: 5000 }).catch(() => false)) {
      // Already set up, skip this test
      console.log('Connect already configured, skipping full flow test');
      return;
    }

    await setupButton.click();

    // Wait for Stripe embedded component to load
    await page.waitForTimeout(5000);

    // Look for Stripe iframe
    const stripeFrames = page.frames().filter(f => f.url().includes('stripe'));

    if (stripeFrames.length > 0) {
      const stripeFrame = stripeFrames[0];

      // Fill in test business information
      // Note: Stripe's embedded forms vary, these are common fields

      // Try to find and fill phone number
      const phoneInput = stripeFrame.locator('input[name*="phone"], input[placeholder*="phone"]');
      if (await phoneInput.isVisible({ timeout: 3000 }).catch(() => false)) {
        await phoneInput.fill('5555555555');
      }

      // Try to find and fill business details
      const einInput = stripeFrame.locator('input[name*="tax_id"], input[placeholder*="EIN"]');
      if (await einInput.isVisible({ timeout: 3000 }).catch(() => false)) {
        await einInput.fill('000000000'); // Stripe test EIN
      }

      // Fill address if visible
      const addressInput = stripeFrame.locator('input[name*="address"], input[placeholder*="address"]');
      if (await addressInput.isVisible({ timeout: 3000 }).catch(() => false)) {
        await addressInput.fill('123 Test Street');
      }

      // Look for continue/submit button
      const continueBtn = stripeFrame.locator('button:has-text("Continue"), button:has-text("Submit")');
      if (await continueBtn.isVisible({ timeout: 3000 }).catch(() => false)) {
        await continueBtn.click();
      }

      // Wait and check for completion
      await page.waitForTimeout(5000);
    }

    // After onboarding, check if status updated
    const completionMessage = page.getByText(/onboarding complete|stripe connected|set up/i);
    const isComplete = await completionMessage.isVisible({ timeout: 10000 }).catch(() => false);

    // Log result for debugging
    console.log('Onboarding completion visible:', isComplete);
  });

  test('should refresh status after onboarding exit', async ({ page }) => {
    await loginAsBusinessOwner(page);
    await navigateToPayments(page);

    // Mock successful refresh response
    await page.route('**/api/payments/connect/refresh-status/**', (route) => {
      route.fulfill({
        status: 200,
        body: JSON.stringify({
          id: 1,
          business: 1,
          stripe_account_id: 'acct_test123',
          account_type: 'custom',
          status: 'active',
          charges_enabled: true,
          payouts_enabled: true,
          details_submitted: true,
          onboarding_complete: true,
        }),
      });
    });

    // Trigger a status refresh
    const refreshButton = page.getByRole('button', { name: /refresh|check status/i });
    if (await refreshButton.isVisible({ timeout: 5000 }).catch(() => false)) {
      await refreshButton.click();

      // Should show updated status
      await expect(page.getByText(/active|connected/i)).toBeVisible({ timeout: 5000 });
    }
  });
});

test.describe('Payment Configuration Status', () => {
  test('should show correct status for unconfigured business', async ({ page }) => {
    // Mock unconfigured payment status
    await page.route('**/api/payments/config/status/**', (route) => {
      route.fulfill({
        status: 200,
        body: JSON.stringify({
          payment_mode: 'none',
          tier: 'Professional',
          can_accept_payments: false,
          api_keys: null,
          connect_account: null,
        }),
      });
    });

    await loginAsBusinessOwner(page);
    await navigateToPayments(page);

    // Should show setup required message
    await expect(page.getByText(/set up payments|not configured/i)).toBeVisible();
  });

  test('should show correct status for configured Connect account', async ({ page }) => {
    // Mock configured payment status
    await page.route('**/api/payments/config/status/**', (route) => {
      route.fulfill({
        status: 200,
        body: JSON.stringify({
          payment_mode: 'connect',
          tier: 'Business',
          can_accept_payments: true,
          api_keys: null,
          connect_account: {
            id: 1,
            stripe_account_id: 'acct_test123',
            account_type: 'custom',
            status: 'active',
            charges_enabled: true,
            payouts_enabled: true,
            details_submitted: true,
            onboarding_complete: true,
          },
        }),
      });
    });

    await loginAsBusinessOwner(page);
    await navigateToPayments(page);

    // Should show connected status
    await expect(page.getByText(/stripe connected|connected/i)).toBeVisible();
    await expect(page.getByText(/charges.*enabled|enabled/i).first()).toBeVisible();
  });

  test('should show API keys option for free tier', async ({ page }) => {
    // Mock free tier status
    await page.route('**/api/payments/config/status/**', (route) => {
      route.fulfill({
        status: 200,
        body: JSON.stringify({
          payment_mode: 'none',
          tier: 'Free',
          can_accept_payments: false,
          api_keys: null,
          connect_account: null,
        }),
      });
    });

    await loginAsBusinessOwner(page);
    await navigateToPayments(page);

    // For free tier, should show API keys configuration option
    const apiKeysSection = page.getByText(/api keys|stripe keys/i);
    const hasApiKeysOption = await apiKeysSection.isVisible({ timeout: 5000 }).catch(() => false);

    // Free tier uses direct API keys instead of Connect
    expect(hasApiKeysOption).toBeTruthy();
  });
});

test.describe('Onboarding Wizard Integration', () => {
  test('should show onboarding wizard for new paid tier business', async ({ page }) => {
    await loginAsBusinessOwner(page);

    // Check if onboarding wizard appears
    const welcomeHeading = page.getByRole('heading', { name: /welcome/i });
    const isWizardVisible = await welcomeHeading.isVisible({ timeout: 5000 }).catch(() => false);

    if (isWizardVisible) {
      // Navigate through wizard to Stripe step
      await page.getByRole('button', { name: /get started/i }).click();

      // Should show Stripe Connect step
      await expect(page.getByRole('heading', { name: /connect stripe|payment/i })).toBeVisible();

      // Should have option to start Connect onboarding
      const connectButton = page.getByRole('button', { name: /connect|set up|start/i });
      await expect(connectButton.first()).toBeVisible();
    }
  });

  test('should handle URL parameters for Stripe return', async ({ page }) => {
    // Test handling of connect=complete parameter
    await page.goto('http://acme.lvh.me:5173/?connect=complete');
    await page.waitForLoadState('networkidle');

    // Login if needed
    const loginHeading = page.getByRole('heading', { name: /sign in/i });
    if (await loginHeading.isVisible({ timeout: 3000 }).catch(() => false)) {
      await page.getByPlaceholder(/username/i).fill('acme_owner');
      await page.getByPlaceholder(/password/i).fill('testpass123');
      await page.getByRole('button', { name: /sign in/i }).click();
      await page.waitForLoadState('networkidle');
    }

    // Page should handle the connect=complete parameter
    // and potentially show success message or refresh status
    console.log('Connect complete parameter handled');
  });
});
