import { describe, it, expect, vi, beforeEach } from 'vitest'
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import PositionCard from '../PositionCard'
import { PositionResponse, OrderType } from '../../types'
import * as tradingApi from '../../api/trading'

vi.mock('../../api/trading')
vi.mock('../../contexts/SnackbarContext', () => ({
    useSnackbar: () => ({
        showError: vi.fn(),
        showSuccess: vi.fn(),
        showWarning: vi.fn(),
        showInfo: vi.fn(),
    }),
}))

const mockPosition: PositionResponse = {
    id: 1,
    symbol: 'BTC/USD',
    quantity: 0.5,
    entry_price: 40000,
    current_price: 42000,
    unrealized_pnl: 1000,
    realized_pnl: 500,
    side: 'long',
    opened_at: '2024-01-01T00:00:00Z',
}

describe('PositionCard', () => {
    let queryClient: QueryClient

    beforeEach(() => {
        queryClient = new QueryClient({
            defaultOptions: { queries: { retry: false } },
        })
        vi.clearAllMocks()
    })

    const renderComponent = (position = mockPosition, paperTrading = false) => {
        const onClose = vi.fn()
        return {
            onClose,
            ...render(
                <QueryClientProvider client={queryClient}>
                    <PositionCard position={position} paperTrading={paperTrading} onClose={onClose} />
                </QueryClientProvider>
            ),
        }
    }

    describe('position data display', () => {
        it('renders position symbol', () => {
            renderComponent()
            expect(screen.getByText('BTC/USD')).toBeInTheDocument()
        })

        it('renders position quantity', () => {
            renderComponent()
            expect(screen.getByText('0.50000000')).toBeInTheDocument()
        })

        it('renders entry price', () => {
            renderComponent()
            expect(screen.getByText('$40000.00')).toBeInTheDocument()
        })

        it('renders current price', () => {
            renderComponent()
            expect(screen.getByText('$42000.00')).toBeInTheDocument()
        })
    })

    describe('PnL display', () => {
        it('displays positive unrealized PnL with plus sign', () => {
            renderComponent()
            expect(screen.getByText('+$1000.00')).toBeInTheDocument()
        })

        it('displays positive realized PnL with plus sign', () => {
            renderComponent()
            expect(screen.getByText('+$500.00')).toBeInTheDocument()
        })

        it('displays negative unrealized PnL correctly', () => {
            const negativePosition = { ...mockPosition, unrealized_pnl: -500 }
            renderComponent(negativePosition)
            expect(screen.getByText('-$500.00')).toBeInTheDocument()
        })

        it('shows positive percent chip for profitable position', () => {
            renderComponent()
            expect(screen.getByText('+5.00%')).toBeInTheDocument()
        })

        it('shows negative percent chip for losing position', () => {
            const losingPosition = { ...mockPosition, current_price: 38000 }
            renderComponent(losingPosition)
            expect(screen.getByText('-5.00%')).toBeInTheDocument()
        })
    })

    describe('close position functionality', () => {
        it('shows close position button', () => {
            renderComponent()
            expect(screen.getByText('Close Position')).toBeInTheDocument()
        })

        it('opens close dialog when button is clicked', async () => {
            renderComponent()

            fireEvent.click(screen.getByText('Close Position'))

            await waitFor(() => {
                expect(screen.getByRole('dialog')).toBeInTheDocument()
            })
        })

        it('shows order type selector in dialog', async () => {
            renderComponent()

            fireEvent.click(screen.getByText('Close Position'))

            await waitFor(() => {
                expect(screen.getByLabelText('Order Type')).toBeInTheDocument()
            })
        })

        it('closes dialog when cancel is clicked', async () => {
            renderComponent()

            fireEvent.click(screen.getByText('Close Position'))

            await waitFor(() => {
                expect(screen.getByRole('dialog')).toBeInTheDocument()
            })

            fireEvent.click(screen.getByText('Cancel'))

            await waitFor(() => {
                expect(screen.queryByRole('dialog')).not.toBeInTheDocument()
            })
        })

        it('submits market order when confirmed', async () => {
            const mockCreateOrder = vi.fn().mockResolvedValue({})
            vi.mocked(tradingApi.tradingApi.createOrder).mockImplementation(mockCreateOrder)

            renderComponent()

            fireEvent.click(screen.getByText('Close Position'))

            await waitFor(() => {
                expect(screen.getByRole('dialog')).toBeInTheDocument()
            })

            // Click the confirm button (second "Close Position" button in dialog)
            const buttons = screen.getAllByText('Close Position')
            fireEvent.click(buttons[1])

            await waitFor(() => {
                expect(mockCreateOrder).toHaveBeenCalled()
            })
        })
    })
})
