import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen } from '@testing-library/react';

const { mockUseApi } = vi.hoisted(() => ({ mockUseApi: vi.fn() }));
const { mockUseSWR } = vi.hoisted(() => ({ mockUseSWR: vi.fn() }));

vi.mock('@/lib/useApi', () => ({ useApi: mockUseApi }));
vi.mock('swr', () => ({ default: mockUseSWR }));

vi.mock('@/services/cabinet', () => ({
  getCabinetSummary: vi.fn(),
}));

vi.mock('@/services/regimens', () => ({
  getBurnRates: vi.fn(),
}));

vi.mock('@/services/purchases', () => ({
  listPurchases: vi.fn(),
}));

vi.mock('@/services/refills', () => ({
  getRefillAlerts: vi.fn(),
}));

vi.mock('@/services/cabinet-events', () => ({
  listCabinetEvents: vi.fn(),
}));

vi.mock('next/link', () => ({
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  default: (props: any) => <a href={props.href}>{props.children}</a>,
}));

import DashboardPage from '../../../../src/app/(dashboard)/dashboard/page';

beforeEach(() => {
  vi.clearAllMocks();
  mockUseApi.mockReturnValue({ householdId: null, isLoading: true, profile: undefined });
  mockUseSWR.mockReturnValue({ data: undefined });
});

describe(DashboardPage.name, () => {
  it('renders heading', () => {
    render(<DashboardPage />);
    expect(screen.getByText('Dashboard')).toBeInTheDocument();
  });

  it('shows loading skeleton when session loading', () => {
    render(<DashboardPage />);
    expect(screen.getByText('Dashboard')).toBeInTheDocument();
  });

  it('renders greeting with user name', () => {
    mockUseApi.mockReturnValue({
      householdId: 'hh1',
      isLoading: false,
      profile: { displayName: 'John Doe' },
    });

    render(<DashboardPage />);

    expect(screen.getByText(/John/)).toBeInTheDocument();
  });

  it('renders generic greeting without profile', () => {
    mockUseApi.mockReturnValue({ householdId: 'hh1', isLoading: false, profile: null });

    render(<DashboardPage />);

    expect(screen.getByText(/there/)).toBeInTheDocument();
  });

  it('renders cabinet items that are in active regimens', () => {
    mockUseApi.mockReturnValue({
      householdId: 'hh1',
      isLoading: false,
      profile: { displayName: 'Jane' },
    });

    const summaryData = {
      data: [
        { medicineId: '1', medicineName: 'Aspirin', totalQuantity: 50, unit: 'tablets' },
        { medicineId: '2', medicineName: 'Ibuprofen', totalQuantity: 100, unit: 'tablets' },
      ],
    };

    const burnRateData = {
      data: [
        { medicineId: '1', medicineName: 'Aspirin', daysUntilEmpty: 10 },
      ],
    };

    mockUseSWR.mockImplementation((key: string) => {
      if (!key) return { data: undefined };
      if (key.includes('cabinet-summary')) return { data: summaryData };
      if (key.includes('burn-rates')) return { data: burnRateData };
      if (key.includes('refill-alerts')) return { data: { data: [] } };
      if (key.includes('purchases')) return { data: { data: [] } };
      if (key.includes('cabinet-events')) return { data: { data: [] } };
      return { data: undefined };
    });

    render(<DashboardPage />);

    expect(screen.getByText('Aspirin')).toBeInTheDocument();
    // Ibuprofen should NOT be in the document because it has no burn rate
    expect(screen.queryByText('Ibuprofen')).not.toBeInTheDocument();
  });

  it('shows empty states when no data', () => {
    mockUseApi.mockReturnValue({
      householdId: 'hh1',
      isLoading: false,
      profile: { displayName: 'Jane' },
    });

    mockUseSWR.mockImplementation((key: string) => {
      if (!key) return { data: undefined };
      if (key.includes('cabinet-summary')) return { data: { data: [] } };
      if (key.includes('burn-rates')) return { data: { data: [] } };
      if (key.includes('refill-alerts')) return { data: { data: [] } };
      if (key.includes('purchases')) return { data: { data: [] } };
      if (key.includes('cabinet-events')) return { data: { data: [] } };
      return { data: undefined };
    });

    render(<DashboardPage />);

    expect(screen.getByText('No active medicines in regimens.')).toBeInTheDocument();
    expect(screen.getByText('No alerts — all stocked.')).toBeInTheDocument();
    expect(screen.getByText('No pending orders.')).toBeInTheDocument();
    expect(screen.getByText('No recent activity.')).toBeInTheDocument();
  });

  it('shows refill alerts with days left', () => {
    mockUseApi.mockReturnValue({
      householdId: 'hh1',
      isLoading: false,
      profile: { displayName: 'Jane' },
    });

    const refillData = {
      data: [{ medicineId: 'm1', medicineName: 'Vitamin C', daysUntilEmpty: 5 }],
    };

    mockUseSWR.mockImplementation((key: string) => {
      if (!key) return { data: undefined };
      if (key.includes('cabinet-summary')) return { data: { data: [{ medicineId: '1' }] } };
      if (key.includes('burn-rates')) return { data: { data: [] } };
      if (key.includes('refill-alerts')) return { data: refillData };
      if (key.includes('purchases')) return { data: { data: [] } };
      if (key.includes('cabinet-events')) return { data: { data: [] } };
      return { data: undefined };
    });

    render(<DashboardPage />);

    expect(screen.getByText('Vitamin C')).toBeInTheDocument();
    expect(screen.getByText('5d')).toBeInTheDocument();
    expect(screen.getByText(/critically low/)).toBeInTheDocument();
  });

  it('shows pending purchases', () => {
    mockUseApi.mockReturnValue({
      householdId: 'hh1',
      isLoading: false,
      profile: { displayName: 'Jane' },
    });

    const purchaseData = {
      data: [
        {
          _id: 'p1',
          storeName: 'Pharmacy Plus',
          items: [{ name: 'A' }, { name: 'B' }],
          status: 'ordered',
        },
      ],
    };

    mockUseSWR.mockImplementation((key: string) => {
      if (!key) return { data: undefined };
      if (key.includes('cabinet-summary')) return { data: { data: [] } };
      if (key.includes('burn-rates')) return { data: { data: [] } };
      if (key.includes('refill-alerts')) return { data: { data: [] } };
      if (key.includes('purchases')) return { data: purchaseData };
      if (key.includes('cabinet-events')) return { data: { data: [] } };
      return { data: undefined };
    });

    render(<DashboardPage />);

    expect(screen.getByText('Pharmacy Plus')).toBeInTheDocument();
    expect(screen.getByText('2 items')).toBeInTheDocument();
    expect(screen.getByText('ordered')).toBeInTheDocument();
  });

  it('shows recent events', () => {
    mockUseApi.mockReturnValue({
      householdId: 'hh1',
      isLoading: false,
      profile: { displayName: 'Jane' },
    });

    const eventData = {
      data: [
        {
          _id: 'e1',
          eventType: 'consumed',
          medicineName: 'Aspirin',
          createdAt: '2026-01-15T10:00:00.000Z',
        },
      ],
    };

    mockUseSWR.mockImplementation((key: string) => {
      if (!key) return { data: undefined };
      if (key.includes('cabinet-summary')) return { data: { data: [] } };
      if (key.includes('burn-rates')) return { data: { data: [] } };
      if (key.includes('refill-alerts')) return { data: { data: [] } };
      if (key.includes('purchases')) return { data: { data: [] } };
      if (key.includes('cabinet-events')) return { data: eventData };
      return { data: undefined };
    });

    render(<DashboardPage />);

    expect(screen.getByText('consumed')).toBeInTheDocument();
    expect(screen.getByText('Aspirin')).toBeInTheDocument();
  });

  it('shows "good shape" message when no critical alerts', () => {
    mockUseApi.mockReturnValue({
      householdId: 'hh1',
      isLoading: false,
      profile: { displayName: 'Jane' },
    });

    mockUseSWR.mockImplementation((key: string) => {
      if (!key) return { data: undefined };
      if (key.includes('cabinet-summary')) return { data: { data: [{ medicineId: '1' }] } };
      if (key.includes('burn-rates')) return { data: { data: [] } };
      if (key.includes('refill-alerts')) return { data: { data: [{ daysUntilEmpty: 20 }] } };
      if (key.includes('purchases')) return { data: { data: [] } };
      if (key.includes('cabinet-events')) return { data: { data: [] } };
      return { data: undefined };
    });

    render(<DashboardPage />);

    expect(screen.getByText('Your cabinet is in good shape.')).toBeInTheDocument();
  });

  it('shows stat badges with summary data', () => {
    mockUseApi.mockReturnValue({
      householdId: 'hh1',
      isLoading: false,
      profile: { displayName: 'Jane' },
    });

    mockUseSWR.mockImplementation((key: string) => {
      if (!key) return { data: undefined };
      if (key.includes('cabinet-summary'))
        return { data: { data: [{ medicineId: '1' }, { medicineId: '2' }, { medicineId: '3' }] } };
      if (key.includes('burn-rates')) return { data: { data: [] } };
      if (key.includes('refill-alerts'))
        return { data: { data: [{ daysUntilEmpty: 5 }, { daysUntilEmpty: 3 }] } };
      if (key.includes('purchases')) return { data: { data: [] } };
      if (key.includes('cabinet-events')) return { data: { data: [] } };
      return { data: undefined };
    });

    render(<DashboardPage />);

    expect(screen.getByText('Total medicines')).toBeInTheDocument();
    expect(screen.getByText('3')).toBeInTheDocument();
    expect(screen.getAllByText('Running low')).toHaveLength(2);
    expect(screen.getByText('2')).toBeInTheDocument();
  });

  it('handles store without name', () => {
    mockUseApi.mockReturnValue({
      householdId: 'hh1',
      isLoading: false,
      profile: { displayName: 'Jane' },
    });

    const purchaseData = {
      data: [{ _id: 'p1', storeName: undefined, items: [{ name: 'A' }], status: 'ordered' }],
    };

    mockUseSWR.mockImplementation((key: string) => {
      if (!key) return { data: undefined };
      if (key.includes('cabinet-summary')) return { data: { data: [] } };
      if (key.includes('burn-rates')) return { data: { data: [] } };
      if (key.includes('refill-alerts')) return { data: { data: [] } };
      if (key.includes('purchases')) return { data: purchaseData };
      if (key.includes('cabinet-events')) return { data: { data: [] } };
      return { data: undefined };
    });

    render(<DashboardPage />);

    expect(screen.getByText('Unknown store')).toBeInTheDocument();
  });

  it('handles cabinet item with no name', () => {
    mockUseApi.mockReturnValue({
      householdId: 'hh1',
      isLoading: false,
      profile: { displayName: 'Jane' },
    });

    const summaryData = {
      data: [{ medicineId: 'c1', medicineName: undefined, totalQuantity: 10, unit: 'pills' }],
    };

    const burnRateData = {
      data: [{ medicineId: 'c1', medicineName: undefined, daysUntilEmpty: 5 }],
    };

    mockUseSWR.mockImplementation((key: string) => {
      if (!key) return { data: undefined };
      if (key.includes('cabinet-summary')) return { data: summaryData };
      if (key.includes('burn-rates')) return { data: burnRateData };
      if (key.includes('refill-alerts')) return { data: { data: [] } };
      if (key.includes('purchases')) return { data: { data: [] } };
      if (key.includes('cabinet-events')) return { data: { data: [] } };
      return { data: undefined };
    });

    render(<DashboardPage />);

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