import { test, expect } from '../../fixtures/test-base';
import { siteConfig } from '../../config/siteConfig';
import { loginViaUI } from '../../support/auth-helpers';
import {
    selectDeliveryFulfillment,
    fillShippingAddress,
    acceptTermsAndPlaceOrder,
    verifyOrderConfirmation,
    TEST_SHIPPING_ADDRESS,
} from '../../support/checkout-helpers';
import { fillStripeCard, STRIPE_CARDS } from '../../support/payment-helpers';

test.describe('Logged-In Checkout', () => {
    test.setTimeout(120_000);

    const email = siteConfig.auth.testEmail;
    const password = siteConfig.auth.testPassword;

    test.beforeEach(async ({ page }) => {
        test.skip(
            !email || !password,
            'E2E_TEST_EMAIL and E2E_TEST_PASSWORD are required for logged-in checkout tests'
        );

        const loggedIn = await loginViaUI(page, email!, password!);
        expect(loggedIn, 'Should be logged in before checkout').toBeTruthy();
    });

    test('CHK-003 @checkout: Logged-in checkout full flow', async ({ page, addToCartAndCheckout }) => {
        // Step 1: Add product #1 (Cotton Knit Cardigan) and go to checkout
        await addToCartAndCheckout('cotton_knit_cardigan_swing');

        // Step 2: Select delivery fulfillment
        await selectDeliveryFulfillment(page);

        // Step 3: Handle shipping address (use saved or fill new)
        const savedAddressSelectors = [
            '[class*="saved-address" i]',
            '[class*="address-card" i]',
            '[class*="address-list" i]',
            '[data-testid*="saved-address"]',
            'input[type="radio"][name*="address" i]',
        ];

        let hasSavedAddress = false;
        for (const selector of savedAddressSelectors) {
            const el = page.locator(selector).first();
            const visible = await el.isVisible().catch(() => false);
            if (visible) {
                hasSavedAddress = true;
                const radio = page.locator('input[type="radio"][name*="address" i]').first();
                if (await radio.isVisible().catch(() => false)) {
                    await radio.click();
                }
                break;
            }
        }

        if (!hasSavedAddress) {
            await fillShippingAddress(page, { ...TEST_SHIPPING_ADDRESS, email: '' });
        }

        await page.waitForTimeout(2000);

        // Step 4: Fill Stripe payment or use saved card
        const cardFilled = await fillStripeCard(page, STRIPE_CARDS.standard);
        if (!cardFilled) {
            // Try saved card
            const savedCardSelectors = [
                '[class*="saved-card" i]',
                '[class*="saved-payment" i]',
                'input[type="radio"][name*="card" i]',
                'input[type="radio"][name*="payment" i]',
            ];
            for (const selector of savedCardSelectors) {
                const el = page.locator(selector).first();
                if (await el.isVisible().catch(() => false)) {
                    await el.click();
                    await page.waitForTimeout(500);
                    break;
                }
            }
        }

        await page.waitForTimeout(1000);

        // Step 5: Accept terms and place order
        const orderPlaced = await acceptTermsAndPlaceOrder(page);
        test.skip(!orderPlaced, 'Place order button not found or disabled');

        // Step 6: Verify order confirmation — order linked to account
        const confirmed = await verifyOrderConfirmation(page);
        expect(confirmed, 'Order confirmation page should be displayed for logged-in user').toBeTruthy();

        // Verify order is linked to account (no guest email prompt, account indicator present)
        const accountIndicators = [
            ':text("My Account")',
            ':text("マイアカウント")',
            'a[href*="/account"]',
            '[data-testid*="account"]',
        ];

        let accountLinked = false;
        for (const selector of accountIndicators) {
            const el = page.locator(selector).first();
            if (await el.isVisible().catch(() => false)) {
                accountLinked = true;
                break;
            }
        }

        // Account link should be present on confirmation (logged-in user)
        // Not a hard failure if not visible, as different sites show this differently
        if (accountLinked) {
            console.log('Order confirmed and linked to logged-in account');
        }

        await page.screenshot({
            path: `test-results/chk-003-logged-in-checkout-${Date.now()}.png`,
        });
    });

    test('CHK-004 @checkout: Saved info pre-filled', async ({ page, addToCartAndCheckout }) => {
        // Add product and go to checkout
        await addToCartAndCheckout('cotton_knit_cardigan_swing');

        // Check for pre-filled / pre-selected saved address
        await page.waitForTimeout(2000);

        const savedAddressIndicators = [
            '[class*="saved-address" i]',
            '[class*="address-card" i]',
            '[class*="default-address" i]',
            '[data-testid*="saved-address"]',
            'input[type="radio"][name*="address" i]:checked',
            '[class*="selected" i][class*="address" i]',
        ];

        let addressPreFilled = false;
        for (const selector of savedAddressIndicators) {
            const el = page.locator(selector).first();
            if (await el.isVisible().catch(() => false)) {
                addressPreFilled = true;
                break;
            }
        }

        // Check for pre-selected payment method
        const savedPaymentIndicators = [
            '[class*="saved-card" i]',
            '[class*="saved-payment" i]',
            '[class*="default-payment" i]',
            'input[type="radio"][name*="payment" i]:checked',
            'input[type="radio"][name*="card" i]:checked',
            '[data-testid*="saved-payment"]',
        ];

        let paymentPreSelected = false;
        for (const selector of savedPaymentIndicators) {
            const el = page.locator(selector).first();
            if (await el.isVisible().catch(() => false)) {
                paymentPreSelected = true;
                break;
            }
        }

        expect(
            addressPreFilled || paymentPreSelected,
            'Saved address and/or payment should be pre-filled for logged-in user with saved info'
        ).toBeTruthy();

        await page.screenshot({
            path: `test-results/chk-004-saved-info-prefilled-${Date.now()}.png`,
        });
    });

    test('CHK-005 @checkout: Add new address with "Use as billing"', async ({ page, addToCartAndCheckout }) => {
        // Add product and go to checkout
        await addToCartAndCheckout('cotton_knit_cardigan_swing');

        await selectDeliveryFulfillment(page);
        await page.waitForTimeout(1500);

        // Click "Add new address" button
        const addNewAddressSelectors = [
            'button:has-text("Add new address")',
            'button:has-text("新しい住所を追加")',
            'button:has-text("Add address")',
            'a:has-text("Add new address")',
            '[data-testid*="add-address"]',
            '[data-testid*="new-address"]',
        ];

        let newAddressClicked = false;
        for (const selector of addNewAddressSelectors) {
            const btn = page.locator(selector).first();
            if (await btn.isVisible().catch(() => false)) {
                await btn.click();
                newAddressClicked = true;
                await page.waitForTimeout(1500);
                break;
            }
        }

        test.skip(!newAddressClicked, 'Add new address button not found');

        // Fill new address form
        await fillShippingAddress(page, {
            ...TEST_SHIPPING_ADDRESS,
            street: '銀座4-1-1',
            building: 'テストビル2F',
            email: '',
        });

        // Check "Use as billing" / "Same as shipping" checkbox
        const useAsBillingSelectors = [
            'input[name*="use_as_billing" i]',
            'input[name*="billing_same" i]',
            'input[name*="sameAsShipping" i]',
            'label:has-text("Use as billing") input[type="checkbox"]',
            'label:has-text("Same as shipping") input[type="checkbox"]',
            'label:has-text("請求先住所も同じ") input[type="checkbox"]',
            '[data-testid*="same-as-shipping"] input[type="checkbox"]',
            '[data-testid*="use-as-billing"] input[type="checkbox"]',
        ];

        for (const selector of useAsBillingSelectors) {
            const checkbox = page.locator(selector).first();
            if (await checkbox.isVisible().catch(() => false)) {
                const checked = await checkbox.isChecked().catch(() => false);
                if (!checked) await checkbox.check();
                break;
            }
        }

        await page.waitForTimeout(1000);

        // Verify billing shows "Same as shipping" or billing section is collapsed/hidden
        const billingIndicators = [
            ':text("Same as shipping")',
            ':text("配送先住所と同じ")',
            '[class*="billing" i]:has-text("Same")',
            '[data-testid*="billing-same"]',
        ];

        let billingSameShown = false;
        for (const selector of billingIndicators) {
            const el = page.locator(selector).first();
            if (await el.isVisible().catch(() => false)) {
                billingSameShown = true;
                break;
            }
        }

        // Billing section might just be hidden/collapsed when same as shipping
        const billingFormHidden = !(await page
            .locator('[class*="billing-address-form" i], [data-testid*="billing-form"]')
            .first()
            .isVisible()
            .catch(() => false));

        expect(
            billingSameShown || billingFormHidden,
            'Billing should show "Same as shipping" or billing form should be hidden'
        ).toBeTruthy();

        await page.screenshot({
            path: `test-results/chk-005-new-address-use-as-billing-${Date.now()}.png`,
        });
    });

    test('CHK-006 @checkout: Billing starts collapsed for user with saved billing', async ({ page, addToCartAndCheckout }) => {
        // Add product and go to checkout
        await addToCartAndCheckout('cotton_knit_cardigan_swing');

        await page.waitForTimeout(2000);

        // Look for billing accordion / section that should be collapsed
        const billingAccordionSelectors = [
            '[class*="billing" i][class*="accordion" i]',
            '[class*="billing" i][class*="collapsed" i]',
            '[data-testid*="billing-accordion"]',
            'button:has-text("Billing"):not([aria-expanded="true"])',
            'button:has-text("請求先"):not([aria-expanded="true"])',
            '[aria-label*="billing" i]:not([aria-expanded="true"])',
        ];

        let billingCollapsed = false;
        for (const selector of billingAccordionSelectors) {
            const el = page.locator(selector).first();
            if (await el.isVisible().catch(() => false)) {
                billingCollapsed = true;
                break;
            }
        }

        // Alternative: billing section not expanded (form fields hidden)
        const billingFormVisible = await page
            .locator(
                '[class*="billing-form" i] input:visible, ' +
                '[data-testid*="billing-address"] input:visible'
            )
            .first()
            .isVisible()
            .catch(() => false);

        expect(
            billingCollapsed || !billingFormVisible,
            'Billing section should start collapsed when user has saved billing address'
        ).toBeTruthy();

        await page.screenshot({
            path: `test-results/chk-006-billing-collapsed-${Date.now()}.png`,
        });
    });

    test('CHK-007 @checkout: New address becomes default on next checkout', async ({ page, addToCartAndCheckout }) => {
        // Step 1: First checkout — add new address
        await addToCartAndCheckout('cotton_knit_cardigan_swing');
        await selectDeliveryFulfillment(page);
        await page.waitForTimeout(1500);

        // Click "Add new address"
        const addNewSelectors = [
            'button:has-text("Add new address")',
            'button:has-text("新しい住所を追加")',
            'button:has-text("Add address")',
            '[data-testid*="add-address"]',
        ];

        let clicked = false;
        for (const selector of addNewSelectors) {
            const btn = page.locator(selector).first();
            if (await btn.isVisible().catch(() => false)) {
                await btn.click();
                clicked = true;
                await page.waitForTimeout(1500);
                break;
            }
        }

        test.skip(!clicked, 'Add new address button not found');

        const newAddress = {
            ...TEST_SHIPPING_ADDRESS,
            street: '銀座7-7-7',
            building: '新テストビル',
            email: '',
        };

        await fillShippingAddress(page, newAddress);
        await page.waitForTimeout(2000);

        // Fill payment and place order
        await fillStripeCard(page, STRIPE_CARDS.standard);
        await page.waitForTimeout(1000);

        const orderPlaced = await acceptTermsAndPlaceOrder(page);
        test.skip(!orderPlaced, 'Could not place first order to set new default address');

        await verifyOrderConfirmation(page);

        // Step 2: Start new checkout — verify new address is default
        await addToCartAndCheckout('cotton_knit_cardigan_swing');
        await page.waitForTimeout(3000);

        // Check if the new address is now shown as default/selected
        const addressText = await page.locator('body').textContent().catch(() => '');
        const newAddressIsDefault =
            addressText?.includes(newAddress.street) || addressText?.includes(newAddress.building);

        // Also check for selected radio or highlighted address card
        const selectedAddressSelectors = [
            'input[type="radio"][name*="address" i]:checked',
            '[class*="selected" i][class*="address" i]',
            '[class*="address" i][class*="active" i]',
            '[data-testid*="default-address"]',
        ];

        let defaultAddressFound = false;
        for (const selector of selectedAddressSelectors) {
            const el = page.locator(selector).first();
            if (await el.isVisible().catch(() => false)) {
                defaultAddressFound = true;
                break;
            }
        }

        expect(
            newAddressIsDefault || defaultAddressFound,
            'New address from previous order should be the default on next checkout'
        ).toBeTruthy();

        await page.screenshot({
            path: `test-results/chk-007-new-address-default-${Date.now()}.png`,
        });
    });
});
