import { describe, expect, it } from 'vitest';
import { calculateOverallConfidence, } from '../helpers/overall-confidence.helper.js';
describe('Overall Confidence Calculator', () => {
    describe('Perfect Matches', () => {
        it('should return 1.0 when all components are 1.0', () => {
            const components = {
                amount: 1.0,
                currency: 1.0,
                business: 1.0,
                date: 1.0,
            };
            expect(calculateOverallConfidence(components)).toBe(1.0);
        });
        it('should return 1.0 when all components are exactly 1.0', () => {
            const result = calculateOverallConfidence({
                amount: 1.0,
                currency: 1.0,
                business: 1.0,
                date: 1.0,
            });
            expect(result).toBe(1.0);
            expect(typeof result).toBe('number');
        });
    });
    describe('Zero Matches', () => {
        it('should return 0.0 when all components are 0.0', () => {
            const components = {
                amount: 0.0,
                currency: 0.0,
                business: 0.0,
                date: 0.0,
            };
            expect(calculateOverallConfidence(components)).toBe(0.0);
        });
    });
    describe('Weighted Formula Verification', () => {
        it('should correctly apply amount weight (0.4)', () => {
            // Only amount is 1.0, others are 0.0
            const result = calculateOverallConfidence({
                amount: 1.0,
                currency: 0.0,
                business: 0.0,
                date: 0.0,
            });
            expect(result).toBe(0.4);
        });
        it('should correctly apply currency weight (0.2)', () => {
            // Only currency is 1.0, others are 0.0
            const result = calculateOverallConfidence({
                amount: 0.0,
                currency: 1.0,
                business: 0.0,
                date: 0.0,
            });
            expect(result).toBe(0.2);
        });
        it('should correctly apply business weight (0.3)', () => {
            // Only business is 1.0, others are 0.0
            const result = calculateOverallConfidence({
                amount: 0.0,
                currency: 0.0,
                business: 1.0,
                date: 0.0,
            });
            expect(result).toBe(0.3);
        });
        it('should correctly apply date weight (0.1)', () => {
            // Only date is 1.0, others are 0.0
            const result = calculateOverallConfidence({
                amount: 0.0,
                currency: 0.0,
                business: 0.0,
                date: 1.0,
            });
            expect(result).toBe(0.1);
        });
        it('should verify weights sum to 1.0', () => {
            // When all components are 1.0, result should be 1.0
            // This verifies: 0.4 + 0.2 + 0.3 + 0.1 = 1.0
            const result = calculateOverallConfidence({
                amount: 1.0,
                currency: 1.0,
                business: 1.0,
                date: 1.0,
            });
            expect(result).toBe(1.0);
        });
    });
    describe('Mixed Confidence Scenarios', () => {
        it('should handle typical good match (all high)', () => {
            const result = calculateOverallConfidence({
                amount: 0.9,
                currency: 1.0,
                business: 1.0,
                date: 1.0,
            });
            // (0.9 × 0.4) + (1.0 × 0.2) + (1.0 × 0.3) + (1.0 × 0.1) = 0.96
            expect(result).toBe(0.96);
        });
        it('should handle partial match (mixed scores)', () => {
            const result = calculateOverallConfidence({
                amount: 0.9,
                currency: 1.0,
                business: 0.5,
                date: 0.8,
            });
            // (0.9 × 0.4) + (1.0 × 0.2) + (0.5 × 0.3) + (0.8 × 0.1)
            // = 0.36 + 0.2 + 0.15 + 0.08 = 0.79
            expect(result).toBe(0.79);
        });
        it('should handle uncertain business with good other factors', () => {
            const result = calculateOverallConfidence({
                amount: 1.0,
                currency: 1.0,
                business: 0.5,
                date: 1.0,
            });
            // (1.0 × 0.4) + (1.0 × 0.2) + (0.5 × 0.3) + (1.0 × 0.1)
            // = 0.4 + 0.2 + 0.15 + 0.1 = 0.85
            expect(result).toBe(0.85);
        });
        it('should handle missing currency with good match otherwise', () => {
            const result = calculateOverallConfidence({
                amount: 1.0,
                currency: 0.2, // Missing currency penalty
                business: 1.0,
                date: 1.0,
            });
            // (1.0 × 0.4) + (0.2 × 0.2) + (1.0 × 0.3) + (1.0 × 0.1)
            // = 0.4 + 0.04 + 0.3 + 0.1 = 0.84
            expect(result).toBe(0.84);
        });
        it('should handle business mismatch with good amount/currency', () => {
            const result = calculateOverallConfidence({
                amount: 1.0,
                currency: 1.0,
                business: 0.2, // Mismatch
                date: 1.0,
            });
            // (1.0 × 0.4) + (1.0 × 0.2) + (0.2 × 0.3) + (1.0 × 0.1)
            // = 0.4 + 0.2 + 0.06 + 0.1 = 0.76
            expect(result).toBe(0.76);
        });
        it('should handle old date with perfect other factors', () => {
            const result = calculateOverallConfidence({
                amount: 1.0,
                currency: 1.0,
                business: 1.0,
                date: 0.0, // 30+ days apart
            });
            // (1.0 × 0.4) + (1.0 × 0.2) + (1.0 × 0.3) + (0.0 × 0.1)
            // = 0.4 + 0.2 + 0.3 + 0.0 = 0.9
            expect(result).toBe(0.9);
        });
    });
    describe('Auto-Match Threshold Scenarios', () => {
        it('should identify clear auto-match candidate (≥0.95)', () => {
            const result = calculateOverallConfidence({
                amount: 1.0,
                currency: 1.0,
                business: 1.0,
                date: 0.5,
            });
            // (1.0 × 0.4) + (1.0 × 0.2) + (1.0 × 0.3) + (0.5 × 0.1)
            // = 0.4 + 0.2 + 0.3 + 0.05 = 0.95
            expect(result).toBe(0.95);
            expect(result).toBeGreaterThanOrEqual(0.95);
        });
        it('should identify borderline case (just below threshold)', () => {
            const result = calculateOverallConfidence({
                amount: 0.9,
                currency: 1.0,
                business: 1.0,
                date: 0.9,
            });
            // (0.9 × 0.4) + (1.0 × 0.2) + (1.0 × 0.3) + (0.9 × 0.1)
            // = 0.36 + 0.2 + 0.3 + 0.09 = 0.95
            expect(result).toBe(0.95);
        });
        it('should identify case just above threshold', () => {
            const result = calculateOverallConfidence({
                amount: 1.0,
                currency: 1.0,
                business: 1.0,
                date: 0.6,
            });
            // (1.0 × 0.4) + (1.0 × 0.2) + (1.0 × 0.3) + (0.6 × 0.1)
            // = 0.4 + 0.2 + 0.3 + 0.06 = 0.96
            expect(result).toBe(0.96);
            expect(result).toBeGreaterThan(0.95);
        });
    });
    describe('Decimal Precision', () => {
        it('should round to 2 decimal places', () => {
            const result = calculateOverallConfidence({
                amount: 0.333,
                currency: 0.667,
                business: 0.555,
                date: 0.444,
            });
            // (0.333 × 0.4) + (0.667 × 0.2) + (0.555 × 0.3) + (0.444 × 0.1)
            // = 0.1332 + 0.1334 + 0.1665 + 0.0444 = 0.4775
            expect(result).toBe(0.48);
        });
        it('should handle rounding edge case (0.445 rounds to 0.45)', () => {
            const result = calculateOverallConfidence({
                amount: 0.5,
                currency: 0.5,
                business: 0.5,
                date: 0.0,
            });
            // (0.5 × 0.4) + (0.5 × 0.2) + (0.5 × 0.3) + (0.0 × 0.1)
            // = 0.2 + 0.1 + 0.15 + 0.0 = 0.45
            expect(result).toBe(0.45);
        });
        it('should handle precise calculation without floating point errors', () => {
            const result = calculateOverallConfidence({
                amount: 0.1,
                currency: 0.2,
                business: 0.3,
                date: 0.4,
            });
            // (0.1 × 0.4) + (0.2 × 0.2) + (0.3 × 0.3) + (0.4 × 0.1)
            // = 0.04 + 0.04 + 0.09 + 0.04 = 0.21
            expect(result).toBe(0.21);
        });
    });
    describe('Edge Cases', () => {
        it('should handle all components at 0.5', () => {
            const result = calculateOverallConfidence({
                amount: 0.5,
                currency: 0.5,
                business: 0.5,
                date: 0.5,
            });
            // (0.5 × 0.4) + (0.5 × 0.2) + (0.5 × 0.3) + (0.5 × 0.1)
            // = 0.2 + 0.1 + 0.15 + 0.05 = 0.5
            expect(result).toBe(0.5);
        });
        it('should handle very small non-zero values', () => {
            const result = calculateOverallConfidence({
                amount: 0.01,
                currency: 0.01,
                business: 0.01,
                date: 0.01,
            });
            // (0.01 × 0.4) + (0.01 × 0.2) + (0.01 × 0.3) + (0.01 × 0.1)
            // = 0.004 + 0.002 + 0.003 + 0.001 = 0.01
            expect(result).toBe(0.01);
        });
        it('should handle values very close to 1.0', () => {
            const result = calculateOverallConfidence({
                amount: 0.99,
                currency: 0.99,
                business: 0.99,
                date: 0.99,
            });
            // (0.99 × 0.4) + (0.99 × 0.2) + (0.99 × 0.3) + (0.99 × 0.1)
            // = 0.396 + 0.198 + 0.297 + 0.099 = 0.99
            expect(result).toBe(0.99);
        });
    });
    describe('Validation - Missing Components', () => {
        it('should throw error when amount is null', () => {
            expect(() => calculateOverallConfidence({
                amount: null,
                currency: 1.0,
                business: 1.0,
                date: 1.0,
            })).toThrow('Amount confidence is required');
        });
        it('should throw error when currency is null', () => {
            expect(() => calculateOverallConfidence({
                amount: 1.0,
                currency: null,
                business: 1.0,
                date: 1.0,
            })).toThrow('Currency confidence is required');
        });
        it('should throw error when business is null', () => {
            expect(() => calculateOverallConfidence({
                amount: 1.0,
                currency: 1.0,
                business: null,
                date: 1.0,
            })).toThrow('Business confidence is required');
        });
        it('should throw error when date is null', () => {
            expect(() => calculateOverallConfidence({
                amount: 1.0,
                currency: 1.0,
                business: 1.0,
                date: null,
            })).toThrow('Date confidence is required');
        });
        it('should throw error when amount is undefined', () => {
            expect(() => calculateOverallConfidence({
                amount: undefined,
                currency: 1.0,
                business: 1.0,
                date: 1.0,
            })).toThrow('Amount confidence is required');
        });
        it('should throw error when multiple components are null', () => {
            expect(() => calculateOverallConfidence({
                amount: null,
                currency: null,
                business: 1.0,
                date: 1.0,
            })).toThrow('Amount confidence is required');
        });
    });
    describe('Validation - Out of Range', () => {
        it('should throw error when amount is negative', () => {
            expect(() => calculateOverallConfidence({
                amount: -0.1,
                currency: 1.0,
                business: 1.0,
                date: 1.0,
            })).toThrow('Amount confidence must be between 0.0 and 1.0');
        });
        it('should throw error when amount exceeds 1.0', () => {
            expect(() => calculateOverallConfidence({
                amount: 1.1,
                currency: 1.0,
                business: 1.0,
                date: 1.0,
            })).toThrow('Amount confidence must be between 0.0 and 1.0');
        });
        it('should throw error when currency is negative', () => {
            expect(() => calculateOverallConfidence({
                amount: 1.0,
                currency: -0.5,
                business: 1.0,
                date: 1.0,
            })).toThrow('Currency confidence must be between 0.0 and 1.0');
        });
        it('should throw error when business exceeds 1.0', () => {
            expect(() => calculateOverallConfidence({
                amount: 1.0,
                currency: 1.0,
                business: 2.0,
                date: 1.0,
            })).toThrow('Business confidence must be between 0.0 and 1.0');
        });
        it('should throw error when date is negative', () => {
            expect(() => calculateOverallConfidence({
                amount: 1.0,
                currency: 1.0,
                business: 1.0,
                date: -1.0,
            })).toThrow('Date confidence must be between 0.0 and 1.0');
        });
        it('should throw error with correct component name', () => {
            expect(() => calculateOverallConfidence({
                amount: 1.0,
                currency: 1.0,
                business: 5.0,
                date: 1.0,
            })).toThrow(/Business confidence/);
        });
    });
    describe('Real-World Scenarios', () => {
        it('should handle typical invoice match', () => {
            // Exact amount, currency, business match, 2 days apart
            const result = calculateOverallConfidence({
                amount: 1.0,
                currency: 1.0,
                business: 1.0,
                date: 0.93, // ~2 days difference
            });
            // (1.0 × 0.4) + (1.0 × 0.2) + (1.0 × 0.3) + (0.93 × 0.1) = 0.993
            expect(result).toBe(0.99);
        });
        it('should handle receipt with missing business', () => {
            // Good amount/currency, no business ID, same day
            const result = calculateOverallConfidence({
                amount: 1.0,
                currency: 1.0,
                business: 0.5, // Unknown business
                date: 1.0,
            });
            // (1.0 × 0.4) + (1.0 × 0.2) + (0.5 × 0.3) + (1.0 × 0.1) = 0.85
            expect(result).toBe(0.85);
        });
        it('should handle cross-currency near match', () => {
            // Good amount, no currency match, good business/date
            const result = calculateOverallConfidence({
                amount: 0.9,
                currency: 0.0, // Different currency
                business: 1.0,
                date: 1.0,
            });
            // (0.9 × 0.4) + (0.0 × 0.2) + (1.0 × 0.3) + (1.0 × 0.1) = 0.76
            expect(result).toBe(0.76);
        });
        it('should handle delayed receipt (15 days)', () => {
            // Perfect match except date
            const result = calculateOverallConfidence({
                amount: 1.0,
                currency: 1.0,
                business: 1.0,
                date: 0.5, // 15 days difference
            });
            // (1.0 × 0.4) + (1.0 × 0.2) + (1.0 × 0.3) + (0.5 × 0.1) = 0.95
            expect(result).toBe(0.95);
        });
    });
});
//# sourceMappingURL=overall-confidence.test.js.map