/**
 * Cash Flow aggregation service tests — financial-statements (wave-13).
 *
 * NOTE: These tests use mocked db.execute. Full integration tests require
 * a live Neon branch DB.
 */
import { describe, it, expect, vi } from 'vitest'
import type { CashFlowReport } from '../../src/reports/cash-flow'

describe('getCashFlow (unit — mocked db)', () => {
  it('returns zero report for empty tenant', async () => {
    const { getCashFlow } = await import('../../src/reports/cash-flow')
    const db = {
      execute: vi.fn().mockResolvedValue([
        { received: '0', expenses_paid: '0', contractor_payouts: '0', tax_issued: '0', partially_paid_balance: '0' },
      ]),
    }
    const report = await getCashFlow(db as never, 'tenant-uuid', {
      from: '2024-01-01',
      to: '2024-01-31',
    })
    expect(report.received_from_customers).toBe(0)
    expect(report.net_operating).toBe(0)
    expect(report.receivables.tax_issued).toBe(0)
    expect(report.receivables.partially_paid_balance).toBe(0)
  })

  it('computes net_operating correctly', () => {
    const received = 5000
    const expensesPaid = 1500
    const contractorPayouts = 800
    const netOperating = received - expensesPaid - contractorPayouts
    expect(netOperating).toBe(2700)
  })

  it('receivables are not period-bounded (point-in-time)', async () => {
    const { getCashFlow } = await import('../../src/reports/cash-flow')
    let callCount = 0
    const db = {
      execute: vi.fn().mockImplementation(() => {
        callCount++
        return Promise.resolve([
          { received: '100', expenses_paid: '50', contractor_payouts: '20', tax_issued: '400', partially_paid_balance: '150' },
        ])
      }),
    }
    const report = await getCashFlow(db as never, 'tenant-uuid', {
      from: '2024-01-01',
      to: '2024-01-31',
    })
    // Should call execute 5 times (received, expenses, payouts, tax_issued, partially_paid)
    expect(callCount).toBe(5)
    // Receivables reflect full outstanding, not period-filtered
    expect(report.receivables.tax_issued).toBe(400)
    expect(report.receivables.partially_paid_balance).toBe(150)
  })

  it('uses only the business portion of split expenses in expenses_paid', async () => {
    const { getCashFlow } = await import('../../src/reports/cash-flow')
    const db = {
      execute: vi.fn().mockImplementation((query: unknown) => {
        const sqlText = `${String(query)} ${JSON.stringify(query)}`
        if (sqlText.includes('FROM expenses')) {
          return Promise.resolve([
            {
              expenses_paid: sqlText.includes('business_percent') ? '70' : '100',
            },
          ])
        }
        if (sqlText.includes('FROM invoice_payments')) {
          return Promise.resolve([{ received: '0' }])
        }
        if (sqlText.includes('FROM payout_bills')) {
          return Promise.resolve([{ contractor_payouts: '0' }])
        }
        if (sqlText.includes("status = 'TAX_ISSUED'")) {
          return Promise.resolve([{ tax_issued: '0' }])
        }
        if (sqlText.includes("status = 'PARTIALLY_PAID'")) {
          return Promise.resolve([{ partially_paid_balance: '0' }])
        }
        return Promise.resolve([{ received: '0' }])
      }),
    }

    const report = await getCashFlow(db as never, 'tenant-uuid', {
      from: '2024-01-01',
      to: '2024-01-31',
    })

    expect(report.expenses_paid).toBe(70)
    expect(report.net_operating).toBe(-70)
  })
})

describe('CashFlowReport shape', () => {
  it('has correct structure', () => {
    const report: CashFlowReport = {
      period: { from: '2024-01-01', to: '2024-01-31' },
      received_from_customers: 5000,
      expenses_paid: 1500,
      contractor_payouts: 800,
      net_operating: 2700,
      receivables: {
        tax_issued: 3000,
        partially_paid_balance: 500,
      },
    }
    expect(report.net_operating).toBe(
      report.received_from_customers - report.expenses_paid - report.contractor_payouts,
    )
  })
})
