import { render, screen } from '@testing-library/react';
import type { UseFormRegister, FieldErrors } from 'react-hook-form';
import { describe, expect, it, vi } from 'vitest';
import type { CreateListingFormData } from '@/lib/validations/listings';
import { StepBasicInfo, StepLocation, StepDetails, StepPricing } from '../listing-form-steps';

// Minimal register mock that returns required react-hook-form props
function mockRegister(): UseFormRegister<CreateListingFormData> {
  return vi.fn().mockImplementation((name: string) => ({
    name,
    onChange: vi.fn(),
    onBlur: vi.fn(),
    ref: vi.fn(),
  })) as unknown as UseFormRegister<CreateListingFormData>;
}

const noErrors: FieldErrors<CreateListingFormData> = {};

// ─── StepBasicInfo ──────────────────────────────────────

describe('StepBasicInfo', () => {
  it('renders the step heading', () => {
    render(<StepBasicInfo register={mockRegister()} errors={noErrors} />);
    expect(screen.getByText('Thông tin cơ bản')).toBeInTheDocument();
  });

  it('renders transaction type select', () => {
    render(<StepBasicInfo register={mockRegister()} errors={noErrors} />);
    expect(screen.getByLabelText('Loại giao dịch *')).toBeInTheDocument();
  });

  it('renders property type select', () => {
    render(<StepBasicInfo register={mockRegister()} errors={noErrors} />);
    expect(screen.getByLabelText('Loại bất động sản *')).toBeInTheDocument();
  });

  it('renders title input', () => {
    render(<StepBasicInfo register={mockRegister()} errors={noErrors} />);
    expect(screen.getByLabelText('Tiêu đề tin đăng *')).toBeInTheDocument();
  });

  it('renders description textarea', () => {
    render(<StepBasicInfo register={mockRegister()} errors={noErrors} />);
    expect(screen.getByLabelText('Mô tả chi tiết *')).toBeInTheDocument();
  });

  it('renders transaction type options', () => {
    render(<StepBasicInfo register={mockRegister()} errors={noErrors} />);
    expect(screen.getByText('Bán')).toBeInTheDocument();
    expect(screen.getByText('Cho thuê')).toBeInTheDocument();
  });

  it('renders property type options', () => {
    render(<StepBasicInfo register={mockRegister()} errors={noErrors} />);
    expect(screen.getByText('Căn hộ')).toBeInTheDocument();
    expect(screen.getByText('Nhà riêng')).toBeInTheDocument();
    expect(screen.getByText('Biệt thự')).toBeInTheDocument();
  });

  it('shows error message for transactionType', () => {
    const errors: FieldErrors<CreateListingFormData> = {
      transactionType: { type: 'required', message: 'Vui lòng chọn loại giao dịch' },
    };
    render(<StepBasicInfo register={mockRegister()} errors={errors} />);
    expect(screen.getByText('Vui lòng chọn loại giao dịch')).toBeInTheDocument();
  });

  it('shows error message for title', () => {
    const errors: FieldErrors<CreateListingFormData> = {
      title: { type: 'min', message: 'Tiêu đề tối thiểu 5 ký tự' },
    };
    render(<StepBasicInfo register={mockRegister()} errors={errors} />);
    expect(screen.getByText('Tiêu đề tối thiểu 5 ký tự')).toBeInTheDocument();
  });
});

// ─── StepLocation ───────────────────────────────────────

describe('StepLocation', () => {
  it('renders the step heading', () => {
    render(<StepLocation register={mockRegister()} errors={noErrors} />);
    expect(screen.getByText('Vị trí')).toBeInTheDocument();
  });

  it('renders address input', () => {
    render(<StepLocation register={mockRegister()} errors={noErrors} />);
    expect(screen.getByLabelText('Địa chỉ *')).toBeInTheDocument();
  });

  it('renders ward input', () => {
    render(<StepLocation register={mockRegister()} errors={noErrors} />);
    expect(screen.getByLabelText('Phường/Xã *')).toBeInTheDocument();
  });

  it('renders district input', () => {
    render(<StepLocation register={mockRegister()} errors={noErrors} />);
    expect(screen.getByLabelText('Quận/Huyện *')).toBeInTheDocument();
  });

  it('renders city input', () => {
    render(<StepLocation register={mockRegister()} errors={noErrors} />);
    expect(screen.getByLabelText('Tỉnh/Thành phố *')).toBeInTheDocument();
  });

  it('renders latitude and longitude inputs', () => {
    render(<StepLocation register={mockRegister()} errors={noErrors} />);
    expect(screen.getByLabelText('Vĩ độ')).toBeInTheDocument();
    expect(screen.getByLabelText('Kinh độ')).toBeInTheDocument();
  });

  it('renders latitude + longitude fields without the picker when setValue is not passed', () => {
    render(<StepLocation register={mockRegister()} errors={noErrors} />);
    // Picker is opt-in: only mounts when setValue/watch are provided.
    expect(screen.getByLabelText('Vĩ độ')).toBeInTheDocument();
    expect(screen.getByLabelText('Kinh độ')).toBeInTheDocument();
  });

  it('shows error for address', () => {
    const errors: FieldErrors<CreateListingFormData> = {
      address: { type: 'required', message: 'Vui lòng nhập địa chỉ' },
    };
    render(<StepLocation register={mockRegister()} errors={errors} />);
    expect(screen.getByText('Vui lòng nhập địa chỉ')).toBeInTheDocument();
  });
});

// ─── StepDetails ────────────────────────────────────────

describe('StepDetails', () => {
  it('renders the step heading', () => {
    render(<StepDetails register={mockRegister()} errors={noErrors} />);
    expect(screen.getByText('Thông số chi tiết')).toBeInTheDocument();
  });

  it('renders area input', () => {
    render(<StepDetails register={mockRegister()} errors={noErrors} />);
    expect(screen.getByLabelText('Diện tích (m²) *')).toBeInTheDocument();
  });

  it('renders bedroom and bathroom inputs', () => {
    render(<StepDetails register={mockRegister()} errors={noErrors} />);
    expect(screen.getByLabelText('Phòng ngủ')).toBeInTheDocument();
    expect(screen.getByLabelText('Phòng tắm')).toBeInTheDocument();
  });

  it('renders direction select', () => {
    render(<StepDetails register={mockRegister()} errors={noErrors} />);
    expect(screen.getByLabelText('Hướng nhà')).toBeInTheDocument();
  });

  it('renders direction options', () => {
    render(<StepDetails register={mockRegister()} errors={noErrors} />);
    // "Direction" options appear in both `direction` and `balconyDirection`
    // selects, so they occur multiple times.
    expect(screen.getAllByText('Bắc').length).toBeGreaterThanOrEqual(1);
    expect(screen.getAllByText('Nam').length).toBeGreaterThanOrEqual(1);
    expect(screen.getAllByText('Đông').length).toBeGreaterThanOrEqual(1);
  });

  it('renders year built input', () => {
    render(<StepDetails register={mockRegister()} errors={noErrors} />);
    expect(screen.getByLabelText('Năm xây dựng')).toBeInTheDocument();
  });

  it('renders legal status and project name inputs', () => {
    render(<StepDetails register={mockRegister()} errors={noErrors} />);
    expect(screen.getByLabelText('Pháp lý')).toBeInTheDocument();
    expect(screen.getByLabelText('Tên dự án')).toBeInTheDocument();
  });

  it('renders amenities input', () => {
    render(<StepDetails register={mockRegister()} errors={noErrors} />);
    expect(screen.getByLabelText(/Tiện ích/)).toBeInTheDocument();
  });
});

// ─── StepPricing ────────────────────────────────────────

describe('StepPricing', () => {
  it('renders the step heading', () => {
    render(<StepPricing register={mockRegister()} errors={noErrors} />);
    expect(screen.getByText('Giá & Hoa hồng')).toBeInTheDocument();
  });

  it('renders price input', () => {
    render(<StepPricing register={mockRegister()} errors={noErrors} />);
    expect(screen.getByLabelText('Giá bán (VNĐ) *')).toBeInTheDocument();
  });

  it('renders rent price and commission inputs', () => {
    render(<StepPricing register={mockRegister()} errors={noErrors} />);
    expect(screen.getByLabelText('Giá thuê/tháng (VNĐ)')).toBeInTheDocument();
    expect(screen.getByLabelText('Hoa hồng (%)')).toBeInTheDocument();
  });

  it('renders price format hint', () => {
    render(<StepPricing register={mockRegister()} errors={noErrors} />);
    expect(screen.getByText(/Nhập số không có dấu chấm/)).toBeInTheDocument();
  });

  it('shows error for priceVND', () => {
    const errors: FieldErrors<CreateListingFormData> = {
      priceVND: { type: 'required', message: 'Giá bán là bắt buộc' },
    };
    render(<StepPricing register={mockRegister()} errors={errors} />);
    expect(screen.getByText('Giá bán là bắt buộc')).toBeInTheDocument();
  });
});
