import { describe, expect, it, vi } from 'vitest'

function makeSelectChain(
  result: unknown,
  options: {
    joinMethod?: 'where' | 'leftJoin' | 'innerJoin'
    withLimit?: boolean
    withOrderBy?: boolean
  } = {},
) {
  const { joinMethod = 'where', withLimit = false, withOrderBy = false } = options
  const whereResult = withLimit
    ? {
        limit: vi.fn().mockResolvedValue(result),
      }
    : withOrderBy
      ? {
          orderBy: vi.fn().mockResolvedValue(result),
        }
    : result
  const where = vi.fn().mockReturnValue(whereResult)
  if (joinMethod === 'where') {
    return {
      from: vi.fn(() => ({
        where,
      })),
    }
  }

  return {
    from: vi.fn(() => ({
      [joinMethod]: vi.fn(() => ({
        where,
      })),
    })),
  }
}

describe('getCustomerProfitability', () => {
  it('excludes projects whose profitability detail is missing and summarizes the remaining rows', async () => {
    const db = {
      select: vi
        .fn()
        .mockImplementationOnce(() => ({
          from: vi.fn(() => ({
            where: vi.fn(() => ({
              limit: vi.fn().mockResolvedValue([
                { id: 'customer-1', name: 'Acme Corp' },
              ]),
            })),
          })),
        }))
        .mockImplementationOnce(() => ({
          from: vi.fn(() => ({
            where: vi.fn().mockResolvedValue([
              { id: 'project-missing', name: 'Missing Project' },
              { id: 'project-live', name: 'Live Project' },
            ]),
          })),
        }))
        .mockImplementationOnce(() => makeSelectChain([], { joinMethod: 'leftJoin', withLimit: true }))
        .mockImplementationOnce(() => makeSelectChain([
          {
            id: 'project-live',
            name: 'Live Project',
            customerId: 'customer-1',
            customerName: 'Acme Corp',
          },
        ], { joinMethod: 'leftJoin', withLimit: true }))
        .mockImplementationOnce(() => makeSelectChain([
          {
            invoiceId: 'invoice-1',
            number: 'INV-1',
            issuedAt: '2026-06-15',
            amount: '1000.00',
            status: 'PAID',
            isCreditNote: false,
          },
        ], { withOrderBy: true }))
        .mockImplementationOnce(() => makeSelectChain([
          { staffCost: '250.00', staffHours: '5.00' },
        ], { joinMethod: 'innerJoin' }))
        .mockImplementationOnce(() => makeSelectChain([{ contractorCost: '150.00' }], { joinMethod: 'innerJoin' }))
        .mockImplementationOnce(() => makeSelectChain([{ expenseCost: '50.00' }])),
    }

    const { getCustomerProfitability } = await import('../../src/queries/profitability')
    const result = await getCustomerProfitability(db as never, 'tenant-1', 'customer-1')

    expect(result).toEqual({
      customerId: 'customer-1',
      customerName: 'Acme Corp',
      projects: [
        {
          id: 'project-live',
          name: 'Live Project',
          customerId: 'customer-1',
          customerName: 'Acme Corp',
          revenue: '1000.00',
          cost: '450.00',
          profit: '550.00',
          margin: '55.00',
        },
      ],
      summary: {
        revenue: '1000.00',
        cost: '450.00',
        profit: '550.00',
        margin: '55.00',
      },
    })
  })
})
