import { EpochMillis, maybe, SizeInBytes } from "@upload-io/upload-shared-iso/common/model/Primitives";
import { EpochMillisUnboxed, FileSizeUnboxed } from "@upload-io/upload-shared-iso/common/model/UnboxedPrimitives";

export interface StorageStatisticsSegmentDto {
  firstFileCreated: EpochMillis | undefined;
  lastFileCreated: EpochMillis | undefined;
  totalFileCount: number;
  totalFileSize: SizeInBytes;
}

export interface StorageStatisticsSegmentUnboxedDto {
  firstFileCreated: EpochMillisUnboxed | null;
  lastFileCreated: EpochMillisUnboxed | null;
  totalFileCount: number;
  totalFileSize: FileSizeUnboxed;
}

function reduceOpt(
  left: number | undefined,
  right: number | undefined,
  reduce: (l: number, r: number) => number
): number | undefined {
  if (left === undefined) {
    return right;
  }
  if (right === undefined) {
    return left;
  }
  return reduce(left, right);
}

export namespace StorageStatisticsSegmentDto {
  export const empty: StorageStatisticsSegmentDto = {
    firstFileCreated: undefined,
    lastFileCreated: undefined,
    totalFileCount: 0,
    totalFileSize: SizeInBytes(0)
  };

  export function combine(
    left: StorageStatisticsSegmentDto,
    right: StorageStatisticsSegmentDto
  ): StorageStatisticsSegmentDto {
    return {
      firstFileCreated: maybe(EpochMillis, reduceOpt(left.firstFileCreated, right.firstFileCreated, Math.min)),
      lastFileCreated: maybe(EpochMillis, reduceOpt(left.lastFileCreated, right.lastFileCreated, Math.max)),
      totalFileCount: left.totalFileCount + right.totalFileCount,
      totalFileSize: SizeInBytes(left.totalFileSize.valueOf() + right.totalFileSize.valueOf())
    };
  }
}
