import { describe, it, expect, jest, beforeAll, afterEach } from '@jest/globals';
import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import userEvent from '@testing-library/user-event';

interface MotionComponentProps {
  children?: React.ReactNode;
  className?: string;
  disabled?: boolean;
  [key: string]: unknown;
}

interface InputComponentProps {
  label?: string;
  id?: string;
  placeholder?: string;
  required?: boolean;
  value?: string;
  onChange?: (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
  onBlur?: () => void;
  error?: string;
  rows?: number;
  [key: string]: unknown;
}

interface ToastComponentProps {
  message?: string;
  type?: string;
  onClose?: () => void;
  [key: string]: unknown;
}

global.fetch = jest.fn(() =>
  Promise.resolve({
    ok: true,
    json: () => Promise.resolve({ success: true }),
  } as Response)
);

jest.mock('framer-motion', () => ({
  motion: {
    div: ({ children, className, ...props }: MotionComponentProps) => (
      <div className={className} {...props}>
        {children}
      </div>
    ),
    section: ({ children, className, ...props }: MotionComponentProps) => (
      <section className={className} {...props}>
        {children}
      </section>
    ),
  },
  AnimatePresence: ({ children }: MotionComponentProps) => <>{children}</>,
}));

jest.mock('lucide-react', () => ({
  Mail: () => <span data-testid="mail-icon" />,
  Phone: () => <span data-testid="phone-icon" />,
  MapPin: () => <span data-testid="map-pin-icon" />,
  Send: () => <span data-testid="send-icon" />,
  Loader2: () => <span data-testid="loader-icon" />,
  Clock: () => <span data-testid="clock-icon" />,
  HeadphonesIcon: () => <span data-testid="headphones-icon" />,
  CheckCircle2: () => <span data-testid="check-circle-icon" />,
  RefreshCw: () => <span data-testid="refresh-cw-icon" />,
}));

jest.mock('@/lib/sanitize', () => ({
  sanitizeInput: (value: string) => value,
}));

jest.mock('@/lib/csrf', () => ({
  generateCSRFToken: jest.fn(() => 'test-csrf-token'),
  setCSRFTokenToStorage: jest.fn(),
  getCSRFTokenFromStorage: jest.fn(() => 'test-csrf-token'),
}));

const { generateCSRFToken, setCSRFTokenToStorage } = jest.requireMock('@/lib/csrf') as {
  generateCSRFToken: jest.Mock;
  setCSRFTokenToStorage: jest.Mock;
};

jest.mock('@/lib/security/captcha', () => ({
  generateCaptcha: jest.fn(() => ({
    question: '1 + 1 = ?',
    answer: 2,
    hash: 'test-hash',
    timestamp: Date.now(),
  })),
}));

const { generateCaptcha } = jest.requireMock('@/lib/security/captcha') as {
  generateCaptcha: jest.Mock;
};

jest.mock('@/lib/constants', () => ({
  COMPANY_INFO: {
    name: '四川睿新致远科技有限公司',
    email: 'contact@novalon.cn',
    phone: '028-88888888',
    address: '中国四川省成都市龙泉驿区幸福路12号',
  },
}));

jest.mock('@/components/ui/button', () => ({
  Button: ({ children, className, disabled, ...props }: MotionComponentProps) => (
    <button className={className} disabled={disabled} {...props}>
      {children}
    </button>
  ),
}));

jest.mock('@/components/ui/input', () => ({
  Input: ({ label, id, placeholder, required, value, onChange, onBlur, error, ...props }: InputComponentProps) => (
    <div>
      <label htmlFor={id}>{label}{required && '*'}</label>
      <input
        id={id}
        placeholder={placeholder}
        value={value}
        onChange={onChange}
        onBlur={onBlur}
        data-testid={`${id}-input`}
        {...props}
      />
      {error && <span data-testid={`${id}-error`}>{error}</span>}
    </div>
  ),
}));

jest.mock('@/components/ui/textarea', () => ({
  Textarea: ({ label, id, placeholder, rows, required, value, onChange, onBlur, error, ...props }: InputComponentProps) => (
    <div>
      <label htmlFor={id}>{label}{required && '*'}</label>
      <textarea
        id={id}
        placeholder={placeholder}
        rows={rows}
        value={value}
        onChange={onChange}
        onBlur={onBlur}
        data-testid={`${id}-input`}
        {...props}
      />
      {error && <span data-testid={`${id}-error`}>{error}</span>}
    </div>
  ),
}));

jest.mock('@/components/ui/toast', () => ({
  Toast: ({ message, type, onClose, ...props }: ToastComponentProps) => (
    <div data-testid="toast-notification" data-type={type} {...props}>
      {message}
      <button onClick={onClose}>关闭</button>
    </div>
  ),
}));

import { ContactSection } from './contact-section';

describe('ContactSection', () => {
  beforeAll(() => {
    jest.clearAllMocks();
  });

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

  describe('Rendering', () => {
    it('should render contact section', () => {
      render(<ContactSection />);
      const section = document.querySelector('section#contact');
      expect(section).toBeInTheDocument();
    });

    it('should render contact form', () => {
      render(<ContactSection />);
      expect(screen.getByTestId('name-input')).toBeInTheDocument();
      expect(screen.getByTestId('phone-input')).toBeInTheDocument();
      expect(screen.getByTestId('email-input')).toBeInTheDocument();
      expect(screen.getByTestId('message-input')).toBeInTheDocument();
      expect(screen.getByTestId('captcha-question')).toBeInTheDocument();
      expect(screen.getByTestId('captcha-input')).toBeInTheDocument();
    });

    it('should render submit button', () => {
      render(<ContactSection />);
      expect(screen.getByRole('button', { name: /发送消息/ })).toBeInTheDocument();
    });

    it('should render company contact information', () => {
      render(<ContactSection />);
      expect(screen.getByText('contact@novalon.cn')).toBeInTheDocument();
      expect(screen.getByText('中国四川省成都市龙泉驿区幸福路12号')).toBeInTheDocument();
    });

    it('should render work hours card', () => {
      render(<ContactSection />);
      expect(screen.getByTestId('work-hours-card')).toBeInTheDocument();
    });
  });

  describe('Form Validation', () => {
    it('should show error for invalid name', async () => {
      render(<ContactSection />);
      const nameInput = screen.getByTestId('name-input');
      
      await userEvent.type(nameInput, '张');
      fireEvent.blur(nameInput);
      
      await waitFor(() => {
        expect(screen.getByTestId('name-error')).toBeInTheDocument();
      });
    });

    it('should show error for invalid phone', async () => {
      render(<ContactSection />);
      const phoneInput = screen.getByTestId('phone-input');
      
      await userEvent.type(phoneInput, '1234567890');
      fireEvent.blur(phoneInput);
      
      await waitFor(() => {
        expect(screen.getByTestId('phone-error')).toBeInTheDocument();
      });
    });

    it('should show error for invalid email', async () => {
      render(<ContactSection />);
      const emailInput = screen.getByTestId('email-input');
      
      await userEvent.type(emailInput, 'invalid-email');
      fireEvent.blur(emailInput);
      
      await waitFor(() => {
        expect(screen.getByTestId('email-error')).toBeInTheDocument();
      });
    });

    it('should show error for short message', async () => {
      render(<ContactSection />);
      const messageInput = screen.getByTestId('message-input');
      
      await userEvent.type(messageInput, '短留言');
      fireEvent.blur(messageInput);
      
      await waitFor(() => {
        expect(screen.getByTestId('message-error')).toBeInTheDocument();
      });
    });
  });

  describe('Accessibility', () => {
    it('should have proper form labels', () => {
      render(<ContactSection />);
      
      expect(screen.getByLabelText(/姓名/)).toBeInTheDocument();
      expect(screen.getByLabelText(/电话/)).toBeInTheDocument();
      expect(screen.getByLabelText(/邮箱/)).toBeInTheDocument();
      expect(screen.getByLabelText(/留言/)).toBeInTheDocument();
      expect(screen.getByLabelText(/验证码/)).toBeInTheDocument();
    });

    it('should have proper ARIA attributes', () => {
      render(<ContactSection />);
      const section = document.querySelector('section#contact');
      expect(section).toHaveAttribute('role', 'region');
      expect(section).toHaveAttribute('aria-labelledby', 'contact-heading');
    });
  });

  describe('CSRF Protection', () => {
    it('should generate CSRF token on mount', () => {
      render(<ContactSection />);
      
      expect(generateCSRFToken).toHaveBeenCalled();
      expect(setCSRFTokenToStorage).toHaveBeenCalledWith('test-csrf-token');
    });
  });

  describe('Captcha Functionality', () => {
    it('should render captcha question', () => {
      render(<ContactSection />);
      expect(screen.getByTestId('captcha-question')).toBeInTheDocument();
      expect(screen.getByText('1 + 1 = ?')).toBeInTheDocument();
    });

    it('should render captcha input', () => {
      render(<ContactSection />);
      expect(screen.getByTestId('captcha-input')).toBeInTheDocument();
    });

    it('should render refresh captcha button', () => {
      render(<ContactSection />);
      expect(screen.getByTestId('refresh-captcha')).toBeInTheDocument();
    });

    it('should refresh captcha when refresh button is clicked', async () => {
      render(<ContactSection />);
      
      const refreshButton = screen.getByTestId('refresh-captcha');
      await userEvent.click(refreshButton);
      
      expect(generateCaptcha).toHaveBeenCalled();
    });

    it.skip('should show error for invalid captcha', async () => {
      render(<ContactSection />);
      const nameInput = screen.getByTestId('name-input');
      const phoneInput = screen.getByTestId('phone-input');
      const emailInput = screen.getByTestId('email-input');
      const messageInput = screen.getByTestId('message-input');
      const captchaInput = screen.getByTestId('captcha-input');
      const submitButton = screen.getByRole('button', { name: /发送消息/ });
      
      await userEvent.type(nameInput, '张三');
      await userEvent.type(phoneInput, '13800138000');
      await userEvent.type(emailInput, 'test@example.com');
      await userEvent.type(messageInput, '这是一条测试留言内容');
      
      captchaInput.focus();
      fireEvent.change(captchaInput, { target: { value: '3' } });
      
      await userEvent.click(submitButton);
      
      await waitFor(() => {
        expect(screen.getByTestId('captcha-error')).toBeInTheDocument();
      }, { timeout: 3000 });
    });
  });
});
