import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen } from '@testing-library/react';
import React from 'react';
import { CustomerPreview } from '../CustomerPreview';
import { Service, Business } from '../../../types';

// Mock dependencies
vi.mock('react-i18next', () => ({
  useTranslation: () => ({ t: (key: string) => key }),
}));

// Mock Lucide icons
vi.mock('lucide-react', () => ({
  Clock: () => <span data-testid="icon-clock" />,
  DollarSign: () => <span data-testid="icon-dollar-sign" />,
  Image: () => <span data-testid="icon-image" />,
  CheckCircle2: () => <span data-testid="icon-check-circle" />,
  AlertCircle: () => <span data-testid="icon-alert-circle" />,
}));

// Mock Badge component
vi.mock('../../ui/Badge', () => ({
  default: ({ children, variant, size }: any) =>
    <span data-testid={`badge-${variant}`} data-size={size}>{children}</span>,
}));

describe('CustomerPreview', () => {
  const mockBusiness: Business = {
    id: 'business-1',
    name: 'Test Business',
    primaryColor: '#2563eb',
    secondaryColor: '#0ea5e9',
  } as Business;

  const mockService: Service = {
    id: '1',
    name: 'Haircut',
    description: 'Professional haircut service',
    price: 50,
    durationMinutes: 60,
    photos: [],
    category: { id: 'cat1', name: 'Hair Services' },
    variable_pricing: false,
  } as Service;

  const mockServiceWithPhoto: Service = {
    ...mockService,
    photos: ['https://example.com/photo.jpg'],
  };

  const mockServiceWithDeposit: Service = {
    ...mockService,
    deposit_amount: 10,
  };

  const mockServiceVariablePricing: Service = {
    ...mockService,
    variable_pricing: true,
    deposit_amount: 25,
  };

  const defaultProps = {
    service: mockService,
    business: mockBusiness,
  };

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

  it('renders customer preview heading', () => {
    render(React.createElement(CustomerPreview, defaultProps));
    expect(screen.getByText('Customer Preview')).toBeInTheDocument();
  });

  it('shows live preview badge', () => {
    render(React.createElement(CustomerPreview, defaultProps));
    expect(screen.getByTestId('badge-info')).toBeInTheDocument();
    expect(screen.getByText('Live Preview')).toBeInTheDocument();
  });

  it('displays service name', () => {
    render(React.createElement(CustomerPreview, defaultProps));
    expect(screen.getByText('Haircut')).toBeInTheDocument();
  });

  it('displays service description', () => {
    render(React.createElement(CustomerPreview, defaultProps));
    expect(screen.getByText('Professional haircut service')).toBeInTheDocument();
  });

  it('displays service category', () => {
    render(React.createElement(CustomerPreview, defaultProps));
    expect(screen.getByText('Hair Services')).toBeInTheDocument();
  });

  it('displays duration', () => {
    render(React.createElement(CustomerPreview, defaultProps));
    expect(screen.getByText('60 mins')).toBeInTheDocument();
  });

  it('shows clock icon for duration', () => {
    render(React.createElement(CustomerPreview, defaultProps));
    expect(screen.getByTestId('icon-clock')).toBeInTheDocument();
  });

  it('displays price', () => {
    render(React.createElement(CustomerPreview, defaultProps));
    expect(screen.getByText('50')).toBeInTheDocument();
  });

  it('shows dollar sign icon for price', () => {
    render(React.createElement(CustomerPreview, defaultProps));
    expect(screen.getByTestId('icon-dollar-sign')).toBeInTheDocument();
  });

  it('shows image icon when no photos', () => {
    render(React.createElement(CustomerPreview, defaultProps));
    expect(screen.getByTestId('icon-image')).toBeInTheDocument();
  });

  it('displays photo when available', () => {
    const props = { ...defaultProps, service: mockServiceWithPhoto };
    render(React.createElement(CustomerPreview, props));

    const img = document.querySelector('img');
    expect(img).toBeInTheDocument();
    expect(img).toHaveAttribute('src', 'https://example.com/photo.jpg');
    expect(img).toHaveAttribute('alt', 'Haircut');
  });

  it('displays deposit requirement when set', () => {
    const props = { ...defaultProps, service: mockServiceWithDeposit };
    render(React.createElement(CustomerPreview, props));

    expect(screen.getByText(/Deposit required:/)).toBeInTheDocument();
    expect(screen.getByText((content, element) => {
      return element?.textContent === 'Deposit required: $10';
    })).toBeInTheDocument();
  });

  it('does not show deposit when not required', () => {
    render(React.createElement(CustomerPreview, defaultProps));
    expect(screen.queryByText(/Deposit required:/)).not.toBeInTheDocument();
  });

  it('shows variable pricing badge', () => {
    const props = { ...defaultProps, service: mockServiceVariablePricing };
    render(React.createElement(CustomerPreview, props));

    expect(screen.getByText('Variable')).toBeInTheDocument();
  });

  it('shows "Price varies" text for variable pricing', () => {
    const props = { ...defaultProps, service: mockServiceVariablePricing };
    render(React.createElement(CustomerPreview, props));

    expect(screen.getByText('Price varies')).toBeInTheDocument();
  });

  it('shows deposit for variable pricing services', () => {
    const props = { ...defaultProps, service: mockServiceVariablePricing };
    render(React.createElement(CustomerPreview, props));

    expect(screen.getByText(/Deposit required:/)).toBeInTheDocument();
  });

  it('displays info alert about preview', () => {
    render(React.createElement(CustomerPreview, defaultProps));
    expect(screen.getByTestId('icon-alert-circle')).toBeInTheDocument();
    expect(screen.getByText(/This is how your service will appear to customers/)).toBeInTheDocument();
  });

  it('handles null service gracefully', () => {
    const props = { ...defaultProps, service: null };
    render(React.createElement(CustomerPreview, props));

    expect(screen.getByText('New Service')).toBeInTheDocument();
    expect(screen.getByText('Service description will appear here...')).toBeInTheDocument();
  });

  it('displays default category when not set', () => {
    const serviceWithoutCategory = { ...mockService, category: undefined };
    const props = { ...defaultProps, service: serviceWithoutCategory };
    render(React.createElement(CustomerPreview, props));

    expect(screen.getByText('General')).toBeInTheDocument();
  });

  it('uses preview data when provided', () => {
    const previewData = {
      name: 'Custom Name',
      description: 'Custom Description',
      price: 75,
      durationMinutes: 90,
    };
    const props = { ...defaultProps, previewData };
    render(React.createElement(CustomerPreview, props));

    expect(screen.getByText('Custom Name')).toBeInTheDocument();
    expect(screen.getByText('Custom Description')).toBeInTheDocument();
    expect(screen.getByText('75')).toBeInTheDocument();
    expect(screen.getByText('90 mins')).toBeInTheDocument();
  });

  it('preview data overrides service data', () => {
    const previewData = { name: 'Preview Name' };
    const props = { ...defaultProps, previewData };
    render(React.createElement(CustomerPreview, props));

    // Should show preview data instead of service data
    expect(screen.getByText('Preview Name')).toBeInTheDocument();
    expect(screen.queryByText('Haircut')).not.toBeInTheDocument();
  });

  it('formats price correctly', () => {
    const props = { ...defaultProps, service: { ...mockService, price: 123 } };
    render(React.createElement(CustomerPreview, props));

    expect(screen.getByText('123')).toBeInTheDocument();
  });

  it('handles zero price', () => {
    const props = { ...defaultProps, service: { ...mockService, price: 0 } };
    render(React.createElement(CustomerPreview, props));

    expect(screen.getByText('0')).toBeInTheDocument();
  });

  it('applies business colors to gradient', () => {
    render(React.createElement(CustomerPreview, defaultProps));

    // The gradient uses business colors in the style attribute
    const gradientDiv = document.querySelector('[style*="gradient"]');
    expect(gradientDiv).toBeInTheDocument();
  });

  it('displays deposit with correct formatting', () => {
    const props = { ...defaultProps, service: { ...mockService, deposit_amount: 15 } };
    render(React.createElement(CustomerPreview, props));

    expect(screen.getByText((content, element) => {
      return element?.textContent === 'Deposit required: $15';
    })).toBeInTheDocument();
  });

  it('shows default duration when not set', () => {
    const serviceWithoutDuration = { ...mockService, durationMinutes: undefined };
    const props = { ...defaultProps, service: serviceWithoutDuration };
    render(React.createElement(CustomerPreview, props));

    expect(screen.getByText('30 mins')).toBeInTheDocument();
  });

  it('displays border styling to indicate selected preview', () => {
    render(React.createElement(CustomerPreview, defaultProps));

    const card = document.querySelector('.border-brand-600');
    expect(card).toBeInTheDocument();
  });

  it('displays ring styling', () => {
    render(React.createElement(CustomerPreview, defaultProps));

    const card = document.querySelector('.ring-brand-600');
    expect(card).toBeInTheDocument();
  });

  it('handles preview data with partial updates', () => {
    const previewData = { price: 99 };
    const props = { ...defaultProps, previewData };
    render(React.createElement(CustomerPreview, props));

    // Name should still be from service
    expect(screen.getByText('Haircut')).toBeInTheDocument();
    // Price should be from previewData
    expect(screen.getByText('99')).toBeInTheDocument();
  });

  it('merges photos from preview data', () => {
    const previewData = { photos: ['https://preview.com/new.jpg'] };
    const props = { ...defaultProps, previewData };
    render(React.createElement(CustomerPreview, props));

    const img = document.querySelector('img');
    expect(img).toHaveAttribute('src', 'https://preview.com/new.jpg');
  });

  it('handles empty photos array', () => {
    const props = { ...defaultProps, service: { ...mockService, photos: [] } };
    render(React.createElement(CustomerPreview, props));

    expect(screen.getByTestId('icon-image')).toBeInTheDocument();
  });

  it('uses first photo only for cover', () => {
    const serviceWithMultiplePhotos = {
      ...mockService,
      photos: ['https://first.com/1.jpg', 'https://second.com/2.jpg'],
    };
    const props = { ...defaultProps, service: serviceWithMultiplePhotos };
    render(React.createElement(CustomerPreview, props));

    const img = document.querySelector('img');
    expect(img).toHaveAttribute('src', 'https://first.com/1.jpg');
  });

  it('displays horizontal card layout', () => {
    render(React.createElement(CustomerPreview, defaultProps));

    const cardContainer = document.querySelector('.flex.h-full');
    expect(cardContainer).toBeInTheDocument();
  });
});
