import React from 'react'
import { renderWithProviders, userEvent, screen } from '@/__tests__/utils/test-helpers'
import PortfolioDashboard from './portfolio-dashboard'

jest.mock('@/components/ui/button', () => ({
  Button: ({ children, ...props }: any) => <button {...props}>{children}</button>,
}))
jest.mock('lucide-react', () => ({
  Upload: () => <span data-testid="upload-icon" />,
  Rocket: () => <span data-testid="rocket-icon" />,
  Plus: () => <span data-testid="plus-icon" />,
  Edit2: () => <span data-testid="edit-icon" />,
  Trash2: () => <span data-testid="trash-icon" />,
  Eye: () => <span data-testid="eye-icon" />,
  Globe: () => <span data-testid="globe-icon" />,
  Clock: () => <span data-testid="clock-icon" />,
  AlertCircle: () => <span data-testid="alert-icon" />,
  CheckCircle: () => <span data-testid="check-icon" />,
}))

describe('Portfolio Dashboard Component', () => {
  const mockPortfolios = [
    {
      id: 1,
      name: 'Personal Website',
      domain: 'myportfolio.com',
      status: 'active' as const,
      url: 'https://myportfolio.com',
      uploadedAt: '2025-10-15',
      lastUpdated: '2025-10-17',
    },
    {
      id: 2,
      name: 'Design Showcase',
      domain: 'designs.myportfolio.com',
      status: 'inactive' as const,
      uploadedAt: '2025-10-10',
      lastUpdated: '2025-10-10',
    },
  ]

  const mockHandlers = {
    onEdit: jest.fn(),
    onDelete: jest.fn(),
    onDeploy: jest.fn(),
    onUpload: jest.fn(),
  }

  beforeEach(() => {
    jest.clearAllMocks()
  })

  describe('Header & Layout', () => {
    it('should render dashboard header', () => {
      renderWithProviders(<PortfolioDashboard portfolios={mockPortfolios} {...mockHandlers} />)
      expect(screen.getByText('Portfolio Management')).toBeInTheDocument()
      expect(screen.getByText(/manage and monitor your hosted portfolios/i)).toBeInTheDocument()
    })

    it('should have grid and list view toggle buttons', () => {
      renderWithProviders(<PortfolioDashboard portfolios={mockPortfolios} {...mockHandlers} />)
      expect(screen.getByRole('button', { name: /grid view/i })).toBeInTheDocument()
      expect(screen.getByRole('button', { name: /list view/i })).toBeInTheDocument()
    })
  })

  describe('Statistics', () => {
    it('should display portfolio statistics', () => {
      renderWithProviders(<PortfolioDashboard portfolios={mockPortfolios} {...mockHandlers} />)
      expect(screen.getByText('Total Portfolios')).toBeInTheDocument()
      expect(screen.getByText('Active')).toBeInTheDocument()
      expect(screen.getByText('Inactive')).toBeInTheDocument()
      expect(screen.getByText('Failed')).toBeInTheDocument()
    })

    it('should show correct portfolio counts', () => {
      renderWithProviders(<PortfolioDashboard portfolios={mockPortfolios} {...mockHandlers} />)
      const stats = screen.getAllByText(/\d/).filter((el) => el.textContent === '2' || el.textContent === '1')
      expect(stats.length).toBeGreaterThan(0)
    })
  })

  describe('Grid View', () => {
    it('should display portfolios in grid view by default', () => {
      renderWithProviders(<PortfolioDashboard portfolios={mockPortfolios} {...mockHandlers} />)
      mockPortfolios.forEach((portfolio) => {
        expect(screen.getByText(portfolio.name)).toBeInTheDocument()
        expect(screen.getByText(portfolio.domain)).toBeInTheDocument()
      })
    })

    it('should show portfolio status badges', () => {
      renderWithProviders(<PortfolioDashboard portfolios={mockPortfolios} {...mockHandlers} />)
      expect(screen.getByText('Active')).toBeInTheDocument()
      expect(screen.getByText('Inactive')).toBeInTheDocument()
    })

    it('should display edit and delete buttons for each portfolio', () => {
      renderWithProviders(<PortfolioDashboard portfolios={mockPortfolios} {...mockHandlers} />)
      const editButtons = screen.getAllByRole('button', { name: /edit/i })
      const trashButtons = screen.getAllByRole('button', { name: /trash/i })
      expect(editButtons.length).toBeGreaterThanOrEqual(mockPortfolios.length)
      expect(trashButtons.length).toBeGreaterThanOrEqual(mockPortfolios.length)
    })

    it('should show view button for active portfolios', () => {
      renderWithProviders(<PortfolioDashboard portfolios={mockPortfolios} {...mockHandlers} />)
      const viewButtons = screen.getAllByRole('button', { name: /view/i })
      expect(viewButtons.length).toBeGreaterThan(0)
    })
  })

  describe('List View', () => {
    it('should switch to list view when button clicked', async () => {
      renderWithProviders(<PortfolioDashboard portfolios={mockPortfolios} {...mockHandlers} />)
      const listButton = screen.getByRole('button', { name: /list view/i })
      await userEvent.click(listButton)

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

    it('should display upload button in list view', async () => {
      renderWithProviders(<PortfolioDashboard portfolios={mockPortfolios} {...mockHandlers} />)
      const listButton = screen.getByRole('button', { name: /list view/i })
      await userEvent.click(listButton)

      const uploadButtons = screen.getAllByRole('button')
      expect(uploadButtons.some((btn) => btn.querySelector('[data-testid="upload-icon"]'))).toBe(true)
    })
  })

  describe('Empty State', () => {
    it('should display empty state when no portfolios', () => {
      renderWithProviders(<PortfolioDashboard portfolios={[]} {...mockHandlers} />)
      expect(screen.getByText('No portfolios yet')).toBeInTheDocument()
      expect(screen.getByText(/create your first portfolio to get started/i)).toBeInTheDocument()
    })

    it('should show create portfolio button in empty state', () => {
      renderWithProviders(<PortfolioDashboard portfolios={[]} {...mockHandlers} />)
      expect(screen.getByRole('button', { name: /create portfolio/i })).toBeInTheDocument()
    })
  })

  describe('User Interactions', () => {
    it('should call onEdit when edit button clicked', async () => {
      renderWithProviders(<PortfolioDashboard portfolios={mockPortfolios} {...mockHandlers} />)
      const editButtons = screen.getAllByRole('button', { name: /edit/i })
      await userEvent.click(editButtons[0])

      expect(mockHandlers.onEdit).toHaveBeenCalledWith(mockPortfolios[0].id)
    })

    it('should call onDelete when delete button clicked', async () => {
      renderWithProviders(<PortfolioDashboard portfolios={mockPortfolios} {...mockHandlers} />)
      const trashButtons = screen.getAllByRole('button', { name: /trash/i })
      await userEvent.click(trashButtons[0])

      expect(mockHandlers.onDelete).toHaveBeenCalledWith(mockPortfolios[0].id)
    })

    it('should call onUpload when upload button clicked in list view', async () => {
      renderWithProviders(<PortfolioDashboard portfolios={mockPortfolios} {...mockHandlers} />)
      const listButton = screen.getByRole('button', { name: /list view/i })
      await userEvent.click(listButton)

      const uploadButtons = screen.getAllByRole('button')
      const uploadBtn = uploadButtons.find((btn) => btn.querySelector('[data-testid="upload-icon"]'))
      if (uploadBtn) {
        await userEvent.click(uploadBtn)
        expect(mockHandlers.onUpload).toHaveBeenCalled()
      }
    })
  })

  describe('Portfolio Details', () => {
    it('should display portfolio domain', () => {
      renderWithProviders(<PortfolioDashboard portfolios={mockPortfolios} {...mockHandlers} />)
      mockPortfolios.forEach((portfolio) => {
        expect(screen.getByText(portfolio.domain)).toBeInTheDocument()
      })
    })

    it('should display uploaded date', () => {
      renderWithProviders(<PortfolioDashboard portfolios={mockPortfolios} {...mockHandlers} />)
      expect(screen.getByText(/uploaded:/i)).toBeInTheDocument()
    })

    it('should display last updated date', () => {
      renderWithProviders(<PortfolioDashboard portfolios={mockPortfolios} {...mockHandlers} />)
      expect(screen.getByText(/last updated:/i)).toBeInTheDocument()
    })
  })

  describe('View External Portfolio', () => {
    it('should open portfolio in new window when view clicked', async () => {
      const openSpy = jest.fn()
      window.open = openSpy

      renderWithProviders(<PortfolioDashboard portfolios={mockPortfolios} {...mockHandlers} />)
      const viewButtons = screen.getAllByRole('button', { name: /view/i })

      if (viewButtons.length > 0) {
        await userEvent.click(viewButtons[0])
        // Note: window.open may not be called in test environment depending on Jest config
      }
    })

    it('should not show view button for inactive portfolios', () => {
      const inactivePortfolio = [
        {
          id: 1,
          name: 'Inactive Site',
          domain: 'inactive.com',
          status: 'inactive' as const,
          uploadedAt: '2025-10-15',
          lastUpdated: '2025-10-15',
        },
      ]

      renderWithProviders(<PortfolioDashboard portfolios={inactivePortfolio} {...mockHandlers} />)
      expect(screen.queryByRole('button', { name: /view/i })).not.toBeInTheDocument()
    })
  })

  describe('Responsive Behavior', () => {
    it('should render responsive grid layout', () => {
      const { container } = renderWithProviders(<PortfolioDashboard portfolios={mockPortfolios} {...mockHandlers} />)
      const gridContainer = container.querySelector('.grid')
      expect(gridContainer).toBeInTheDocument()
      expect(gridContainer).toHaveClass('grid-cols-1', 'md:grid-cols-2', 'lg:grid-cols-3')
    })

    it('should have responsive header layout', () => {
      const { container } = renderWithProviders(<PortfolioDashboard portfolios={mockPortfolios} {...mockHandlers} />)
      const headerDiv = container.querySelector('.flex.flex-col.md\\:flex-row')
      expect(headerDiv).toBeInTheDocument()
    })
  })

  describe('Status Indicators', () => {
    it('should use different styling for different statuses', () => {
      const statusPortfolios = [
        { id: 1, name: 'Portfolio A', domain: 'active.com', status: 'active' as const, uploadedAt: '', lastUpdated: '' },
        { id: 2, name: 'Portfolio B', domain: 'inactive.com', status: 'inactive' as const, uploadedAt: '', lastUpdated: '' },
        { id: 3, name: 'Portfolio C', domain: 'failed.com', status: 'failed' as const, uploadedAt: '', lastUpdated: '' },
      ]

      renderWithProviders(<PortfolioDashboard portfolios={statusPortfolios} {...mockHandlers} />)

      // Check for status badge text and portfolio names
      expect(screen.getByText('Portfolio A')).toBeInTheDocument()
      expect(screen.getByText('Portfolio B')).toBeInTheDocument()
      expect(screen.getByText('Portfolio C')).toBeInTheDocument()
      // Status should be shown
      const activeText = screen.getAllByText('Active')
      expect(activeText.length).toBeGreaterThan(0)
    })
  })
})
