package service import ( "github.com/gochat/gochat/internal/model" ) // RollupMetricData holds the computed count and value for a single rollup metric. type RollupMetricData struct { Count int64 SumValue float64 SumBizHours float64 } // ExpandEventToRollupMetrics maps a raw event metric name to the rollup metrics // it contributes to. This mirrors Chatwoot's EVENT_METRICS registry. // // Chatwoot EVENT_METRICS mapping: // conversation_resolved → resolutions_count (count) + resolution_time (duration) // first_response → first_response (duration) // reply_time → reply_time (duration) // conversation_bot_resolved → bot_resolutions_count (count) // conversation_bot_handoff → bot_handoffs_count (count) func ExpandEventToRollupMetrics(rawMetric model.RollupMetric, count int64, sumValue, sumBizHours float64) map[model.RollupMetric]RollupMetricData { result := map[model.RollupMetric]RollupMetricData{} switch rawMetric { case model.RollupMetric("conversation_resolved"): // Count metric: resolutions_count result[model.MetricResolutionsCount] = RollupMetricData{ Count: count, SumValue: float64(count), SumBizHours: float64(count), } // Duration metric: resolution_time result[model.MetricResolutionTime] = RollupMetricData{ Count: count, SumValue: sumValue, SumBizHours: sumBizHours, } case model.RollupMetric("first_response"): result[model.MetricFirstResponse] = RollupMetricData{ Count: count, SumValue: sumValue, SumBizHours: sumBizHours, } case model.RollupMetric("reply_time"): result[model.MetricReplyTime] = RollupMetricData{ Count: count, SumValue: sumValue, SumBizHours: sumBizHours, } case model.RollupMetric("conversation_bot_resolved"): result[model.MetricBotResolutionsCount] = RollupMetricData{ Count: count, SumValue: float64(count), SumBizHours: float64(count), } case model.RollupMetric("conversation_bot_handoff"): result[model.MetricBotHandoffsCount] = RollupMetricData{ Count: count, SumValue: float64(count), SumBizHours: float64(count), } default: // Unknown metric — still record it as a direct rollup result[rawMetric] = RollupMetricData{ Count: count, SumValue: sumValue, SumBizHours: sumBizHours, } } return result } // ReportMetricDefinition describes how a report metric is sourced and aggregated. // Mirrors Chatwoot REPORT_METRICS registry. type ReportMetricDefinition struct { RawEventName string // The raw ReportingEvent name that feeds this metric RollupMetric model.RollupMetric // The rollup metric column to read from AggregateType string // "count", "average", "sum" } // ReportMetricsRegistry maps summary response keys to metric definitions. // Mirrors Chatwoot MetricRegistry::REPORT_METRICS. var ReportMetricsRegistry = map[string]ReportMetricDefinition{ "conversations_count": {AggregateType: "count"}, "incoming_messages_count": {AggregateType: "count"}, "outgoing_messages_count": {AggregateType: "count"}, "avg_first_response_time": {RawEventName: "first_response", RollupMetric: model.MetricFirstResponse, AggregateType: "average"}, "avg_resolution_time": {RawEventName: "conversation_resolved", RollupMetric: model.MetricResolutionTime, AggregateType: "average"}, "reply_time": {RawEventName: "reply_time", RollupMetric: model.MetricReplyTime, AggregateType: "average"}, "resolutions_count": {RawEventName: "conversation_resolved", RollupMetric: model.MetricResolutionsCount, AggregateType: "count"}, "bot_resolutions_count": {RawEventName: "conversation_bot_resolved", RollupMetric: model.MetricBotResolutionsCount, AggregateType: "count"}, "bot_handoffs_count": {RawEventName: "conversation_bot_handoff", RollupMetric: model.MetricBotHandoffsCount, AggregateType: "count"}, "avg_first_response_time_business_hours": {RawEventName: "first_response", RollupMetric: model.MetricFirstResponse, AggregateType: "average_biz"}, "avg_resolution_time_business_hours": {RawEventName: "conversation_resolved", RollupMetric: model.MetricResolutionTime, AggregateType: "average_biz"}, "reply_time_business_hours": {RawEventName: "reply_time", RollupMetric: model.MetricReplyTime, AggregateType: "average_biz"}, } // SummaryMetricsMap maps Chatwoot summary API response keys to their // underlying rollup metric names. Mirrors MetricRegistry::SUMMARY_METRICS. var SummaryMetricsMap = map[string]model.RollupMetric{ "resolutions_count": model.MetricResolutionsCount, "avg_resolution_time": model.MetricResolutionTime, "avg_first_response_time": model.MetricFirstResponse, "reply_time": model.MetricReplyTime, } // GetReportMetricDefinition returns the metric definition for a given report key. func GetReportMetricDefinition(key string) *ReportMetricDefinition { if def, ok := ReportMetricsRegistry[key]; ok { return &def } return nil }