/**
 * User Profile View Test
 * 
 * Tags: @user_mgmt @p2 @regression @ui
 * 
 * Comprehensive functional testing of user profile:
 * - Profile data editing and persistence
 * - Form validation
 * - Province selection
 * - Address management
 * - Data integrity after save/reload
 */

import { test, expect } from '@playwright/test';
import { printTestCase, printSuccess, printWarning, ensureAuthenticated } from '../../helpers/test-helpers';

test.describe('03_User_Management - User Profile View', () => {
  // Use authenticated state for all tests in this suite
  test.use({ storageState: 'auth.json' });

  let originalProfileData: any = {};

  test.beforeEach(async ({ page }) => {
    // Ensure we're authenticated before navigating anywhere
    await ensureAuthenticated(page);
    
    console.log('\n🚀 Navigating to user profile page...');
    await page.goto('/users/userProfile');
    await page.waitForLoadState('load');
    
    // Store original profile data for restoration
    originalProfileData = {
      fullname: await page.locator('#inputFullname').inputValue(),
      phone: await page.locator('#inputPhone').inputValue(),
      addressLine1: await page.locator('#inputAddressLine1').inputValue(),
      addressLine2: await page.locator('#inputAddressLine2').inputValue(),
      province: await page.locator('#inputProvince').inputValue(),
      country: await page.locator('#inputCountry').inputValue(),
      postcode: await page.locator('#inputPostcode').inputValue()
    };
    
    console.log('✅ User profile page loaded and original data captured');
  });

  test.afterEach(async ({ page }) => {
    // Restore original profile data if it was modified
    if (originalProfileData.fullname) {
      await page.goto('/users/userProfile');
      await page.waitForLoadState('load');
      
      await page.locator('#inputFullname').fill(originalProfileData.fullname);
      await page.locator('#inputPhone').fill(originalProfileData.phone || '');
      await page.locator('#inputAddressLine1').fill(originalProfileData.addressLine1 || '');
      await page.locator('#inputAddressLine2').fill(originalProfileData.addressLine2 || '');
      await page.locator('#inputProvince').selectOption(originalProfileData.province || '');
      await page.locator('#inputCountry').fill(originalProfileData.country || '');
      await page.locator('#inputPostcode').fill(originalProfileData.postcode || '');
      
      console.log('✅ Original profile data restored');
    }
  });

  test('Test Case 1: Navigate to user profile page', async ({ page }) => {
    printTestCase(1, 'Navigate to User Profile Page');
    
    const currentUrl = page.url();
    expect(currentUrl).toContain('/users/userProfile');
    expect(currentUrl).not.toContain('/login');
    printSuccess('Profile page accessible with authentication');
    
    const heading = page.locator('h5:has-text("Profile Settings")');
    await expect(heading).toBeVisible();
    printSuccess('Profile Settings heading visible');
  });

  test('Test Case 2: Test profile field editing', async ({ page }) => {
    printTestCase(2, 'Test Profile Field Editing');
    
    const fullnameInput = page.locator('#inputFullname');
    const phoneInput = page.locator('#inputPhone');
    
    // Get initial values
    const initialFullname = await fullnameInput.inputValue();
    console.log(`✓ Initial fullname: ${initialFullname}`);
    
    // Edit fullname
    const testFullname = `Test User ${Date.now()}`;
    await fullnameInput.clear();
    await fullnameInput.fill(testFullname);
    
    const newValue = await fullnameInput.inputValue();
    expect(newValue).toBe(testFullname);
    printSuccess('Fullname field editing works');
    
    // Edit phone
    const testPhone = '+27 11 123 4567';
    await phoneInput.clear();
    await phoneInput.fill(testPhone);
    
    const phoneValue = await phoneInput.inputValue();
    expect(phoneValue).toBe(testPhone);
    printSuccess('Phone field editing works');
    
    // Restore original values (don't save)
    await fullnameInput.clear();
    await fullnameInput.fill(initialFullname);
    printSuccess('Original values restored');
  });

  test('Test Case 3: Test province dropdown selection', async ({ page }) => {
    printTestCase(3, 'Test Province Dropdown Selection');
    
    const provinceSelect = page.locator('#inputProvince');
    
    // Get initial value
    const initialProvince = await provinceSelect.inputValue();
    console.log(`✓ Initial province: ${initialProvince || '(none)'}`);
    
    // Select a different province
    await provinceSelect.selectOption('Gauteng');
    await page.waitForTimeout(500);
    
    const selectedValue = await provinceSelect.inputValue();
    expect(selectedValue).toBe('Gauteng');
    printSuccess('Province selection works: Gauteng');
    
    // Try another province
    await provinceSelect.selectOption('Western Cape');
    await page.waitForTimeout(500);
    
    const secondValue = await provinceSelect.inputValue();
    expect(secondValue).toBe('Western Cape');
    printSuccess('Province selection works: Western Cape');
    
    // Restore original
    if (initialProvince) {
      await provinceSelect.selectOption(initialProvince);
    } else {
      await provinceSelect.selectOption('');
    }
    printSuccess('Original province restored');
  });

  test('Test Case 4: Test address fields editing', async ({ page }) => {
    printTestCase(4, 'Test Address Fields Editing');
    
    const addressLine1 = page.locator('#inputAddressLine1');
    const addressLine2 = page.locator('#inputAddressLine2');
    const postcode = page.locator('#inputPostcode');
    const country = page.locator('#inputCountry');
    
    // Get initial values
    const initialAddr1 = await addressLine1.inputValue();
    const initialAddr2 = await addressLine2.inputValue();
    
    // Edit address fields
    await addressLine1.clear();
    await addressLine1.fill('123 Test Street');
    
    await addressLine2.clear();
    await addressLine2.fill('Suite 456');
    
    await postcode.clear();
    await postcode.fill('2001');
    
    await country.clear();
    await country.fill('South Africa');
    
    // Verify changes
    expect(await addressLine1.inputValue()).toBe('123 Test Street');
    expect(await addressLine2.inputValue()).toBe('Suite 456');
    expect(await postcode.inputValue()).toBe('2001');
    expect(await country.inputValue()).toBe('South Africa');
    printSuccess('All address fields editable');
    
    // Restore original values
    await addressLine1.clear();
    await addressLine1.fill(initialAddr1 || '');
    await addressLine2.clear();
    await addressLine2.fill(initialAddr2 || '');
    printSuccess('Original address data restored');
  });

  test('Test Case 5: Test form validation - empty required field', async ({ page }) => {
    printTestCase(5, 'Test Form Validation - Empty Required Field');
    
    const fullnameInput = page.locator('#inputFullname');
    const saveButton = page.locator('button[type="submit"]:has-text("Save Profile")');
    const initialValue = await fullnameInput.inputValue();
    
    // Clear required field
    await fullnameInput.clear();
    printSuccess('Cleared required fullname field');
    
    // Try to submit
    await saveButton.click();
    printSuccess('Clicked save button');
    
    // Wait for validation response
    await page.waitForTimeout(2000);
    
    // Check for error messages
    const errorAlert = page.locator('.alert-danger, .invalid-feedback');
    const errorCount = await errorAlert.count();
    
    if (errorCount > 0 && await errorAlert.first().isVisible()) {
      const errorText = await errorAlert.first().textContent();
      console.log(`✓ Validation error displayed: ${errorText}`);
      printSuccess('Form validation working - empty field rejected');
    } else {
      // Check if form prevented submission (field still empty)
      const currentValue = await fullnameInput.inputValue();
      if (currentValue === '') {
        printSuccess('Form prevented submission with empty field');
      } else {
        printWarning('Validation behavior unclear - field may have reverted');
      }
    }
    
    // Restore original value
    await fullnameInput.fill(initialValue);
    printSuccess('Original fullname restored');
  });

  test('Test Case 6: Test profile data persistence', async ({ page }) => {
    printTestCase(6, 'Test Profile Data Persistence');
    
    // Get initial values
    const initialFullname = await page.locator('#inputFullname').inputValue();
    const initialPhone = await page.locator('#inputPhone').inputValue();
    console.log(`✓ Initial - Fullname: ${initialFullname}, Phone: ${initialPhone || '(empty)'}`);
    
    // Reload the page
    await page.reload();
    await page.waitForLoadState('load');
    printSuccess('Page reloaded');
    
    // Verify data persisted
    const reloadedFullname = await page.locator('#inputFullname').inputValue();
    const reloadedPhone = await page.locator('#inputPhone').inputValue();
    
    expect(reloadedFullname).toBe(initialFullname);
    expect(reloadedPhone).toBe(initialPhone);
    console.log(`✓ After reload - Fullname: ${reloadedFullname}, Phone: ${reloadedPhone || '(empty)'}`);
    printSuccess('Profile data persisted correctly after reload');
  });

  test('Test Case 7: Test profile image upload trigger', async ({ page }) => {
    printTestCase(7, 'Test Profile Image Upload Trigger');
    
    const profileImage = page.locator('#profile_image');
    const fileInput = page.locator('#file');
    
    await expect(profileImage).toBeVisible();
    printSuccess('Profile image is visible');
    
    // Verify file input exists and has correct accept attribute
    await expect(fileInput).toBeAttached();
    const acceptAttr = await fileInput.getAttribute('accept');
    expect(acceptAttr).toBe('image/*');
    console.log(`✓ File input accepts: ${acceptAttr}`);
    printSuccess('File input configured correctly for images');
    
    // Verify file input is hidden (d-none class)
    const fileInputClasses = await fileInput.getAttribute('class');
    expect(fileInputClasses).toContain('d-none');
    printSuccess('File input is properly hidden');
  });

  test('Test Case 8: Test phone number field with helper text', async ({ page }) => {
    printTestCase(8, 'Test Phone Number Field with Helper Text');
    
    const phoneInput = page.locator('#inputPhone');
    await expect(phoneInput).toBeVisible();
    
    // Get and verify placeholder
    const placeholder = await phoneInput.getAttribute('placeholder');
    console.log(`✓ Phone placeholder: ${placeholder}`);
    expect(placeholder).toContain('123');
    printSuccess('Phone field has example placeholder');
    
    // Check for helper text
    const helperText = page.locator('small.form-text.text-muted');
    if (await helperText.count() > 0) {
      const helperContent = await helperText.textContent();
      expect(helperContent).toContain('format');
      console.log(`✓ Helper text: ${helperContent?.substring(0, 60)}...`);
      printSuccess('Phone field has format helper text');
    } else {
      printWarning('No helper text found');
    }
    
    // Test entering phone number
    const initialPhone = await phoneInput.inputValue();
    await phoneInput.clear();
    await phoneInput.fill('+27 82 123 4567');
    
    const enteredValue = await phoneInput.inputValue();
    expect(enteredValue).toBe('+27 82 123 4567');
    printSuccess('Phone number entry works');
    
    // Restore original
    await phoneInput.clear();
    await phoneInput.fill(initialPhone || '');
  });

  test('Test Case 9: Test all province options', async ({ page }) => {
    printTestCase(9, 'Test All Province Options');
    
    const provinceSelect = page.locator('#inputProvince');
    const initialProvince = await provinceSelect.inputValue();
    
    // Get all options
    const options = await provinceSelect.locator('option').allTextContents();
    console.log(`✓ Found ${options.length} province options`);
    
    // Expected SA provinces
    const expectedProvinces = [
      'Eastern Cape', 'Free State', 'Gauteng', 'KwaZulu-Natal',
      'Limpopo', 'Mpumalanga', 'Northern Cape', 'North West', 'Western Cape'
    ];
    
    let foundCount = 0;
    for (const province of expectedProvinces) {
      if (options.some(opt => opt.includes(province))) {
        foundCount++;
        console.log(`  ✓ ${province}`);
      }
    }
    
    expect(foundCount).toBe(expectedProvinces.length);
    printSuccess(`All ${expectedProvinces.length} SA provinces present`);
    
    // Test selecting each province
    for (const province of expectedProvinces.slice(0, 3)) {
      await provinceSelect.selectOption(province);
      await page.waitForTimeout(200);
      const selected = await provinceSelect.inputValue();
      expect(selected).toBe(province);
      console.log(`  ✓ Selected: ${province}`);
    }
    printSuccess('Province selection working for all options');
    
    // Restore original
    if (initialProvince) {
      await provinceSelect.selectOption(initialProvince);
    }
  });

  test('Test Case 10: Test responsive design', async ({ page }) => {
    printTestCase(10, 'Test Responsive Design');
    
    const viewports = [
      { width: 1280, height: 720, name: 'Desktop' },
      { width: 768, height: 1024, name: 'Tablet' },
      { width: 375, height: 667, name: 'Mobile' }
    ];
    
    for (const viewport of viewports) {
      await page.setViewportSize({ width: viewport.width, height: viewport.height });
      console.log(`\n📱 Testing ${viewport.name} (${viewport.width}x${viewport.height})`);
      await page.waitForTimeout(500);
      
      // Verify key elements are accessible
      const profileForm = page.locator('#userForm');
      await expect(profileForm).toBeVisible();
      console.log(`  ✓ Profile form visible`);
      
      const fullnameInput = page.locator('#inputFullname');
      await expect(fullnameInput).toBeVisible();
      console.log(`  ✓ Fullname input accessible`);
      
      const saveButton = page.locator('button[type="submit"]:has-text("Save Profile")');
      await expect(saveButton).toBeVisible();
      console.log(`  ✓ Save button visible`);
    }
    
    // Reset viewport
    await page.setViewportSize({ width: 1280, height: 720 });
    printSuccess('All viewports tested successfully');
  });
});
