import React from 'react'
import { renderWithProviders, userEvent, waitFor } from '@/__tests__/utils/test-helpers'
import { createMockPortfolio } from '@/__tests__/utils/test-helpers'
import { useAuth } from '@/hooks/use-auth'
import { usePortfolios } from '@/hooks/use-portfolios'
import DashboardPage from './page'

jest.mock('@/hooks/use-auth')
jest.mock('@/hooks/use-portfolios')
jest.mock('@/components/ui/button', () => ({
  Button: ({ children, ...props }: any) => <button {...props}>{children}</button>,
}))
jest.mock('@/components/ui/input', () => ({
  Input: (props: any) => <input {...props} />,
}))
jest.mock('@/components/ui/label', () => ({
  Label: ({ children, ...props }: any) => <label {...props}>{children}</label>,
}))
jest.mock('@/components/ui/card', () => ({
  Card: ({ children }: any) => <div data-testid="card">{children}</div>,
  CardHeader: ({ children }: any) => <div data-testid="card-header">{children}</div>,
  CardTitle: ({ children }: any) => <h3>{children}</h3>,
  CardDescription: ({ children }: any) => <p>{children}</p>,
  CardContent: ({ children }: any) => <div data-testid="card-content">{children}</div>,
  CardFooter: ({ children }: any) => <div data-testid="card-footer">{children}</div>,
}))
jest.mock('lucide-react', () => ({
  Upload: () => <span data-testid="upload-icon" />,
  Rocket: () => <span data-testid="rocket-icon" />,
  Plus: () => <span data-testid="plus-icon" />,
  LogOut: () => <span data-testid="logout-icon" />,
}))

describe('DashboardPage', () => {
  const mockLogout = jest.fn()
  const mockUser = { id: 1, name: 'John Doe', email: 'john@example.com', created_at: '', updated_at: '' }
  const mockPortfolios = [
    createMockPortfolio({ id: 1, name: 'Portfolio 1', active: true, path: '/uploads/1.zip' }),
    createMockPortfolio({ id: 2, name: 'Portfolio 2', active: true, path: null }),
    createMockPortfolio({ id: 3, name: 'Portfolio 3', active: false, path: null }),
  ]

  const mockCreatePortfolio = jest.fn()
  const mockUploadPortfolio = jest.fn()
  const mockDeployPortfolio = jest.fn()

  beforeEach(() => {
    jest.clearAllMocks()
    ;(useAuth as jest.Mock).mockReturnValue({
      user: mockUser,
      logout: mockLogout,
    })
    ;(usePortfolios as jest.Mock).mockReturnValue({
      portfolios: mockPortfolios,
      isLoading: false,
      error: null,
      createPortfolio: mockCreatePortfolio,
      uploadPortfolio: mockUploadPortfolio,
      deployPortfolio: mockDeployPortfolio,
    })
  })

  it('should render dashboard with header', () => {
    const { getByText, getByRole } = renderWithProviders(<DashboardPage />)

    expect(getByText('Portfolio Dashboard')).toBeInTheDocument()
    expect(getByText(`Welcome, ${mockUser.name}`)).toBeInTheDocument()
    expect(getByRole('button', { name: /logout/i })).toBeInTheDocument()
  })

  it('should display portfolio statistics', () => {
    const { getByText } = renderWithProviders(<DashboardPage />)

    expect(getByText('Total Portfolios')).toBeInTheDocument()
    expect(getByText('3')).toBeInTheDocument()
    expect(getByText('Active')).toBeInTheDocument()
    expect(getByText('2')).toBeInTheDocument()
    expect(getByText('Uploaded')).toBeInTheDocument()
    expect(getByText('1')).toBeInTheDocument()
  })

  it('should display list of portfolios', () => {
    const { getByText } = renderWithProviders(<DashboardPage />)

    mockPortfolios.forEach((portfolio) => {
      expect(getByText(portfolio.name)).toBeInTheDocument()
      expect(getByText(portfolio.domain)).toBeInTheDocument()
    })
  })

  it('should display portfolio status badges', () => {
    const { getByText } = renderWithProviders(<DashboardPage />)

    expect(getByText('Uploaded')).toBeInTheDocument()
    expect(getByText('Pending Upload')).toBeInTheDocument()
    expect(getByText('Pending Payment')).toBeInTheDocument()
  })

  it('should show create portfolio form when button clicked', async () => {
    const { getByRole, getByText, getByPlaceholderText } = renderWithProviders(<DashboardPage />)

    const newPortfolioButton = getByRole('button', { name: /new portfolio/i })
    await userEvent.click(newPortfolioButton)

    expect(getByText('Create New Portfolio')).toBeInTheDocument()
    expect(getByPlaceholderText('My Portfolio')).toBeInTheDocument()
    expect(getByPlaceholderText('myportfolio.com')).toBeInTheDocument()
  })

  it('should create portfolio with valid data', async () => {
    mockCreatePortfolio.mockResolvedValueOnce({ id: 4, name: 'New Portfolio', domain: 'new.com' })

    const { getByRole, getByPlaceholderText } = renderWithProviders(<DashboardPage />)

    const newPortfolioButton = getByRole('button', { name: /new portfolio/i })
    await userEvent.click(newPortfolioButton)

    const nameInput = getByPlaceholderText('My Portfolio') as HTMLInputElement
    const domainInput = getByPlaceholderText('myportfolio.com') as HTMLInputElement
    const createButton = getByRole('button', { name: /^Create$/ })

    await userEvent.type(nameInput, 'New Portfolio')
    await userEvent.type(domainInput, 'new.com')
    await userEvent.click(createButton)

    expect(mockCreatePortfolio).toHaveBeenCalledWith('New Portfolio', 'new.com')
  })

  it('should close create form after successful creation', async () => {
    mockCreatePortfolio.mockResolvedValueOnce({ id: 4 })

    const { getByRole, getByPlaceholderText, queryByText } = renderWithProviders(<DashboardPage />)

    const newPortfolioButton = getByRole('button', { name: /new portfolio/i })
    await userEvent.click(newPortfolioButton)

    const nameInput = getByPlaceholderText('My Portfolio') as HTMLInputElement
    const domainInput = getByPlaceholderText('myportfolio.com') as HTMLInputElement
    const createButton = getByRole('button', { name: /^Create$/ })

    await userEvent.type(nameInput, 'New Portfolio')
    await userEvent.type(domainInput, 'new.com')
    await userEvent.click(createButton)

    await waitFor(() => {
      expect(queryByText('Create New Portfolio')).not.toBeInTheDocument()
    })
  })

  it('should cancel create form', async () => {
    const { getByRole, queryByText } = renderWithProviders(<DashboardPage />)

    const newPortfolioButton = getByRole('button', { name: /new portfolio/i })
    await userEvent.click(newPortfolioButton)

    expect(queryByText('Create New Portfolio')).toBeInTheDocument()

    const cancelButton = getByRole('button', { name: /cancel/i })
    await userEvent.click(cancelButton)

    expect(queryByText('Create New Portfolio')).not.toBeInTheDocument()
  })

  it('should handle upload button for pending upload portfolio', async () => {
    const { getByRole, queryAllByRole } = renderWithProviders(<DashboardPage />)

    const uploadButtons = queryAllByRole('button', { name: /upload zip/i })
    expect(uploadButtons.length).toBeGreaterThan(0)
  })

  it('should handle deploy button for uploaded portfolio', async () => {
    mockDeployPortfolio.mockResolvedValueOnce({ id: 1 })

    const { getByRole } = renderWithProviders(<DashboardPage />)

    const deployButtons = getByRole('button', { name: /^Deploy$/ })
    await userEvent.click(deployButtons)

    expect(mockDeployPortfolio).toHaveBeenCalledWith(1)
  })

  it('should show loading state', () => {
    ;(usePortfolios as jest.Mock).mockReturnValue({
      portfolios: [],
      isLoading: true,
      error: null,
      createPortfolio: mockCreatePortfolio,
      uploadPortfolio: mockUploadPortfolio,
      deployPortfolio: mockDeployPortfolio,
    })

    const { getByText } = renderWithProviders(<DashboardPage />)
    expect(getByText('Loading portfolios...')).toBeInTheDocument()
  })

  it('should show error message', () => {
    const errorMessage = 'Failed to load portfolios'
    ;(usePortfolios as jest.Mock).mockReturnValue({
      portfolios: [],
      isLoading: false,
      error: errorMessage,
      createPortfolio: mockCreatePortfolio,
      uploadPortfolio: mockUploadPortfolio,
      deployPortfolio: mockDeployPortfolio,
    })

    const { getByText } = renderWithProviders(<DashboardPage />)
    expect(getByText(errorMessage)).toBeInTheDocument()
  })

  it('should show empty state when no portfolios', () => {
    ;(usePortfolios as jest.Mock).mockReturnValue({
      portfolios: [],
      isLoading: false,
      error: null,
      createPortfolio: mockCreatePortfolio,
      uploadPortfolio: mockUploadPortfolio,
      deployPortfolio: mockDeployPortfolio,
    })

    const { getByText } = renderWithProviders(<DashboardPage />)
    expect(getByText('No portfolios yet. Create your first one!')).toBeInTheDocument()
  })

  it('should call logout when logout button clicked', async () => {
    const { getByRole } = renderWithProviders(<DashboardPage />)

    const logoutButton = getByRole('button', { name: /logout/i })
    await userEvent.click(logoutButton)

    expect(mockLogout).toHaveBeenCalled()
  })

  it('should display portfolio creation date', () => {
    const { getByText } = renderWithProviders(<DashboardPage />)

    mockPortfolios.forEach((portfolio) => {
      const dateStr = new Date(portfolio.created_at).toLocaleDateString()
      expect(getByText(`Created: ${dateStr}`)).toBeInTheDocument()
    })
  })

  it('should handle upload loading state', async () => {
    const { getByRole, getByText } = renderWithProviders(<DashboardPage />)

    const uploadButtons = getByRole('button', { name: /upload zip/i })
    // Simulate upload in progress
    await userEvent.click(uploadButtons)

    // After click, button text should show loading
    // Note: actual file upload state management would need more complex mocking
  })

  it('should handle deploy loading state', async () => {
    const { getByRole, getByText } = renderWithProviders(<DashboardPage />)

    const deployButton = getByRole('button', { name: /^Deploy$/ })
    await userEvent.click(deployButton)

    expect(mockDeployPortfolio).toHaveBeenCalled()
  })

  it('should render statistics with responsive grid', () => {
    const { getAllByTestId } = renderWithProviders(<DashboardPage />)

    const statCards = getAllByTestId('card')
    // Should have at least stat cards + portfolio cards
    expect(statCards.length).toBeGreaterThanOrEqual(3)
  })
})
