import type { AdminTask, DurationExpression, EntitlementDecision, FactRef, GrantPaidLeaveOptions, MoneyAmount, PayDecision, PayFixedAmountOptions, PayPercentOfPayOptions, PercentOfPay, PolicyBuilder, PolicyBuilderResult, PolicyCondition, RequireKnownOptions, RequirementDecision, TopUpToOptions, WageReplacementRef, } from './types'; export class CompanyPolicyBuilder implements PolicyBuilder { private readonly conditions: PolicyCondition[] = []; private readonly requiredEvidence: PolicyBuilderResult['requiredEvidence'] = []; private entitlementDecision: EntitlementDecision | undefined; private payDecision: PayDecision = { type: 'NO_COMPANY_PAY' }; private readonly requirementDecisions: RequirementDecision[] = []; private jobProtectionDecision: PolicyBuilderResult['jobProtection'] = 'UNCHANGED'; eligibleWhen(condition: PolicyCondition): PolicyBuilder { this.conditions.push(condition); return this; } requireKnown(_fact: FactRef | WageReplacementRef, options: RequireKnownOptions): PolicyBuilder { this.requiredEvidence.push({ key: options.evidenceKey, ...(options.message === undefined ? {} : { message: options.message }), }); return this; } grantPaidLeave(duration: DurationExpression, options: GrantPaidLeaveOptions = {}): PolicyBuilder { this.entitlementDecision = { type: 'PAID_LEAVE', duration, ...(options.leaveType === undefined ? {} : { leaveType: options.leaveType }), }; return this; } noCompanyPay(): PolicyBuilder { this.payDecision = { type: 'NO_COMPANY_PAY' }; return this; } payFixedAmount(amount: MoneyAmount, options: PayFixedAmountOptions): PolicyBuilder { this.payDecision = { type: 'FIXED_AMOUNT', amount, duration: options.duration, earningType: options.earningType, }; return this; } payPercentOfPay(target: PercentOfPay, options: PayPercentOfPayOptions): PolicyBuilder { this.payDecision = { type: 'PERCENT_OF_PAY', target, base: options.base, duration: options.duration, earningType: options.earningType, }; return this; } topUpTo(target: PercentOfPay, options: TopUpToOptions): PolicyBuilder { this.payDecision = { type: 'MAKE_WHOLE_TOPUP', target, base: options.base, offsetBy: options.offsetBy, earningType: options.earningType, }; return this; } requireAdminTask(key: AdminTask | string): PolicyBuilder { this.requirementDecisions.push({ type: 'ADMIN_TASK', key, blocksPayment: false, }); return this; } doesNotProvideJobProtection(): PolicyBuilder { this.jobProtectionDecision = 'NONE'; return this; } build(): PolicyBuilderResult { return { conditions: [...this.conditions], requiredEvidence: [...this.requiredEvidence], ...(this.entitlementDecision === undefined ? {} : { entitlement: this.entitlementDecision }), pay: this.payDecision, requirements: [...this.requirementDecisions], jobProtection: this.jobProtectionDecision, diagnostics: [], }; } }