import { daysBetween } from '../../common/dates'; import type { SuggestionEvidence } from '../suggestion.types'; import { formatDayDe, type SuggestionTextRegister, type SuggestionTextTemplate, } from '../suggestion-texts'; const MAX_PRODUCT_LENGTH = 40; const SEGMENT_PHRASES: Readonly> = { FRUEHJAHR: 'Im Frühjahr', SCHWARMZEIT: 'In der Schwarmzeit', SOMMER: 'Im Sommer', SPAETSOMMER: 'Im Spätsommer', HERBST: 'Im Herbst', }; function text(evidence: SuggestionEvidence, key: string): string | null { const value = evidence[key]; return typeof value === 'string' ? value : null; } function count(evidence: SuggestionEvidence, key: string): number | null { const value = evidence[key]; return typeof value === 'number' ? value : null; } /** 'vor 8 Tagen', 'vor 1 Tag', 'heute'. */ function agoDe(from: string, today: string): string { const days = Math.max(0, daysBetween(from, today)); if (days === 0) { return 'heute'; } return `vor ${days} ${days === 1 ? 'Tag' : 'Tagen'}`; } function lastInspectionReason( evidence: SuggestionEvidence, today: string, ): string { const last = text(evidence, 'lastInspectedOn'); return last === null ? 'Noch keine Durchsicht erfasst.' : `Letzte Durchsicht ${agoDe(last, today)}.`; } function intervalReason(evidence: SuggestionEvidence): string[] { const phrase = SEGMENT_PHRASES[text(evidence, 'segment') ?? '']; const days = count(evidence, 'intervalDays'); return phrase !== undefined && days !== null ? [`${phrase} alle ${days} Tage.`] : []; } const INSPECTION_DUE: SuggestionTextTemplate = { ruleKey: 'INSPECTION_INTERVAL', example: { colonyId: 'c1', inspectionId: 'i1', lastInspectedOn: '2026-05-04', dueOn: '2026-05-11', intervalDays: 7, segment: 'SCHWARMZEIT', }, render: (evidence, _lookup, today) => ({ title: 'Durchsicht', reasons: [ lastInspectionReason(evidence, today), ...intervalReason(evidence), ], }), }; const INSPECTION_FIRST_OF_YEAR: SuggestionTextTemplate = { ruleKey: 'INSPECTION_INTERVAL', example: { colonyId: 'c1', inspectionId: 'i1', lastInspectedOn: '2025-09-20', dueOn: '2026-03-20', intervalDays: 14, segment: 'FRUEHJAHR', }, render: (evidence) => { const last = text(evidence, 'lastInspectedOn'); return { title: 'Erste Durchsicht im Jahr', reasons: [ 'Die Saison hat begonnen.', last === null ? 'Noch keine Durchsicht erfasst.' : `Letzte Durchsicht am ${formatDayDe(last, true)}.`, ], }; }, }; const VARROA_MEASURE_DUE: SuggestionTextTemplate = { ruleKey: 'SEASON_AUTOPILOT', example: { colonyId: 'c1', measurementId: 'm1', lastMeasuredOn: '2026-05-06', dueOn: '2026-06-03', intervalDays: 28, }, render: (evidence, _lookup, today) => { const last = text(evidence, 'lastMeasuredOn'); const days = count(evidence, 'intervalDays'); return { title: 'Varroa messen', reasons: [ last === null ? 'Noch keine Messung erfasst.' : `Letzte Messung ${agoDe(last, today)}.`, ...(days === null ? [] : [`Alle ${days} Tage messen.`]), ], }; }, }; const VARROA_WINTER_MEASURE: SuggestionTextTemplate = { ruleKey: 'SEASON_AUTOPILOT', example: { colonyId: 'c1', measurementId: 'm1', lastMeasuredOn: '2026-09-01', dueOn: '2026-11-15', intervalDays: 28, }, render: () => ({ title: 'Varroa messen', reasons: ['Vor der Winterbehandlung den Milbenfall messen.'], }), }; const VARROA_RECHECK_DUE: SuggestionTextTemplate = { ruleKey: 'SEASON_AUTOPILOT', example: { colonyId: 'c1', treatmentId: 't1', endedOn: '2026-08-02', recheckOn: '2026-08-16', }, render: (evidence, lookup) => { const treatmentId = text(evidence, 'treatmentId'); const product = (treatmentId === null ? null : lookup.treatmentProduct(treatmentId)) ?? 'Behandlung'; const name = product.slice(0, MAX_PRODUCT_LENGTH); const ended = text(evidence, 'endedOn'); const recheck = text(evidence, 'recheckOn'); return { title: 'Behandlungserfolg messen', reasons: [ ended === null ? `Behandlung mit ${name} beendet.` : `Behandlung mit ${name} endete am ${formatDayDe(ended)}`, ...(recheck === null ? [] : [`Nachkontrolle ab ${formatDayDe(recheck)}`]), ], }; }, }; /** Texts of the season autopilot suggestions, by reason code. */ export const AUTOPILOT_TEXTS: SuggestionTextRegister = { INSPECTION_DUE, INSPECTION_FIRST_OF_YEAR, VARROA_MEASURE_DUE, VARROA_WINTER_MEASURE, VARROA_RECHECK_DUE, };