import { test, expect } from './fixtures';
import { randomUUID } from 'crypto';

test.describe('II. Workout Management', () => {

    test('2.1 A. Workout Plans - Create New Plan', async ({ page, createUniqueUser, request }) => {
        const user = await loginAndSetup(page, createUniqueUser);

        // Seed exercise
        const seedResp = await request.post('/api/exercises', {
            data: { name: 'Test Sq', type: 'STRENGTH' },
            headers: { 'Authorization': `Bearer ${user.token}` }
        });
        expect(seedResp.ok()).toBeTruthy();

        await page.reload();

        await page.getByRole('button', { name: 'Plans' }).first().click();

        await page.getByRole('button', { name: 'Create Plan' }).click();

        // Wait for potential animation/loading
        await expect(page.getByText('Plan Editor')).toBeVisible({ timeout: 10000 });

        await page.getByLabel(/Name/i).fill('My New Strength Plan');
        await page.getByPlaceholder(/Describe preparation/i).fill('Focus on compound lifts');

        await page.getByRole('button', { name: 'Add Exercise' }).click();

        await expect(page.getByText('Select Exercise')).toBeVisible();
        await page.getByText('Test Sq').click();

        await page.getByRole('button', { name: 'Save' }).click();

        await expect(page.getByText('My New Strength Plan')).toBeVisible();
        await expect(page.getByText('Focus on compound lifts')).toBeVisible();
    });

    test('2.2 A. Workout Plans - Edit Existing Plan', async ({ page, createUniqueUser, request }) => {
        const user = await loginAndSetup(page, createUniqueUser);

        const seedResp = await request.post('/api/plans', {
            data: {
                id: randomUUID(),
                name: 'Original Plan',
                description: 'Original Description',
                steps: []
            },
            headers: { 'Authorization': `Bearer ${user.token}` }
        });
        expect(seedResp.ok()).toBeTruthy();

        await page.reload();

        await page.getByRole('button', { name: 'Plans' }).first().click();
        await expect(page.getByText('Original Plan')).toBeVisible();

        const card = page.locator('div')
            .filter({ hasText: 'Original Plan' })
            .filter({ has: page.getByRole('button', { name: 'Edit Plan' }) })
            .last();
        await card.getByRole('button', { name: 'Edit Plan' }).click();

        await page.getByLabel(/Name/i).fill('Updated Plan Name');
        await page.getByRole('button', { name: 'Save' }).click();

        await expect(page.getByText('Updated Plan Name')).toBeVisible();
        await expect(page.getByText('Original Plan')).not.toBeVisible();
    });

    test('2.3 A. Workout Plans - Delete Plan', async ({ page, createUniqueUser, request }) => {
        const user = await loginAndSetup(page, createUniqueUser);
        const resp = await request.post('/api/plans', {
            data: {
                id: randomUUID(),
                name: 'Plan To Delete',
                description: 'Delete me',
                steps: []
            },
            headers: { 'Authorization': `Bearer ${user.token}` }
        });
        expect(resp.ok()).toBeTruthy();
        await page.reload();

        await page.getByRole('button', { name: 'Plans' }).first().click();
        page.on('dialog', dialog => dialog.accept());

        const card = page.locator('div')
            .filter({ hasText: 'Plan To Delete' })
            .filter({ has: page.getByRole('button', { name: 'Delete Plan' }) })
            .last();
        await card.getByRole('button', { name: 'Delete Plan' }).click();

        await expect(page.getByText('Plan To Delete')).not.toBeVisible();
    });

    test('2.4 A. Workout Plans - Reorder Exercises', async ({ page, createUniqueUser, request }) => {
        page.on('console', msg => console.log('PAGE LOG:', msg.text()));
        const user = await loginAndSetup(page, createUniqueUser);
        // Need exercises
        const ex1Id = randomUUID();
        const ex2Id = randomUUID();
        await request.post('/api/exercises', {
            data: { id: ex1Id, name: 'Ex One', type: 'STRENGTH' },
            headers: { 'Authorization': `Bearer ${user.token}` }
        });
        await request.post('/api/exercises', {
            data: { id: ex2Id, name: 'Ex Two', type: 'STRENGTH' },
            headers: { 'Authorization': `Bearer ${user.token}` }
        });

        const planId = randomUUID();
        await request.post('/api/plans', {
            data: {
                id: planId,
                name: 'Reorder Plan',
                description: 'Testing reorder',
                steps: [
                    { exerciseId: ex1Id, isWeighted: false },
                    { exerciseId: ex2Id, isWeighted: false }
                ]
            },
            headers: { 'Authorization': `Bearer ${user.token}` }
        });
        await page.reload();

        await page.getByRole('button', { name: 'Plans' }).first().click();

        // Use the new aria-label selector
        const card = page.locator('div')
            .filter({ hasText: 'Reorder Plan' })
            .filter({ has: page.getByRole('button', { name: 'Edit Plan' }) })
            .last();
        await card.getByRole('button', { name: 'Edit Plan' }).click();

        const card1 = page.locator('[draggable="true"]').filter({ hasText: 'Ex One' });
        const card2 = page.locator('[draggable="true"]').filter({ hasText: 'Ex Two' });

        // Initial state check
        await expect(page.locator('[draggable="true"]').first()).toContainText('Ex One');

        // Drag using handles with explicit wait
        const sourceHandle = card1.locator('.lucide-grip-vertical');
        const targetHandle = card2.locator('.lucide-grip-vertical');

        await expect(sourceHandle).toBeVisible();
        await expect(targetHandle).toBeVisible();

        console.log('Starting Drag...');
        await sourceHandle.dragTo(targetHandle);
        console.log('Drag complete');

        // Wait for reorder to settle
        await page.waitForTimeout(1000);

        // Verify Swap immediately
        await expect(page.locator('[draggable="true"]').first()).toContainText('Ex Two');

        await page.getByRole('button', { name: 'Save' }).click();

        // Reload and verify persistence
        await page.reload();
        await page.getByRole('button', { name: 'Plans' }).first().click();

        const cardRevisit = page.locator('div')
            .filter({ hasText: 'Reorder Plan' })
            .filter({ has: page.getByRole('button', { name: 'Edit Plan' }) })
            .last();
        await cardRevisit.getByRole('button', { name: 'Edit Plan' }).click();

        await expect(page.locator('[draggable="true"]').first()).toContainText('Ex Two');
        await expect(page.locator('[draggable="true"]').last()).toContainText('Ex One');
    });

    test('2.5 A. Workout Plans - Start Session from Plan', async ({ page, createUniqueUser, request }) => {
        const user = await loginAndSetup(page, createUniqueUser);
        const resp = await request.post('/api/plans', {
            data: {
                id: randomUUID(),
                name: 'Startable Plan',
                description: 'Ready to go',
                steps: []
            },
            headers: { 'Authorization': `Bearer ${user.token}` }
        });
        console.log(await resp.json());
        expect(resp.ok()).toBeTruthy();

        await page.reload();

        await page.getByRole('button', { name: 'Plans' }).first().click();

        const card = page.locator('div')
            .filter({ hasText: 'Startable Plan' })
            .filter({ has: page.getByRole('button', { name: 'Start' }) })
            .last();
        await card.getByRole('button', { name: 'Start' }).click();

        // Expect Preparation Modal
        const modal = page.locator('.fixed.inset-0.z-50');
        await expect(modal).toBeVisible();
        await expect(modal.getByText('Ready to go')).toBeVisible();
        // Click Start in the modal (ensure we click the button inside the modal)
        await modal.getByRole('button', { name: 'Start' }).click();

        await expect(page.getByText('Startable Plan', { exact: false })).toBeVisible();
        await expect(page.getByRole('button', { name: 'Finish' })).toBeVisible();
    });

    // --- Exercise Tests ---

    test('2.6 B. Exercise Library - Create Custom Exercise (Strength)', async ({ page, createUniqueUser }) => {
        await loginAndSetup(page, createUniqueUser);

        await page.getByRole('button', { name: 'Profile' }).click();
        await page.locator('button:has-text("Manage Exercises")').click();

        // Use force click as button might be obstructed or animating
        await page.getByRole('button', { name: /New Exercise/i }).click({ force: true });

        await expect(page.locator('div[role="dialog"]')).toBeVisible();
        await page.locator('div[role="dialog"]').getByLabel('Name').fill('Custom Bicep Curl');
        await expect(page.locator('div[role="dialog"]').getByText('Free Weights & Machines', { exact: false })).toBeVisible();

        await page.locator('div[role="dialog"]').getByRole('button', { name: 'Create' }).click();
        await page.waitForTimeout(1000);

        // Reload and filter
        await page.reload();
        await page.getByRole('button', { name: 'Profile' }).click();
        await page.locator('button:has-text("Manage Exercises")').click();

        await page.getByLabel(/Filter by name/i).fill('Custom Bicep Curl');
        await expect(page.getByText('Custom Bicep Curl')).toBeVisible();
    });

    test('2.7 B. Exercise Library - Create Custom Exercise (Bodyweight)', async ({ page, createUniqueUser }) => {
        await loginAndSetup(page, createUniqueUser);

        await page.getByRole('button', { name: 'Profile' }).click();
        await page.getByRole('button', { name: /Manage Exercises/i }).click();

        await page.getByRole('button', { name: /New Exercise/i }).click({ force: true });

        await expect(page.locator('div[role="dialog"]')).toBeVisible();
        await page.locator('div[role="dialog"]').getByLabel('Name').fill('Adv Pushup');

        // Scope to dialog and use force click for type selection
        await page.locator('div[role="dialog"]').getByRole('button', { name: /Bodyweight/i }).click({ force: true });

        await expect(page.getByLabel('Body Weight')).toBeVisible();
        await page.getByLabel('Body Weight').fill('50');
        await page.locator('div[role="dialog"]').getByRole('button', { name: 'Create' }).click();
        await page.waitForTimeout(1000);

        // Reload and filter
        await page.reload();
        await page.getByRole('button', { name: 'Profile' }).click();
        await page.getByRole('button', { name: /Manage Exercises/i }).click();

        await page.getByLabel(/Filter by name/i).fill('Adv Pushup');
        await expect(page.getByText('Adv Pushup')).toBeVisible();
        await expect(page.getByText('Bodyweight', { exact: false }).first()).toBeVisible();
    });

    test('2.8 B. Exercise Library - Edit Exercise Name', async ({ page, createUniqueUser }) => {
        // Updated to use UI creation for robustness
        await loginAndSetup(page, createUniqueUser);

        await page.getByRole('button', { name: 'Profile' }).click();
        await page.locator('button:has-text("Manage Exercises")').click();

        // Use force click as button might be obstructed or animating
        await page.getByRole('button', { name: /New Exercise/i }).click({ force: true });

        await expect(page.locator('div[role="dialog"]')).toBeVisible();
        await page.locator('div[role="dialog"]').getByLabel('Name').fill('Typo Name');
        await expect(page.locator('div[role="dialog"]').getByText('Free Weights & Machines', { exact: false })).toBeVisible();

        await page.locator('div[role="dialog"]').getByRole('button', { name: 'Create' }).click();
        await page.waitForTimeout(1000);

        // Reload and filter
        await page.reload();
        await page.getByRole('button', { name: 'Profile' }).click();
        await page.locator('button:has-text("Manage Exercises")').click();

        await page.getByLabel(/Filter by name/i).fill('Typo Name');
        await expect(page.getByText('Typo Name')).toBeVisible();

        // Filter specifically for the container that has both text and button
        const row = page.locator('div')
            .filter({ hasText: 'Typo Name' })
            .filter({ has: page.getByLabel('Edit Exercise') })
            .last();

        await expect(row).toBeVisible();
        await row.getByLabel('Edit Exercise').click();

        await page.locator('div[role="dialog"] input').first().fill('Fixed Name');
        await page.locator('div[role="dialog"]').getByRole('button', { name: 'Save', exact: true }).click();

        // Clear filter to see the renamed exercise
        await page.getByLabel(/Filter by name/i).fill('');
        await expect(page.getByText('Fixed Name')).toBeVisible();
        await expect(page.getByText('Typo Name')).not.toBeVisible();
    });

    test('2.9 B. Exercise Library - Archive/Unarchive', async ({ page, createUniqueUser }) => {
        // Updated to use UI creation for robustness
        await loginAndSetup(page, createUniqueUser);

        await page.getByRole('button', { name: 'Profile' }).click();
        await page.locator('button:has-text("Manage Exercises")').click();

        // Use force click as button might be obstructed or animating
        await page.getByRole('button', { name: /New Exercise/i }).click({ force: true });

        await expect(page.locator('div[role="dialog"]')).toBeVisible();
        await page.locator('div[role="dialog"]').getByLabel('Name').fill('Archive Me');
        await expect(page.locator('div[role="dialog"]').getByText('Free Weights & Machines', { exact: false })).toBeVisible();

        await page.locator('div[role="dialog"]').getByRole('button', { name: 'Create' }).click();
        await page.waitForTimeout(1000);

        // Reload and filter
        await page.reload();
        await page.getByRole('button', { name: 'Profile' }).click();
        await page.locator('button:has-text("Manage Exercises")').click();

        await page.getByLabel(/Filter by name/i).fill('Archive Me');
        await expect(page.getByText('Archive Me')).toBeVisible();

        const row = page.locator('div.flex.justify-between').filter({ hasText: 'Archive Me' }).last();
        // Archive button (box-archive or similar)
        await row.locator('[aria-label="Archive Exercise"]').click();

        // It should disappear or fade. "Show Archived" is false by default.
        await expect(page.getByText('Archive Me')).not.toBeVisible();

        // Toggle Show Archived
        // Label might not be linked, so we filter by text and find the adjacent checkbox
        await page.locator('div').filter({ hasText: /Show Archived/i }).last().locator('input[type="checkbox"]').check();
        await expect(page.getByText('Archive Me')).toBeVisible();

        // Unarchive
        const archivedRow = page.locator('div')
            .filter({ hasText: 'Archive Me' })
            .filter({ has: page.getByLabel('Unarchive Exercise') })
            .last();
        await archivedRow.getByLabel('Unarchive Exercise').click();

        // Verify it persists after unchecking "Show Archived"
        await page.locator('div').filter({ hasText: /Show Archived/i }).last().locator('input[type="checkbox"]').uncheck();
        await expect(page.getByText('Archive Me')).toBeVisible();
    });

    test('2.10 B. Exercise Library - Filter by Name', async ({ page, createUniqueUser, request }) => {
        const user = await loginAndSetup(page, createUniqueUser);
        await request.post('/api/exercises', {
            data: { name: 'FindThisOne', type: 'STRENGTH' },
            headers: { 'Authorization': `Bearer ${user.token}` }
        });
        await request.post('/api/exercises', {
            data: { name: 'IgnoreThatOne', type: 'STRENGTH' },
            headers: { 'Authorization': `Bearer ${user.token}` }
        });
        await page.reload();

        await page.getByRole('button', { name: 'Profile' }).click();
        await page.getByRole('button', { name: /Manage Exercises/i }).click();

        await page.getByLabel(/Filter by name/i).fill('FindThis');

        await expect(page.getByText('FindThisOne')).toBeVisible();
        await expect(page.getByText('IgnoreThatOne')).not.toBeVisible();
    });

    test('2.11 B. Exercise Library - Capitalization (Mobile)', async ({ page, createUniqueUser }) => {
        // Simulate Mobile Viewport
        await page.setViewportSize({ width: 390, height: 844 }); // iPhone 12 Pro
        await loginAndSetup(page, createUniqueUser);

        await page.getByRole('button', { name: 'Profile' }).click();
        await page.locator('button:has-text("Manage Exercises")').click();

        // Use force as FAB might be different on mobile, but text is same
        await page.getByRole('button', { name: /New Exercise/i }).click({ force: true });

        await expect(page.locator('div[role="dialog"]')).toBeVisible();

        // Verify autocapitalize attribute is set to 'words' or 'sentences'
        // In ExerciseModal.tsx it is set to 'words'
        const nameInput = page.locator('div[role="dialog"]').getByLabel('Name');
        await expect(nameInput).toHaveAttribute('autocapitalize', 'words');
    });

    test('2.12 B. Exercise Library - Unilateral', async ({ page, createUniqueUser }) => {
        await loginAndSetup(page, createUniqueUser);
        await page.getByRole('button', { name: 'Profile' }).click();
        await page.getByRole('button', { name: /Manage Exercises/i }).click();

        await page.getByRole('button', { name: /New Exercise/i }).click({ force: true });

        await expect(page.locator('div[role="dialog"]')).toBeVisible();
        await page.locator('div[role="dialog"]').getByLabel('Name').fill('Single Leg Squat');

        await page.getByLabel(/Unilateral exercise/).check();

        await page.locator('div[role="dialog"]').getByRole('button', { name: 'Create' }).click();
        await page.waitForTimeout(1000);

        // Reload and filter
        await page.reload();
        await page.getByRole('button', { name: 'Profile' }).click();
        await page.getByRole('button', { name: /Manage Exercises/i }).click();

        await page.getByLabel(/Filter by name/i).fill('Single Leg Squat');
        await expect(page.getByText('Single Leg Squat')).toBeVisible();
        await expect(page.getByText('Unilateral', { exact: false }).first()).toBeVisible();
    });

    test('2.13 B. Exercise Library - Special Types', async ({ page, createUniqueUser }) => {
        await loginAndSetup(page, createUniqueUser);
        await page.getByRole('button', { name: 'Profile' }).click();
        await page.getByRole('button', { name: /Manage Exercises/i }).click();

        await page.getByRole('button', { name: /New Exercise/i }).click({ force: true });

        await expect(page.locator('div[role="dialog"]')).toBeVisible();
        await page.locator('div[role="dialog"]').getByLabel('Name').fill('Plank Test');

        await page.locator('div[role="dialog"]').getByRole('button', { name: /Static/i }).click({ force: true });

        await page.locator('div[role="dialog"]').getByRole('button', { name: 'Create' }).click();
        await page.waitForTimeout(1000);

        // Reload and filter
        await page.reload();
        await page.getByRole('button', { name: 'Profile' }).click();
        await page.getByRole('button', { name: /Manage Exercises/i }).click();

        await page.getByLabel(/Filter by name/i).fill('Plank Test');
        await expect(page.getByText('Plank Test')).toBeVisible();
        await expect(page.getByText('Static', { exact: false }).first()).toBeVisible();
    });
});

async function loginAndSetup(page: any, createUniqueUser: any) {
    const user = await createUniqueUser();
    await page.goto('/');
    await page.getByLabel('Email').fill(user.email);
    await page.getByLabel('Password').fill(user.password);
    await page.getByRole('button', { name: 'Login' }).click();

    try {
        const heading = page.getByRole('heading', { name: /Change Password/i });
        const dashboard = page.getByText('Free Workout');
        await expect(heading.or(dashboard)).toBeVisible({ timeout: 5000 });
        if (await heading.isVisible()) {
            await page.getByLabel('New Password').fill('StrongNewPass123!');
            await page.getByRole('button', { name: /Save|Change/i }).click();
            await expect(dashboard).toBeVisible();
        }
    } catch (e) {
        // Login might already be done or dashboard loaded fast
    }
    return user;
}