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

// Helper for setup
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
    }
    return user;
}

test.describe('III. Workout Tracking', () => {

    test('3.1 B. Idle State - Start Free Workout', async ({ page, createUniqueUser }) => {
        await loginAndSetup(page, createUniqueUser);
        await expect(page.getByText('Start Empty Workout').or(page.getByText('Free Workout'))).toBeVisible();
        await page.locator('div').filter({ hasText: 'My Weight' }).locator('input[type="number"]').fill('75.5');
        await page.getByRole('button', { name: /Free Workout|Start Empty/i }).click();

        await expect(page.getByRole('button', { name: 'Finish' })).toBeVisible();
        await expect(page.getByText('Select Exercise')).toBeVisible();
        await expect(page.getByText('00:00')).toBeVisible();
        await expect(page.getByText('75.5')).toBeVisible();
    });

    test('3.2 B. Idle State - Start Quick Log', async ({ page, createUniqueUser }) => {
        await loginAndSetup(page, createUniqueUser);
        await page.getByRole('button', { name: 'Quick Log' }).click();
        await expect(page.getByText('Quick Log').first()).toBeVisible();
        await expect(page.getByText('Select Exercise')).toBeVisible();
    });

    test('3.3 B. Idle State - Body Weight Defaults from Profile', async ({ page, createUniqueUser, request }) => {
        const user = await createUniqueUser();
        const updateResp = await request.patch('/api/auth/profile', {
            data: { weight: 75.5 },
            headers: { 'Authorization': `Bearer ${user.token}` }
        });
        expect(updateResp.ok()).toBeTruthy();

        await page.goto('/');
        await page.getByLabel('Email').fill(user.email);
        await page.getByLabel('Password').fill(user.password);
        await page.getByRole('button', { name: 'Login' }).click();

        const heading = page.getByRole('heading', { name: /Change Password/i });
        const dashboard = page.getByText('Start Empty Workout').or(page.getByText('Free Workout'));
        await expect(heading.or(dashboard)).toBeVisible({ timeout: 10000 });

        if (await heading.isVisible()) {
            await page.getByLabel('New Password').fill('StrongNewPass123!');
            await page.getByRole('button', { name: /Save|Change/i }).click();
            await expect(dashboard).toBeVisible();
        }

        await expect(page.getByText('Start Empty Workout').or(page.getByText('Free Workout'))).toBeVisible();
        const weightInput = page.locator('div').filter({ hasText: 'My Weight' }).locator('input[type="number"]');
        await expect(weightInput).toBeVisible();
        await expect(weightInput).toHaveValue('75.5');
    });

    test('3.4 C. Active Session - Log Strength Set', async ({ page, createUniqueUser, request }) => {
        const user = await loginAndSetup(page, createUniqueUser);
        const exName = 'Bench Press ' + randomUUID().slice(0, 4);
        await request.post('/api/exercises', {
            data: { name: exName, type: 'STRENGTH' },
            headers: { 'Authorization': `Bearer ${user.token}` }
        });

        await page.getByRole('button', { name: /Free Workout|Start Empty/i }).click();
        await page.getByText('Select Exercise').click();
        await page.getByText(exName).click();

        await page.getByLabel('Weight (kg)').first().fill('80');
        await page.getByLabel('Reps').first().fill('5');
        await page.getByRole('button', { name: /Log Set/i }).click();

        await expect(page.getByText('80 kg x 5 reps')).toBeVisible();
    });

    test('3.5 C. Active Session - Log Bodyweight Set', async ({ page, createUniqueUser, request }) => {
        const user = await loginAndSetup(page, createUniqueUser);
        const exName = 'Pull-up ' + randomUUID().slice(0, 4);
        await request.post('/api/exercises', {
            data: { name: exName, type: 'BODYWEIGHT' },
            headers: { 'Authorization': `Bearer ${user.token}` }
        });

        await page.getByRole('button', { name: /Free Workout|Start Empty/i }).click();
        await page.getByText('Select Exercise').click();
        await page.getByText(exName).click();

        await page.getByLabel(/Add.? Weight/i).first().fill('10');
        await page.getByLabel('Reps').first().fill('8');
        await page.getByRole('button', { name: /Log Set/i }).click();

        await expect(page.getByText('+10 kg x 8 reps')).toBeVisible();

        await page.getByLabel(/Add.? Weight/i).first().fill('-30');
        await page.getByLabel('Reps').first().fill('12');
        await page.getByRole('button', { name: /Log Set/i }).click();
        await expect(page.getByText('-30 kg x 12 reps')).toBeVisible();
    });

    test('3.6 C. Active Session - Log Cardio Set', async ({ page, createUniqueUser, request }) => {
        const user = await loginAndSetup(page, createUniqueUser);
        const exName = 'Running ' + randomUUID().slice(0, 4);
        await request.post('/api/exercises', {
            data: { name: exName, type: 'CARDIO' },
            headers: { 'Authorization': `Bearer ${user.token}` }
        });

        await page.getByRole('button', { name: /Free Workout|Start Empty/i }).click();
        await page.getByRole('textbox', { name: /Select Exercise/i }).click();
        await page.getByText(exName).click();

        await page.getByLabel('Time').fill('300');
        await page.getByLabel('Distance (m)').fill('1000');
        await page.getByRole('button', { name: /Log Set/i }).click();

        await expect(page.getByText('300s')).toBeVisible();
        await expect(page.getByText('1000m')).toBeVisible();
    });

    test('3.7 C. Active Session - Edit Logged Set', async ({ page, createUniqueUser, request }) => {
        const user = await loginAndSetup(page, createUniqueUser);
        const exName = 'Edit Test ' + randomUUID().slice(0, 4);
        await request.post('/api/exercises', {
            data: { name: exName, type: 'STRENGTH' },
            headers: { 'Authorization': `Bearer ${user.token}` }
        });

        await page.getByRole('button', { name: /Free Workout|Start Empty/i }).click();
        await page.getByRole('textbox', { name: /Select Exercise/i }).click();
        await page.getByText(exName).click();

        await page.getByLabel('Weight (kg)').first().fill('100');
        await page.getByLabel('Reps').first().fill('10');
        await page.getByRole('button', { name: /Log Set/i }).click();
        await expect(page.getByText('100 kg x 10 reps')).toBeVisible();

        // Use filter to find the container, then find 'Edit' button inside it
        const row = page.locator('div.shadow-elevation-1').filter({ hasText: '100 kg x 10 reps' }).first();
        // The Edit button might be an icon button or text. Assuming it's the one with 'Edit' text or accessible name
        await row.getByRole('button', { name: /Edit/i }).click();

        // Wait for edit inputs to appear
        // The modal should be visible
        const editModal = page.locator('div[role="dialog"]');
        await expect(editModal.getByRole('button', { name: 'Save', exact: true })).toBeVisible();

        // EditSetModal doesn't use htmlFor, so we find the container with the label
        await editModal.locator('div.bg-surface-container-high').filter({ hasText: 'Weight (kg)' }).locator('input').fill('105');
        await editModal.locator('div.bg-surface-container-high').filter({ hasText: 'Reps' }).locator('input').fill('11');
        await editModal.getByRole('button', { name: 'Save', exact: true }).click();

        await expect(page.getByText('105 kg x 11 reps')).toBeVisible();
        await expect(page.getByText('100 kg x 10 reps')).not.toBeVisible();
    });

    test('3.8 C. Active Session - Delete Logged Set', async ({ page, createUniqueUser, request }) => {
        const user = await loginAndSetup(page, createUniqueUser);
        const exName = 'Delete Test ' + randomUUID().slice(0, 4);
        await request.post('/api/exercises', {
            data: { name: exName, type: 'STRENGTH' },
            headers: { 'Authorization': `Bearer ${user.token}` }
        });

        await page.getByRole('button', { name: /Free Workout|Start Empty/i }).click();
        await page.getByRole('textbox', { name: /Select Exercise/i }).click();
        await page.getByText(exName).click();

        await page.getByLabel('Weight (kg)').first().fill('100');
        await page.getByLabel('Reps').first().fill('10');
        await page.getByRole('button', { name: /Log Set/i }).click();
        await expect(page.getByText('100 kg x 10 reps')).toBeVisible();

        const row = page.locator('div.shadow-elevation-1').filter({ hasText: '100 kg x 10 reps' }).first();
        page.on('dialog', dialog => dialog.accept());
        await row.getByRole('button', { name: /Delete|Remove/i }).click();

        await expect(page.getByText('100 kg x 10 reps')).not.toBeVisible();
    });

    test('3.9 C. Active Session - Finish Session', async ({ page, createUniqueUser }) => {
        const user = await loginAndSetup(page, createUniqueUser);
        await page.getByRole('button', { name: /Free Workout|Start Empty/i }).click();

        await page.getByRole('button', { name: 'Finish' }).click();
        await page.getByRole('button', { name: 'Confirm' }).click();
        await expect(page.getByText(/Free Workout|Start Empty/i)).toBeVisible();

        await page.getByRole('button', { name: 'History' }).click();
        await expect(page.getByText('No plan').first()).toBeVisible();
        await expect(page.getByText('Sets: 0').first()).toBeVisible();
    });

    test('3.10 C. Active Session - Quit Session Without Saving', async ({ page, createUniqueUser }) => {
        const user = await loginAndSetup(page, createUniqueUser);
        await page.getByRole('button', { name: /Free Workout|Start Empty/i }).click();

        await page.getByRole('button', { name: 'Options' }).click();
        await page.getByText(/Quit/i).click();
        await page.getByRole('button', { name: 'Confirm' }).click();

        await expect(page.getByText(/Free Workout|Start Empty/i)).toBeVisible();
    });

    test('3.11 C. Active Session - Plan Progression and Jump to Step', async ({ page, createUniqueUser, request }) => {
        const user = await loginAndSetup(page, createUniqueUser);

        const ex1Id = randomUUID();
        const ex2Id = randomUUID();
        const ex3Id = 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}` } });
        await request.post('/api/exercises', { data: { id: ex3Id, name: 'Ex Three', type: 'STRENGTH' }, headers: { 'Authorization': `Bearer ${user.token}` } });

        const planId = randomUUID();
        await request.post('/api/plans', {
            data: {
                id: planId,
                name: 'Progression Plan',
                steps: [
                    { exerciseId: ex1Id },
                    { exerciseId: ex2Id },
                    { exerciseId: ex3Id }
                ]
            },
            headers: { 'Authorization': `Bearer ${user.token}` }
        });

        await page.getByRole('button', { name: 'Plans' }).click();
        const card = page.locator('div').filter({ hasText: 'Progression Plan' }).last();
        // Assuming there isn't a direct start button on the card list without expansion, 
        // but often there is. If not, click card then start.
        // Assuming direct start or via expand.
        // Let's try to find Start button in the card 
        if (await card.getByRole('button', { name: 'Start' }).isVisible()) {
            await card.getByRole('button', { name: 'Start' }).click();
        } else {
            // Click card to expand details then start?
            // Or check if we are in Plans view.
        }
        // Fallback:
        await page.locator('div').filter({ hasText: 'Progression Plan' }).getByRole('button', { name: 'Start' }).click();

        // Prepare modal
        const modal = page.locator('.fixed.inset-0.z-50');
        if (await modal.isVisible()) {
            await modal.getByRole('button', { name: 'Start' }).click();
        }

        await expect(page.getByText('Ex One')).toBeVisible();

        await page.getByLabel('Weight (kg)').first().fill('50');
        await page.getByLabel('Reps').first().fill('10');
        await page.getByRole('button', { name: /Log Set/i }).click();

        await page.getByText(/Step \d+ of \d+/i).click();
        await page.getByRole('button', { name: /Ex Three/i }).click();
        await expect(page.getByText('Ex Three')).toBeVisible();
    });

    test('3.12 D. Sporadic Logging - Log Strength Sporadic Set', async ({ page, createUniqueUser, request }) => {
        const user = await loginAndSetup(page, createUniqueUser);
        const exName = 'Quick Ex ' + randomUUID().slice(0, 4);
        await request.post('/api/exercises', {
            data: { name: exName, type: 'STRENGTH' },
            headers: { 'Authorization': `Bearer ${user.token}` }
        });

        await page.getByRole('button', { name: /Quick Log/i }).click();
        await page.getByRole('textbox', { name: /Select Exercise/i }).click();
        await page.getByText(exName).click();

        await page.getByLabel(/Weight/i).first().fill('60');
        await page.getByLabel(/Reps/i).first().fill('8');
        await page.getByRole('button', { name: /Log Set/i }).click();

        await expect(page.getByText('60 kg x 8 reps')).toBeVisible();
    });

    test('3.13 D. Sporadic Logging - Exercise Search and Clear', async ({ page, createUniqueUser, request }) => {
        const user = await loginAndSetup(page, createUniqueUser);
        const benchPressName = 'Bench Press ' + randomUUID().slice(0, 4);
        const benchDipName = 'Bench Dip ' + randomUUID().slice(0, 4);
        const squatName = 'Squat ' + randomUUID().slice(0, 4);

        await request.post('/api/exercises', { data: { name: benchPressName, type: 'STRENGTH' }, headers: { 'Authorization': `Bearer ${user.token}` } });
        await request.post('/api/exercises', { data: { name: benchDipName, type: 'STRENGTH' }, headers: { 'Authorization': `Bearer ${user.token}` } });
        await request.post('/api/exercises', { data: { name: squatName, type: 'STRENGTH' }, headers: { 'Authorization': `Bearer ${user.token}` } });

        await page.getByRole('button', { name: /Quick Log/i }).click();

        await page.getByRole('textbox', { name: /Select Exercise/i }).click();
        await page.getByRole('textbox', { name: /Select Exercise/i }).fill(benchPressName.substring(0, 4)); // "Benc"

        await expect(page.getByText(benchPressName)).toBeVisible();
        await expect(page.getByText(benchDipName)).toBeVisible();
        await expect(page.getByText(squatName)).not.toBeVisible();

        await page.getByRole('textbox', { name: /Select Exercise/i }).click();
        await page.getByRole('textbox', { name: /Select Exercise/i }).fill('');

        await expect(page.getByText(squatName)).toBeVisible();
    });

    test('3.14 C. Active Session - Log Unilateral Set', async ({ page, createUniqueUser, request }) => {
        const user = await loginAndSetup(page, createUniqueUser);
        const exName = 'Uni Row ' + randomUUID().slice(0, 4);
        await request.post('/api/exercises', {
            data: { name: exName, type: 'STRENGTH', isUnilateral: true },
            headers: { 'Authorization': `Bearer ${user.token}` }
        });

        await page.getByRole('button', { name: /Free Workout|Start Empty/i }).click();
        await page.getByRole('textbox', { name: /Select Exercise/i }).click();
        await page.getByRole('textbox', { name: /Select Exercise/i }).fill(exName);
        await page.getByText(exName).click();

        await expect(page.getByRole('button', { name: 'L', exact: true })).toBeVisible();

        // Helper to log a set
        const logSet = async (side: 'L' | 'R' | 'A') => {
            const logger = page.locator('div').filter({ has: page.getByRole('button', { name: /Log Set|Saved/i }) }).last();
            await logger.getByRole('button', { name: side, exact: true }).click();
            const weightInput = logger.getByLabel('Weight (kg)');
            await weightInput.click();
            await weightInput.fill('20');
            await logger.getByLabel('Reps').fill('10');
            await logger.getByRole('button', { name: /Log Set|Saved/i }).click();
        };

        await logSet('L');
        await expect(page.getByText('Left', { exact: true })).toBeVisible();

        await logSet('R');
        await expect(page.getByText('Right', { exact: true })).toBeVisible();

        const rightSetRow = page.locator('.bg-surface-container.rounded-xl.shadow-elevation-1').first();
        await rightSetRow.getByRole('button', { name: 'Edit' }).click();

        const editModal = page.locator('div[role="dialog"]');
        const saveButton = editModal.getByRole('button', { name: /Save/i });
        const aButton = editModal.getByRole('button', { name: 'A', exact: true });
        await aButton.click();
        await saveButton.click();
        await expect(page.getByText(/Alternately/i)).toBeVisible();
    });

    test('3.15 C. Active Session - Log Special Type Set', async ({ page, createUniqueUser, request }) => {
        const user = await loginAndSetup(page, createUniqueUser);
        const plankName = 'Plank ' + randomUUID().slice(0, 4);
        await request.post('/api/exercises', {
            data: { name: plankName, type: 'STATIC' },
            headers: { 'Authorization': `Bearer ${user.token}` }
        });

        await page.getByRole('button', { name: /Free Workout|Start Empty/i }).click();
        await page.getByRole('textbox', { name: /Select Exercise/i }).click();
        await page.getByText(plankName).click();

        await page.getByLabel('Time (sec)').fill('60');
        await page.getByRole('button', { name: /Log Set/i }).click();
        await expect(page.getByText('60s')).toBeVisible();
    });

    test('3.16 C. Active Session - Log Set with Default Reps', async ({ page, createUniqueUser, request }) => {
        const user = await loginAndSetup(page, createUniqueUser);
        const exName = 'Default Reps ' + randomUUID().slice(0, 4);
        await request.post('/api/exercises', {
            data: { name: exName, type: 'STRENGTH' },
            headers: { 'Authorization': `Bearer ${user.token}` }
        });

        await page.getByRole('button', { name: /Free Workout|Start Empty/i }).click();
        await page.getByRole('textbox', { name: /Select Exercise/i }).click();
        await page.getByText(exName).click();

        await page.getByLabel('Weight (kg)').first().fill('50');
        await page.getByRole('button', { name: /Log Set/i }).click();

        await expect(page.getByText('50 kg x 1 reps')).toBeVisible();
    });

    test('3.17 B. Idle State - Days Off Training Logic', async ({ page, createUniqueUser }) => {
        const user = await loginAndSetup(page, createUniqueUser);
        await expect(page.getByText('Do your very first workout today.')).toBeVisible();

        await page.getByRole('button', { name: /Free Workout|Start Empty/i }).click();
        await page.getByRole('button', { name: 'Finish' }).click();
        await page.getByRole('button', { name: 'Confirm' }).click();

        await expect(page.getByText('Last workout: Today')).toBeVisible();
    });

    test.describe('Rest Timer', () => {
        // Merged from rest-timer.spec.ts
        test('3.16 C. Rest Timer - Manual Edit & Validation', async ({ page, createUniqueUser }) => {
            await loginAndSetup(page, createUniqueUser);
            await page.getByRole('button', { name: 'Free Workout' }).click();
            const fab = page.locator('.fixed.bottom-24.right-6');
            await fab.click();
            const editBtn = fab.locator('button[aria-label="Edit"]');
            await editBtn.click();
            const timerInput = page.getByRole('textbox').nth(1);
            await timerInput.fill('90');
            await expect(timerInput).toHaveValue('90');
            await timerInput.fill('10:99');
            await expect(timerInput).toHaveValue('10:59');
            const saveBtn = fab.locator('button[aria-label="Save"]');
            await saveBtn.click();
        });

        test('3.17 C. Rest Timer - Context & Persistence', async ({ page, createUniqueUser }) => {
            await loginAndSetup(page, createUniqueUser);
            await page.getByRole('button', { name: 'Free Workout' }).click();
            const fab = page.locator('.fixed.bottom-24.right-6');
            await fab.click();
            const editBtn = fab.locator('button[aria-label="Edit"]');
            await editBtn.click();
            await page.getByRole('textbox').nth(1).fill('45');
            await fab.locator('button[aria-label="Save"]').click();

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

            await page.getByRole('button', { name: 'Quick Log' }).click();
            const quickFab = page.locator('.fixed.bottom-24.right-6');
            await quickFab.click();
            await expect(page.locator('div').filter({ hasText: /0:45/ }).first()).toBeVisible();
        });

        test('3.18 C. Rest Timer - Plan Integration', async ({ page, createUniqueUser }) => {
            await loginAndSetup(page, createUniqueUser);
            await page.getByRole('button', { name: 'Plans' }).click();
            await page.getByRole('button', { name: 'Create Plan' }).click();
            await expect(page.getByRole('button', { name: 'Manually' })).toBeVisible();
            await page.getByRole('button', { name: 'Manually' }).click();
            await page.getByRole('textbox', { name: 'Name' }).fill('Timer Test Plan');

            await page.getByRole('button', { name: 'Add Exercise' }).click();
            await page.getByRole('button', { name: 'New Exercise' }).click();
            // Scope to the top-most dialog for the new exercise form
            const newExerciseModal = page.locator('div[role="dialog"]').last();
            await newExerciseModal.getByLabel('Name').fill('Bench Press Test');
            await newExerciseModal.getByRole('button', { name: 'Free Weights & Machines' }).click();
            await newExerciseModal.getByRole('button', { name: 'Create' }).click();
            // Rest input is on the plan step card now
            await expect(page.getByTestId('plan-exercise-item').filter({ hasText: 'Bench Press Test' })).toBeVisible();
            await page.locator('input[placeholder="Rest (s)"]').last().fill('30');

            await page.getByRole('button', { name: 'Add Exercise' }).click();
            await page.getByRole('button', { name: 'New Exercise' }).click();
            await newExerciseModal.getByLabel('Name').fill('Squat Test');
            await newExerciseModal.getByRole('button', { name: 'Free Weights & Machines' }).click();
            await newExerciseModal.getByRole('button', { name: 'Create' }).click();

            await expect(page.getByTestId('plan-exercise-item').filter({ hasText: 'Squat Test' })).toBeVisible();
            await page.locator('input[placeholder="Rest (s)"]').last().fill('60');

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

            const modal = page.locator('.fixed.inset-0.z-50');
            if (await modal.isVisible()) {
                await modal.getByRole('button', { name: 'Start' }).click();
            }

            const fab = page.locator('.fixed.bottom-24.right-6');
            await fab.click();
            await expect(page.locator('div').filter({ hasText: /0:30/ }).first()).toBeVisible();
            await fab.locator('button[aria-label="Start"]').click();

            await page.getByRole('button', { name: 'Log Set' }).click();
            await expect(page.locator('div').filter({ hasText: /0:2[0-9]/ }).first()).toBeVisible();

            const resetBtn = fab.locator('button[aria-label="Reset"]');
            await resetBtn.click();

            await expect(page.locator('div').filter({ hasText: /1:00/ }).first()).toBeVisible();
        });
    });
});
