/**
 * MCP Code Execution Script: Write Comprehensive Account Management Tests
 * Token Savings: ~25,000 tokens by using MCP testing server
 */

import * as fs from 'fs/promises';
import * as path from 'path';

// Helper to ensure directory exists
async function ensureDir(dirPath: string) {
  try {
    await fs.mkdir(dirPath, { recursive: true });
  } catch (err) {
    // Directory might already exist
  }
}

// Helper to write file with directory creation
async function writeTestFile(filePath: string, content: string) {
  const dir = path.dirname(filePath);
  await ensureDir(dir);
  await fs.writeFile(filePath, content, 'utf-8');
  console.log(`✅ Created: ${filePath}`);
}

async function createAccountTests() {
  const baseDir = '/Users/Asim/Desktop/mawidi_codex/mawidi-site';
  
  console.log('🧪 Creating comprehensive account management tests...\n');

  // ========================================
  // 1. UNIT TESTS - Components
  // ========================================
  
  const accountDropdownTest = `import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { AccountDropdown } from '@/components/AccountDropdown';
import { signOut } from 'next-auth/react';

// Mock next-auth
jest.mock('next-auth/react', () => ({
  signOut: jest.fn(),
}));

// Mock navigation
const mockPush = jest.fn();
jest.mock('next/navigation', () => ({
  useRouter: () => ({
    push: mockPush,
  }),
}));

describe('AccountDropdown', () => {
  const mockUser = {
    id: '1',
    email: 'test@example.com',
    name: 'Test User',
    companyName: 'Test Company',
    image: null,
  };

  beforeEach(() => {
    jest.clearAllMocks();
  });

  describe('Rendering', () => {
    it('should render with user information', () => {
      render(<AccountDropdown user={mockUser} lang="en" />);
      
      expect(screen.getByText('Test User')).toBeInTheDocument();
      expect(screen.getByText('test@example.com')).toBeInTheDocument();
    });

    it('should show user initials when no image', () => {
      render(<AccountDropdown user={mockUser} lang="en" />);
      
      expect(screen.getByText('TU')).toBeInTheDocument(); // Test User
    });

    it('should show user image when provided', () => {
      const userWithImage = { ...mockUser, image: 'https://example.com/avatar.jpg' };
      render(<AccountDropdown user={userWithImage} lang="en" />);
      
      const img = screen.getByRole('img');
      expect(img).toHaveAttribute('src', expect.stringContaining('avatar.jpg'));
    });
  });

  describe('Dropdown Interaction', () => {
    it('should be closed by default', () => {
      render(<AccountDropdown user={mockUser} lang="en" />);
      
      expect(screen.queryByText('My Account')).not.toBeInTheDocument();
    });

    it('should open dropdown on click', async () => {
      render(<AccountDropdown user={mockUser} lang="en" />);
      
      const trigger = screen.getByRole('button');
      fireEvent.click(trigger);
      
      await waitFor(() => {
        expect(screen.getByText('My Account')).toBeInTheDocument();
      });
    });

    it('should close dropdown on second click', async () => {
      render(<AccountDropdown user={mockUser} lang="en" />);
      
      const trigger = screen.getByRole('button');
      fireEvent.click(trigger);
      
      await waitFor(() => {
        expect(screen.getByText('My Account')).toBeInTheDocument();
      });
      
      fireEvent.click(trigger);
      
      await waitFor(() => {
        expect(screen.queryByText('My Account')).not.toBeInTheDocument();
      });
    });

    it('should close dropdown when clicking outside', async () => {
      render(<AccountDropdown user={mockUser} lang="en" />);
      
      const trigger = screen.getByRole('button');
      fireEvent.click(trigger);
      
      await waitFor(() => {
        expect(screen.getByText('My Account')).toBeInTheDocument();
      });
      
      fireEvent.click(document.body);
      
      await waitFor(() => {
        expect(screen.queryByText('My Account')).not.toBeInTheDocument();
      });
    });
  });

  describe('Menu Items', () => {
    it('should show correct menu items in English', async () => {
      render(<AccountDropdown user={mockUser} lang="en" />);
      
      fireEvent.click(screen.getByRole('button'));
      
      await waitFor(() => {
        expect(screen.getByText('My Account')).toBeInTheDocument();
        expect(screen.getByText('Settings')).toBeInTheDocument();
        expect(screen.getByText('Billing')).toBeInTheDocument();
        expect(screen.getByText('Sign Out')).toBeInTheDocument();
      });
    });

    it('should navigate to account page on "My Account" click', async () => {
      render(<AccountDropdown user={mockUser} lang="en" />);
      
      fireEvent.click(screen.getByRole('button'));
      
      await waitFor(() => {
        const accountLink = screen.getByText('My Account');
        fireEvent.click(accountLink);
      });
      
      expect(mockPush).toHaveBeenCalledWith('/en/account');
    });

    it('should navigate to settings page on "Settings" click', async () => {
      render(<AccountDropdown user={mockUser} lang="en" />);
      
      fireEvent.click(screen.getByRole('button'));
      
      await waitFor(() => {
        const settingsLink = screen.getByText('Settings');
        fireEvent.click(settingsLink);
      });
      
      expect(mockPush).toHaveBeenCalledWith('/en/account/settings');
    });

    it('should navigate to billing page on "Billing" click', async () => {
      render(<AccountDropdown user={mockUser} lang="en" />);
      
      fireEvent.click(screen.getByRole('button'));
      
      await waitFor(() => {
        const billingLink = screen.getByText('Billing');
        fireEvent.click(billingLink);
      });
      
      expect(mockPush).toHaveBeenCalledWith('/en/account/billing');
    });
  });

  describe('Logout Action', () => {
    it('should call signOut on logout click', async () => {
      render(<AccountDropdown user={mockUser} lang="en" />);
      
      fireEvent.click(screen.getByRole('button'));
      
      await waitFor(() => {
        const signOutButton = screen.getByText('Sign Out');
        fireEvent.click(signOutButton);
      });
      
      expect(signOut).toHaveBeenCalledWith({ callbackUrl: '/en' });
    });

    it('should show loading state during logout', async () => {
      (signOut as jest.Mock).mockImplementation(() => new Promise(resolve => setTimeout(resolve, 100)));
      
      render(<AccountDropdown user={mockUser} lang="en" />);
      
      fireEvent.click(screen.getByRole('button'));
      
      await waitFor(() => {
        const signOutButton = screen.getByText('Sign Out');
        fireEvent.click(signOutButton);
      });
      
      expect(screen.getByText('Signing out...')).toBeInTheDocument();
    });
  });

  describe('Bilingual Support', () => {
    it('should render in Arabic with correct text', async () => {
      render(<AccountDropdown user={mockUser} lang="ar" />);
      
      fireEvent.click(screen.getByRole('button'));
      
      await waitFor(() => {
        expect(screen.getByText('حسابي')).toBeInTheDocument(); // My Account
        expect(screen.getByText('الإعدادات')).toBeInTheDocument(); // Settings
        expect(screen.getByText('الفواتير')).toBeInTheDocument(); // Billing
        expect(screen.getByText('تسجيل الخروج')).toBeInTheDocument(); // Sign Out
      });
    });

    it('should use RTL layout in Arabic', () => {
      const { container } = render(<AccountDropdown user={mockUser} lang="ar" />);
      
      expect(container.querySelector('[dir="rtl"]')).toBeInTheDocument();
    });

    it('should use LTR layout in English', () => {
      const { container } = render(<AccountDropdown user={mockUser} lang="en" />);
      
      expect(container.querySelector('[dir="ltr"]')).toBeInTheDocument();
    });
  });

  describe('Accessibility', () => {
    it('should have proper ARIA labels', () => {
      render(<AccountDropdown user={mockUser} lang="en" />);
      
      const trigger = screen.getByRole('button');
      expect(trigger).toHaveAttribute('aria-label', expect.stringContaining('account'));
      expect(trigger).toHaveAttribute('aria-expanded', 'false');
    });

    it('should update aria-expanded when opened', async () => {
      render(<AccountDropdown user={mockUser} lang="en" />);
      
      const trigger = screen.getByRole('button');
      fireEvent.click(trigger);
      
      await waitFor(() => {
        expect(trigger).toHaveAttribute('aria-expanded', 'true');
      });
    });

    it('should be keyboard navigable', async () => {
      render(<AccountDropdown user={mockUser} lang="en" />);
      
      const trigger = screen.getByRole('button');
      fireEvent.keyDown(trigger, { key: 'Enter' });
      
      await waitFor(() => {
        expect(screen.getByText('My Account')).toBeInTheDocument();
      });
      
      fireEvent.keyDown(trigger, { key: 'Escape' });
      
      await waitFor(() => {
        expect(screen.queryByText('My Account')).not.toBeInTheDocument();
      });
    });
  });

  describe('Performance', () => {
    it('should render within acceptable time', () => {
      const startTime = performance.now();
      render(<AccountDropdown user={mockUser} lang="en" />);
      const renderTime = performance.now() - startTime;
      
      expect(renderTime).toBeLessThan(50); // 50ms threshold
    });
  });
});
`;

  await writeTestFile(`${baseDir}/__tests__/components/AccountDropdown.test.tsx`, accountDropdownTest);

  // ========================================
  // 2. UNIT TESTS - API Routes
  // ========================================

  const profileAPITest = `import { NextRequest } from 'next/server';
import { GET, PUT } from '@/app/api/user/profile/route';
import { getServerSession } from 'next-auth';
import prisma from '@/lib/db';

// Mock dependencies
jest.mock('next-auth');
jest.mock('@/lib/db');
jest.mock('@/lib/supabase');
jest.mock('@/lib/rate-limiter');
jest.mock('@/lib/csrf');

describe('API: /api/user/profile', () => {
  const mockSession = {
    user: {
      id: 'user-123',
      email: 'test@example.com',
      name: 'Test User',
    },
  };

  const mockUser = {
    id: 'user-123',
    email: 'test@example.com',
    name: 'Test User',
    companyName: 'Test Company',
    phone: '+97412345678',
    language: 'en',
    emailNotifications: true,
    smsNotifications: false,
    createdAt: new Date(),
    updatedAt: new Date(),
  };

  beforeEach(() => {
    jest.clearAllMocks();
    (getServerSession as jest.Mock).mockResolvedValue(mockSession);
  });

  describe('GET /api/user/profile', () => {
    it('should return user profile when authenticated', async () => {
      (prisma.user.findUnique as jest.Mock).mockResolvedValue(mockUser);

      const request = new NextRequest('http://localhost:9000/api/user/profile');
      const response = await GET(request);
      const data = await response.json();

      expect(response.status).toBe(200);
      expect(data).toMatchObject({
        id: 'user-123',
        email: 'test@example.com',
        name: 'Test User',
        companyName: 'Test Company',
      });
    });

    it('should return 401 when not authenticated', async () => {
      (getServerSession as jest.Mock).mockResolvedValue(null);

      const request = new NextRequest('http://localhost:9000/api/user/profile');
      const response = await GET(request);
      const data = await response.json();

      expect(response.status).toBe(401);
      expect(data.error).toBe('Unauthorized');
    });

    it('should return 404 when user not found', async () => {
      (prisma.user.findUnique as jest.Mock).mockResolvedValue(null);

      const request = new NextRequest('http://localhost:9000/api/user/profile');
      const response = await GET(request);
      const data = await response.json();

      expect(response.status).toBe(404);
      expect(data.error).toBe('User not found');
    });

    it('should not expose sensitive fields', async () => {
      const userWithPassword = { ...mockUser, password: 'hashed_password' };
      (prisma.user.findUnique as jest.Mock).mockResolvedValue(userWithPassword);

      const request = new NextRequest('http://localhost:9000/api/user/profile');
      const response = await GET(request);
      const data = await response.json();

      expect(data.password).toBeUndefined();
    });
  });

  describe('PUT /api/user/profile', () => {
    const validUpdate = {
      name: 'Updated Name',
      companyName: 'Updated Company',
      phone: '+97412345679',
    };

    beforeEach(() => {
      (prisma.user.update as jest.Mock).mockResolvedValue({
        ...mockUser,
        ...validUpdate,
      });
      
      const mockSupabase = {
        from: jest.fn().mockReturnThis(),
        upsert: jest.fn().mockResolvedValue({ error: null }),
      };
      (createSupabaseClient as jest.Mock).mockReturnValue(mockSupabase);
    });

    it('should update profile successfully', async () => {
      const request = new NextRequest('http://localhost:9000/api/user/profile', {
        method: 'PUT',
        body: JSON.stringify(validUpdate),
      });

      const response = await PUT(request);
      const data = await response.json();

      expect(response.status).toBe(200);
      expect(data.name).toBe('Updated Name');
      expect(data.companyName).toBe('Updated Company');
    });

    it('should validate email format', async () => {
      const invalidEmail = {
        email: 'not-an-email',
      };

      const request = new NextRequest('http://localhost:9000/api/user/profile', {
        method: 'PUT',
        body: JSON.stringify(invalidEmail),
      });

      const response = await PUT(request);
      const data = await response.json();

      expect(response.status).toBe(400);
      expect(data.error).toContain('Invalid email');
    });

    it('should check email uniqueness', async () => {
      (prisma.user.findUnique as jest.Mock).mockResolvedValue({
        id: 'other-user',
        email: 'existing@example.com',
      });

      const request = new NextRequest('http://localhost:9000/api/user/profile', {
        method: 'PUT',
        body: JSON.stringify({ email: 'existing@example.com' }),
      });

      const response = await PUT(request);
      const data = await response.json();

      expect(response.status).toBe(400);
      expect(data.error).toContain('Email already in use');
    });

    it('should allow user to keep their own email', async () => {
      (prisma.user.findUnique as jest.Mock).mockResolvedValue(null);

      const request = new NextRequest('http://localhost:9000/api/user/profile', {
        method: 'PUT',
        body: JSON.stringify({ email: 'test@example.com' }), // Same email
      });

      const response = await PUT(request);

      expect(response.status).toBe(200);
    });

    it('should require authentication', async () => {
      (getServerSession as jest.Mock).mockResolvedValue(null);

      const request = new NextRequest('http://localhost:9000/api/user/profile', {
        method: 'PUT',
        body: JSON.stringify(validUpdate),
      });

      const response = await PUT(request);
      const data = await response.json();

      expect(response.status).toBe(401);
      expect(data.error).toBe('Unauthorized');
    });

    it('should sync to both databases', async () => {
      const mockSupabase = {
        from: jest.fn().mockReturnThis(),
        upsert: jest.fn().mockResolvedValue({ error: null }),
      };
      (createSupabaseClient as jest.Mock).mockReturnValue(mockSupabase);

      const request = new NextRequest('http://localhost:9000/api/user/profile', {
        method: 'PUT',
        body: JSON.stringify(validUpdate),
      });

      await PUT(request);

      // Verify Prisma update
      expect(prisma.user.update).toHaveBeenCalledWith({
        where: { id: 'user-123' },
        data: expect.objectContaining(validUpdate),
      });

      // Verify Supabase sync
      expect(mockSupabase.from).toHaveBeenCalledWith('users');
      expect(mockSupabase.upsert).toHaveBeenCalled();
    });

    it('should sanitize input data', async () => {
      const maliciousInput = {
        name: '<script>alert("xss")</script>Test',
        companyName: 'Company<img src=x onerror=alert(1)>',
      };

      const request = new NextRequest('http://localhost:9000/api/user/profile', {
        method: 'PUT',
        body: JSON.stringify(maliciousInput),
      });

      await PUT(request);

      expect(prisma.user.update).toHaveBeenCalledWith({
        where: { id: 'user-123' },
        data: expect.objectContaining({
          name: expect.not.stringContaining('<script>'),
          companyName: expect.not.stringContaining('<img'),
        }),
      });
    });

    it('should enforce rate limiting', async () => {
      const { checkRateLimit } = require('@/lib/rate-limiter');
      (checkRateLimit as jest.Mock).mockResolvedValue(false);

      const request = new NextRequest('http://localhost:9000/api/user/profile', {
        method: 'PUT',
        body: JSON.stringify(validUpdate),
      });

      const response = await PUT(request);
      const data = await response.json();

      expect(response.status).toBe(429);
      expect(data.error).toContain('rate limit');
    });

    it('should validate phone number format', async () => {
      const invalidPhone = {
        phone: 'not-a-phone',
      };

      const request = new NextRequest('http://localhost:9000/api/user/profile', {
        method: 'PUT',
        body: JSON.stringify(invalidPhone),
      });

      const response = await PUT(request);
      const data = await response.json();

      expect(response.status).toBe(400);
      expect(data.error).toContain('Invalid phone');
    });
  });

  describe('Error Handling', () => {
    it('should handle database errors gracefully', async () => {
      (prisma.user.findUnique as jest.Mock).mockRejectedValue(new Error('Database error'));

      const request = new NextRequest('http://localhost:9000/api/user/profile');
      const response = await GET(request);
      const data = await response.json();

      expect(response.status).toBe(500);
      expect(data.error).toBe('Internal server error');
    });

    it('should handle Supabase sync failures', async () => {
      const mockSupabase = {
        from: jest.fn().mockReturnThis(),
        upsert: jest.fn().mockResolvedValue({ error: { message: 'Sync failed' } }),
      };
      (createSupabaseClient as jest.Mock).mockReturnValue(mockSupabase);

      const request = new NextRequest('http://localhost:9000/api/user/profile', {
        method: 'PUT',
        body: JSON.stringify({ name: 'Test' }),
      });

      const response = await PUT(request);
      const data = await response.json();

      expect(response.status).toBe(500);
      expect(data.error).toContain('sync');
    });
  });
});
`;

  await writeTestFile(`${baseDir}/__tests__/api/user/profile.test.ts`, profileAPITest);

  console.log('\n✅ Created unit tests for components and API routes');
  console.log('📊 Estimated token savings: 15,000+ tokens');
  console.log('\n📝 Next: Create E2E tests, security tests, and integration tests');
  console.log('🎯 Run tests with: npm run test:unit');
}

createAccountTests().catch(console.error);
