import { describe, it, expect, beforeEach, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import OrderModal from './OrderModal';
import { useDesignStore } from '../store/designStore';
import type { Stone, ModelTemplate } from '../types';

const testStone: Stone = { id: 1, name: 'Akik', image: '/akik.jpg', active: true };
const testStone2: Stone = { id: 2, name: 'Amazonit', image: '/amazonit.jpg', active: true };
const testTemplate: ModelTemplate = {
  id: 1,
  name: 'Yuvarlak Bileklik',
  jewelryType: 'bileklik',
  image: '/template.jpg',
};

function setupFilledStore() {
  useDesignStore.setState({
    jewelryType: 'bileklik',
    size: { label: 'M', circumferenceCm: 18 },
    stoneSizeMm: 8,
    selectedTemplate: testTemplate,
  });
  // Fill all slots
  const state = useDesignStore.getState();
  const filledSlots = state.slots.map((s, i) => ({
    ...s,
    stone: i % 2 === 0 ? testStone : testStone2,
  }));
  useDesignStore.setState({ slots: filledSlots });
}

describe('OrderModal', () => {
  beforeEach(() => {
    localStorage.clear();
    vi.restoreAllMocks();
    setupFilledStore();
  });

  it('renders order summary with design details', () => {
    render(<OrderModal onClose={() => {}} />);

    expect(screen.getByText('Sipariş Özeti')).toBeInTheDocument();
    expect(screen.getByText('Bileklik')).toBeInTheDocument();
    expect(screen.getByText('Yuvarlak Bileklik')).toBeInTheDocument();
    expect(screen.getByText('M')).toBeInTheDocument();
    expect(screen.getByText('8mm')).toBeInTheDocument();
  });

  it('renders placed stones list', () => {
    render(<OrderModal onClose={() => {}} />);

    expect(screen.getAllByText('Akik').length).toBeGreaterThan(0);
    expect(screen.getAllByText('Amazonit').length).toBeGreaterThan(0);
  });

  it('renders customer info form fields', () => {
    render(<OrderModal onClose={() => {}} />);

    expect(screen.getByLabelText(/Ad Soyad/)).toBeInTheDocument();
    expect(screen.getByLabelText(/Telefon/)).toBeInTheDocument();
    expect(screen.getByLabelText(/Not/)).toBeInTheDocument();
  });

  it('renders Onayla and İptal buttons', () => {
    render(<OrderModal onClose={() => {}} />);

    expect(screen.getByText('Onayla')).toBeInTheDocument();
    expect(screen.getByText('İptal')).toBeInTheDocument();
  });

  it('calls onClose when İptal is clicked', async () => {
    const user = userEvent.setup();
    const onClose = vi.fn();
    render(<OrderModal onClose={onClose} />);

    await user.click(screen.getByText('İptal'));
    expect(onClose).toHaveBeenCalledOnce();
  });

  it('shows validation error when name or phone is empty', async () => {
    const user = userEvent.setup();
    vi.spyOn(globalThis, 'fetch').mockRejectedValue(new Error('offline'));

    render(<OrderModal onClose={() => {}} />);

    await user.click(screen.getByText('Onayla'));
    expect(screen.getByTestId('order-error')).toHaveTextContent(
      'Ad ve telefon alanları zorunludur.',
    );
  });

  it('submits order and shows success message', async () => {
    const user = userEvent.setup();
    vi.spyOn(globalThis, 'fetch').mockRejectedValue(new Error('offline'));

    render(<OrderModal onClose={() => {}} />);

    await user.type(screen.getByLabelText(/Ad Soyad/), 'Test User');
    await user.type(screen.getByLabelText(/Telefon/), '05551234567');
    await user.click(screen.getByText('Onayla'));

    expect(
      await screen.findByText('Sipariş Başarıyla Oluşturuldu!'),
    ).toBeInTheDocument();
  });

  it('saves order to localStorage on submit (API fallback)', async () => {
    const user = userEvent.setup();
    vi.spyOn(globalThis, 'fetch').mockRejectedValue(new Error('offline'));

    render(<OrderModal onClose={() => {}} />);

    await user.type(screen.getByLabelText(/Ad Soyad/), 'Test User');
    await user.type(screen.getByLabelText(/Telefon/), '05551234567');
    await user.type(screen.getByLabelText(/Not/), 'Hediye paketi');
    await user.click(screen.getByText('Onayla'));

    await screen.findByText('Sipariş Başarıyla Oluşturuldu!');

    const stored = JSON.parse(
      localStorage.getItem('safnaturel_orders')!,
    );
    expect(stored).toHaveLength(1);
    expect(stored[0].customerName).toBe('Test User');
    expect(stored[0].customerPhone).toBe('05551234567');
    expect(stored[0].customerNote).toBe('Hediye paketi');
    expect(stored[0].jewelryType).toBe('bileklik');
  });

  it('preserves design data on error (design store unchanged)', async () => {
    const user = userEvent.setup();
    vi.spyOn(globalThis, 'fetch').mockRejectedValue(new Error('offline'));

    render(<OrderModal onClose={() => {}} />);

    // Submit without filling required fields to trigger validation error
    await user.click(screen.getByText('Onayla'));

    // Design store should be unchanged
    const state = useDesignStore.getState();
    expect(state.slots.every((s) => s.stone !== null)).toBe(true);
    expect(state.selectedTemplate?.name).toBe('Yuvarlak Bileklik');
  });

  it('shows Tamam button after success and calls onClose', async () => {
    const user = userEvent.setup();
    const onClose = vi.fn();
    vi.spyOn(globalThis, 'fetch').mockRejectedValue(new Error('offline'));

    render(<OrderModal onClose={onClose} />);

    await user.type(screen.getByLabelText(/Ad Soyad/), 'Test');
    await user.type(screen.getByLabelText(/Telefon/), '0555');
    await user.click(screen.getByText('Onayla'));

    await screen.findByText('Sipariş Başarıyla Oluşturuldu!');
    await user.click(screen.getByText('Tamam'));
    expect(onClose).toHaveBeenCalledOnce();
  });
});
