import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { BrowserRouter } from 'react-router-dom';
import '@testing-library/jest-dom';
import PosPromotionPanel from '@/components/POS/PosPromotionPanel';
import SalesPos from '@/components/POS/SalesPos';
import ReturnPos from '@/components/POS/ReturnPos';
import ExchangePos from '@/components/POS/ExchangePos';

// Mock authService
jest.mock('@/services/authService', () => ({
    authService: {
        post: jest.fn(),
        get: jest.fn(),
    },
}));

// Mock toast
jest.mock('react-hot-toast', () => ({
    toast: {
        success: jest.fn(),
        error: jest.fn(),
    },
}));

const createTestQueryClient = () => new QueryClient({
    defaultOptions: {
        queries: { retry: false },
        mutations: { retry: false },
    },
});

const TestWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => {
    const queryClient = createTestQueryClient();

    return (
        <QueryClientProvider client={queryClient}>
            <BrowserRouter>
                {children}
            </BrowserRouter>
        </QueryClientProvider>
    );
};

describe('PosPromotionPanel', () => {
    const defaultProps = {
        voucherCode: '',
        onVoucherCodeChange: jest.fn(),
        appliedPromotions: [],
        freeItems: [],
        warnings: [],
        errors: [],
        totalDiscount: 0,
        isLoading: false,
        onApplyPromotions: jest.fn(),
        context: 'sale' as const,
    };

    it('renders promotion panel correctly', () => {
        render(
            <TestWrapper>
                <PosPromotionPanel {...defaultProps} />
            </TestWrapper>
        );

        expect(screen.getByText('Promotions & Discounts')).toBeInTheDocument();
        expect(screen.getByLabelText('Promo Code')).toBeInTheDocument();
        expect(screen.getByText('Apply Promotions')).toBeInTheDocument();
    });

    it('shows voucher input for sale context', () => {
        render(
            <TestWrapper>
                <PosPromotionPanel {...defaultProps} context="sale" />
            </TestWrapper>
        );

        expect(screen.getByLabelText('Promo Code')).toBeInTheDocument();
    });

    it('hides voucher input for return context', () => {
        render(
            <TestWrapper>
                <PosPromotionPanel {...defaultProps} context="return" />
            </TestWrapper>
        );

        expect(screen.queryByLabelText('Promo Code')).not.toBeInTheDocument();
    });

    it('displays applied promotions', () => {
        const appliedPromotions = [
            {
                id: 1,
                name: 'Test Promotion',
                type: 'percentage' as const,
                percentage: 10,
                description: '10% off',
                exclusive: false,
            },
        ];

        render(
            <TestWrapper>
                <PosPromotionPanel {...defaultProps} appliedPromotions={appliedPromotions} />
            </TestWrapper>
        );

        expect(screen.getByText('Test Promotion')).toBeInTheDocument();
        expect(screen.getByText('-10%')).toBeInTheDocument();
    });

    it('displays free items', () => {
        const freeItems = [
            {
                product_id: 1,
                name: 'Free Item',
                qty: 1,
                price: 0,
                total: 0,
                is_free: true,
            },
        ];

        render(
            <TestWrapper>
                <PosPromotionPanel {...defaultProps} freeItems={freeItems} />
            </TestWrapper>
        );

        expect(screen.getByText('Free Items Added')).toBeInTheDocument();
        expect(screen.getByText('Free Item')).toBeInTheDocument();
        expect(screen.getByText('FREE')).toBeInTheDocument();
    });

    it('displays warnings', () => {
        const warnings = ['Test warning message'];

        render(
            <TestWrapper>
                <PosPromotionPanel {...defaultProps} warnings={warnings} />
            </TestWrapper>
        );

        expect(screen.getByText('Warnings')).toBeInTheDocument();
        expect(screen.getByText('Test warning message')).toBeInTheDocument();
    });

    it('displays errors', () => {
        const errors = ['Test error message'];

        render(
            <TestWrapper>
                <PosPromotionPanel {...defaultProps} errors={errors} />
            </TestWrapper>
        );

        expect(screen.getByText('Errors')).toBeInTheDocument();
        expect(screen.getByText('Test error message')).toBeInTheDocument();
    });

    it('shows return mode info for return context', () => {
        render(
            <TestWrapper>
                <PosPromotionPanel {...defaultProps} context="return" refundAmount={50} />
            </TestWrapper>
        );

        expect(screen.getByText('Return Mode')).toBeInTheDocument();
        expect(screen.getByText('Refund Amount: 50.00 EGP')).toBeInTheDocument();
    });

    it('shows exchange mode info for exchange context', () => {
        render(
            <TestWrapper>
                <PosPromotionPanel
                    {...defaultProps}
                    context="exchange"
                    refundAmount={50}
                    netDifference={25}
                />
            </TestWrapper>
        );

        expect(screen.getByText('Exchange Mode')).toBeInTheDocument();
        expect(screen.getByText('Refund: 50.00 EGP')).toBeInTheDocument();
        expect(screen.getByText('Net: 25.00 EGP')).toBeInTheDocument();
    });
});

describe('SalesPos', () => {
    const defaultProps = {
        onProcessSale: jest.fn(),
        customerId: 1,
        locId: 1,
    };

    it('renders sales POS correctly', () => {
        render(
            <TestWrapper>
                <SalesPos {...defaultProps} />
            </TestWrapper>
        );

        expect(screen.getByText('Sales Items (0 items)')).toBeInTheDocument();
        expect(screen.getByText('Order Summary')).toBeInTheDocument();
        expect(screen.getByText('Process Sale')).toBeInTheDocument();
    });

    it('shows empty cart message when no items', () => {
        render(
            <TestWrapper>
                <SalesPos {...defaultProps} />
            </TestWrapper>
        );

        expect(screen.getByText('No items in cart')).toBeInTheDocument();
        expect(screen.getByText('Add some products to get started')).toBeInTheDocument();
    });

    it('disables process sale button when no items', () => {
        render(
            <TestWrapper>
                <SalesPos {...defaultProps} />
            </TestWrapper>
        );

        const processButton = screen.getByText('Process Sale');
        expect(processButton).toBeDisabled();
    });
});

describe('ReturnPos', () => {
    const defaultProps = {
        onProcessReturn: jest.fn(),
        customerId: 1,
        locId: 1,
        onBack: jest.fn(),
    };

    it('renders return POS correctly', () => {
        render(
            <TestWrapper>
                <ReturnPos {...defaultProps} />
            </TestWrapper>
        );

        expect(screen.getByText('Return Transaction')).toBeInTheDocument();
        expect(screen.getByText('Load Original Invoice')).toBeInTheDocument();
        expect(screen.getByText('Items to Return (0 items)')).toBeInTheDocument();
    });

    it('shows empty items message when no items loaded', () => {
        render(
            <TestWrapper>
                <ReturnPos {...defaultProps} />
            </TestWrapper>
        );

        expect(screen.getByText('No items loaded')).toBeInTheDocument();
        expect(screen.getByText('Load an invoice to see items for return')).toBeInTheDocument();
    });

    it('disables process return button when no items', () => {
        render(
            <TestWrapper>
                <ReturnPos {...defaultProps} />
            </TestWrapper>
        );

        const processButton = screen.getByText('Process Return');
        expect(processButton).toBeDisabled();
    });
});

describe('ExchangePos', () => {
    const defaultProps = {
        onProcessExchange: jest.fn(),
        customerId: 1,
        locId: 1,
        onBack: jest.fn(),
    };

    it('renders exchange POS correctly', () => {
        render(
            <TestWrapper>
                <ExchangePos {...defaultProps} />
            </TestWrapper>
        );

        expect(screen.getByText('Exchange Transaction')).toBeInTheDocument();
        expect(screen.getByText('Load Original Invoice')).toBeInTheDocument();
        expect(screen.getByText('Exchange Items')).toBeInTheDocument();
    });

    it('shows tabs for return and new items', () => {
        render(
            <TestWrapper>
                <ExchangePos {...defaultProps} />
            </TestWrapper>
        );

        expect(screen.getByText('Return Items')).toBeInTheDocument();
        expect(screen.getByText('New Items')).toBeInTheDocument();
    });

    it('shows empty messages for both tabs', () => {
        render(
            <TestWrapper>
                <ExchangePos {...defaultProps} />
            </TestWrapper>
        );

        expect(screen.getByText('No items to return')).toBeInTheDocument();
        expect(screen.getByText('No new items selected')).toBeInTheDocument();
    });

    it('disables process exchange button when no items', () => {
        render(
            <TestWrapper>
                <ExchangePos {...defaultProps} />
            </TestWrapper>
        );

        const processButton = screen.getByText('Process Exchange');
        expect(processButton).toBeDisabled();
    });
});

describe('Admin Sidebar Integration', () => {
    it('should include promotions menu in admin sidebar', () => {
        // This test would verify that the admin sidebar includes the promotions menu
        // The actual implementation would depend on how the sidebar is structured
        expect(true).toBe(true); // Placeholder test
    });
});

describe('Permission Integration', () => {
    it('should respect promotion permissions', () => {
        // This test would verify that promotion features are properly gated by permissions
        // The actual implementation would depend on how permissions are checked in components
        expect(true).toBe(true); // Placeholder test
    });
});
