import { render, screen, fireEvent } from '@testing-library/react';
import { describe, it, expect, vi } from 'vitest';
import { useForm } from 'react-hook-form';
import { Form, FormField, FormItem, FormLabel, FormControl, FormMessage } from './form';
import { Input } from '../input';
import React from 'react';

const FormTester = ({ onSubmit }: { onSubmit: (data: any) => void }) => {
  const form = useForm({
    defaultValues: {
      username: '',
    },
  });

  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)}>
        <FormField
          control={form.control}
          name="username"
          rules={{ required: 'Username is required' }}
          render={({ field }) => (
            <FormItem>
              <FormLabel>Username</FormLabel>
              <FormControl>
                <Input placeholder="shadcn" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        <button type="submit">Submit</button>
      </form>
    </Form>
  );
};

describe('Form', () => {
  it('renders correctly', () => {
    render(<FormTester onSubmit={() => {}} />);
    expect(screen.getByText('Username')).toBeInTheDocument();
    expect(screen.getByPlaceholderText('shadcn')).toBeInTheDocument();
  });

  it('shows error message on invalid submit', async () => {
    render(<FormTester onSubmit={() => {}} />);

    fireEvent.click(screen.getByText('Submit'));

    const errorMessage = await screen.findByText('Username is required');
    expect(errorMessage).toBeInTheDocument();
  });

  it('calls onSubmit with correct data when valid', async () => {
    const onSubmit = vi.fn();
    render(<FormTester onSubmit={onSubmit} />);

    const input = screen.getByPlaceholderText('shadcn');
    fireEvent.change(input, { target: { value: 'johndoe' } });

    fireEvent.click(screen.getByText('Submit'));

    // Need to wait for async form submission
    await vi.waitFor(() =>
      expect(onSubmit).toHaveBeenCalledWith({ username: 'johndoe' }, expect.anything())
    );
  });

  it('has correct data-slot attributes', () => {
    const { container } = render(<FormTester onSubmit={() => {}} />);
    expect(container.querySelector('[data-slot="form-item"]')).toBeInTheDocument();
    expect(container.querySelector('[data-slot="form-label"]')).toBeInTheDocument();
    expect(container.querySelector('[data-slot="form-control"]')).toBeInTheDocument();
  });
});
