import {
  CountMap,
  Evaluation,
  Event,
  Exposure,
  Expression,
  Logs,
  Message,
} from "../types";

export function getExpressionEvaluationCountLogs(expression: Expression): Logs {
  if (expression.isTransient) {
    return {};
  }
  return {
    evaluations: { [expression.id]: 1 },
  };
}

export function getEventLogs(event: Event): Logs {
  return { eventList: [event] };
}

export function getExposureLogs(exposure: Exposure): Logs {
  return { exposureList: [exposure] };
}

export function mergeLogs(...logs: (Logs | undefined)[]): Logs {
  const filteredLogs = logs.filter(Boolean) as Logs[];

  if (filteredLogs.length === 0) {
    return {};
  }
  if (filteredLogs.length === 1) {
    return filteredLogs[0];
  }

  const messageList: Message[] = filteredLogs.flatMap(
    (b) => b.messageList ?? []
  );
  const eventList: Event[] = filteredLogs
    .flatMap((b) => b.eventList ?? [])
    .concat(
      filteredLogs.flatMap((b) =>
        b.events
          ? Object.entries(b.events).flatMap(([eventJson, count]) =>
              new Array(count).fill(JSON.parse(eventJson) as Event)
            )
          : []
      )
    );
  const exposureList: Exposure[] = filteredLogs
    .flatMap((b) => b.exposureList ?? [])
    .concat(
      filteredLogs.flatMap((b) =>
        b.exposures
          ? Object.entries(b.exposures).flatMap(([exposureJson, count]) =>
              new Array(count).fill(JSON.parse(exposureJson) as Exposure)
            )
          : []
      )
    );
  const evaluationList: Evaluation[] = filteredLogs.flatMap(
    (b) => b.evaluationList ?? []
  );
  const evaluations: CountMap = filteredLogs.reduce<CountMap>((acc, b) => {
    if (b.evaluations) {
      Object.entries(b.evaluations).forEach(([expressionId, count]) => {
        acc[expressionId] = (acc[expressionId] || 0) + count;
      });
    }
    return acc;
  }, {});

  return {
    ...(messageList.length > 0 ? { messageList } : {}),
    ...(eventList.length > 0 ? { eventList } : {}),
    ...(exposureList.length > 0 ? { exposureList } : {}),
    ...(evaluationList.length > 0 ? { evaluationList } : {}),
    ...(Object.keys(evaluations).length > 0 ? { evaluations } : {}),
  };
}
