// src/admin/analytics/__tests__/useAnalytics.test.js
import { renderHook, act } from '@testing-library/react';
import { vi, describe, it, expect, beforeEach } from 'vitest';

vi.mock('../../../lib/supabase', () => ({
  supabase: {
    from: vi.fn(),
  },
}));

import { useAnalytics } from '../useAnalytics';
import { supabase } from '../../../lib/supabase';

const FROM = '2026-01-01T00:00:00.000Z';
const TO = '2026-12-31T23:59:59.999Z';

describe('useAnalytics', () => {
  beforeEach(() => vi.clearAllMocks());

  it('returns loading=true initially', () => {
    supabase.from.mockReturnValue({
      select: vi.fn().mockReturnThis(),
      gte: vi.fn().mockReturnThis(),
      lte: vi.fn().mockReturnThis(),
      eq: vi.fn().mockReturnThis(),
      in: vi.fn().mockReturnThis(),
      order: vi.fn().mockReturnValue(new Promise(() => {})),
    });
    const { result } = renderHook(() => useAnalytics(FROM, TO));
    expect(result.current.loading).toBe(true);
  });

  it('computes totalOrders, closedOrders, conversionRate correctly', async () => {
    const orders = [
      { id: '1', status: 'новая', object_type: 'industrial', created_at: '2026-03-01', final_cost: null, closed_at: null },
      { id: '2', status: 'закрыт', object_type: 'commercial', created_at: '2026-03-02', final_cost: 50000, closed_at: '2026-03-10' },
      { id: '3', status: 'закрыт', object_type: 'industrial', created_at: '2026-04-01', final_cost: 80000, closed_at: '2026-04-15' },
    ];
    const events = [];

    supabase.from.mockImplementation((table) => {
      if (table === 'orders') {
        return {
          select: vi.fn().mockReturnThis(),
          gte: vi.fn().mockReturnThis(),
          lte: vi.fn().mockResolvedValue({ data: orders, error: null }),
        };
      }
      return {
        select: vi.fn().mockReturnThis(),
        eq: vi.fn().mockReturnThis(),
        gte: vi.fn().mockReturnThis(),
        in: vi.fn().mockReturnThis(),
        order: vi.fn().mockResolvedValue({ data: events, error: null }),
      };
    });

    const { result } = renderHook(() => useAnalytics(FROM, TO));
    await act(async () => {});

    expect(result.current.totalOrders).toBe(3);
    expect(result.current.closedOrders).toBe(2);
    expect(result.current.conversionRate).toBe(67);
    expect(result.current.totalRevenue).toBe(130000);
    expect(result.current.avgDeal).toBe(65000);
    expect(result.current.loading).toBe(false);
  });

  it('builds byObjectType counts', async () => {
    const orders = [
      { id: '1', status: 'новая', object_type: 'industrial', created_at: '2026-03-01', final_cost: null, closed_at: null },
      { id: '2', status: 'новая', object_type: 'industrial', created_at: '2026-03-02', final_cost: null, closed_at: null },
      { id: '3', status: 'новая', object_type: 'commercial', created_at: '2026-03-03', final_cost: null, closed_at: null },
    ];
    supabase.from.mockImplementation((table) => {
      if (table === 'orders') {
        return { select: vi.fn().mockReturnThis(), gte: vi.fn().mockReturnThis(), lte: vi.fn().mockResolvedValue({ data: orders, error: null }) };
      }
      return { select: vi.fn().mockReturnThis(), eq: vi.fn().mockReturnThis(), gte: vi.fn().mockReturnThis(), in: vi.fn().mockReturnThis(), order: vi.fn().mockResolvedValue({ data: [], error: null }) };
    });

    const { result } = renderHook(() => useAnalytics(FROM, TO));
    await act(async () => {});
    const industrial = result.current.byObjectType.find((x) => x.type === 'industrial');
    expect(industrial?.count).toBe(2);
  });

  it('sets error when orders fetch fails', async () => {
    supabase.from.mockImplementation((table) => {
      if (table === 'orders') {
        return {
          select: vi.fn().mockReturnThis(),
          gte: vi.fn().mockReturnThis(),
          lte: vi.fn().mockResolvedValue({ data: null, error: { message: 'DB error' } }),
        };
      }
      return {
        select: vi.fn().mockReturnThis(),
        eq: vi.fn().mockReturnThis(),
        gte: vi.fn().mockReturnThis(),
        in: vi.fn().mockReturnThis(),
        order: vi.fn().mockResolvedValue({ data: [], error: null }),
      };
    });
    const { result } = renderHook(() => useAnalytics(FROM, TO));
    await act(async () => {});
    expect(result.current.error).toBe('DB error');
    expect(result.current.loading).toBe(false);
  });

  it('returns funnelData with all 5 statuses', async () => {
    const orders = [
      { id: '1', status: 'новая', object_type: 'industrial', created_at: '2026-03-01', final_cost: null, closed_at: null },
      { id: '2', status: 'замер', object_type: 'industrial', created_at: '2026-03-02', final_cost: null, closed_at: null },
    ];
    supabase.from.mockImplementation((table) => {
      if (table === 'orders') {
        return { select: vi.fn().mockReturnThis(), gte: vi.fn().mockReturnThis(), lte: vi.fn().mockResolvedValue({ data: orders, error: null }) };
      }
      return { select: vi.fn().mockReturnThis(), eq: vi.fn().mockReturnThis(), gte: vi.fn().mockReturnThis(), in: vi.fn().mockReturnThis(), order: vi.fn().mockResolvedValue({ data: [], error: null }) };
    });
    const { result } = renderHook(() => useAnalytics(FROM, TO));
    await act(async () => {});
    expect(result.current.funnelData).toHaveLength(5);
    expect(result.current.funnelData.find((d) => d.status === 'новая')?.count).toBe(1);
    expect(result.current.funnelData.find((d) => d.status === 'замер')?.count).toBe(1);
    expect(result.current.funnelData.find((d) => d.status === 'монтаж')?.count).toBe(0);
  });
});
