/**
 * Property-Based Test: Short passwords are rejected client-side
 *
 * Feature: user-profile, Property 6 (client-side): Short passwords are rejected
 * **Validates: Requirements 2.5**
 *
 * For any string of length 1–7 (non-empty so the validation message renders —
 * the component checks `newPassword.length > 0 && newPassword.length < 8`),
 * the form displays a minimum-length validation error and does not submit a
 * request to the Auth_API.
 */
import React from 'react';
import { render, fireEvent, waitFor } from '@testing-library/react';
import fc from 'fast-check';
import UserProfilePanel from '../components/UserProfilePanel';

// Mock profile returned by the API so the form renders
const MOCK_PROFILE = {
  id: 1,
  username: 'testuser',
  email: 'test@example.com',
  group: 'Standard_User',
  created_at: '2026-01-15T10:30:00Z',
  last_login: '2026-07-20T14:22:00Z',
};

beforeEach(() => {
  process.env.REACT_APP_API_BASE = 'http://localhost:3001/api';
});

afterEach(() => {
  jest.restoreAllMocks();
});

it('Property 6 (client-side): Short passwords are rejected', async () => {
  // Generate strings of length 1–7 (non-empty so the validation triggers)
  const shortPasswordArbitrary = fc.string({ minLength: 1, maxLength: 7 });

  await fc.assert(
    fc.asyncProperty(shortPasswordArbitrary, async (shortPassword) => {
      // Mock fetch: first call returns the profile, subsequent calls are tracked
      const fetchMock = jest.fn().mockImplementation((url) => {
        if (typeof url === 'string' && url.includes('/auth/profile')) {
          return Promise.resolve({
            ok: true,
            json: async () => ({ ...MOCK_PROFILE }),
          });
        }
        // Any other call (e.g. change-password) — should NOT happen
        return Promise.resolve({
          ok: true,
          json: async () => ({ message: 'Password changed successfully' }),
        });
      });
      global.fetch = fetchMock;

      const onClose = jest.fn();
      const { container, unmount, getByPlaceholderText } = render(
        <UserProfilePanel isOpen={true} onClose={onClose} />
      );

      try {
        // Wait for the profile to load
        await waitFor(() => {
          expect(container.textContent).toContain(MOCK_PROFILE.username);
        }, { timeout: 3000 });

        // Fill in the form fields:
        // current password, the short new password, and a matching confirm password
        const currentPwInput = getByPlaceholderText('Enter current password');
        const newPwInput = getByPlaceholderText('Minimum 8 characters');
        const confirmPwInput = getByPlaceholderText('Re-enter new password');

        fireEvent.change(currentPwInput, { target: { value: 'currentpass1' } });
        fireEvent.change(newPwInput, { target: { value: shortPassword } });
        fireEvent.change(confirmPwInput, { target: { value: shortPassword } });

        // Assert the "Password must be at least 8 characters" validation error is displayed
        expect(container.textContent).toContain('Password must be at least 8 characters');

        // Assert the submit button is disabled
        const submitButton = container.querySelector('button[type="submit"]');
        expect(submitButton).not.toBeNull();
        expect(submitButton.disabled).toBe(true);

        // Assert that no call was made to the change-password endpoint
        const changePasswordCalls = fetchMock.mock.calls.filter(
          ([url]) => typeof url === 'string' && url.includes('/auth/change-password')
        );
        expect(changePasswordCalls).toHaveLength(0);
      } finally {
        unmount();
      }
    }),
    { numRuns: 100 }
  );
}, 120000);
