import { buildSplitAllocationReadModel } from "@capakraken/application";
import type { PrismaClient } from "@capakraken/db";
import { z } from "zod";
import { TimelineWindowFiltersSchema } from "./timeline-read-schema-support.js";
import { loadTimelineEntryRecords } from "./timeline-entry-query-support.js";
export {
  buildSelfServiceTimelineInput,
  buildTimelineEntriesDetailInput,
  createTimelineDateRange,
  createTimelineFilters,
} from "./timeline-filter-support.js";

export type ShiftDbClient = Pick<
  PrismaClient,
  "project" | "demandRequirement" | "assignment"
>;

export type TimelineEntriesDbClient = Pick<
  PrismaClient,
  "demandRequirement" | "assignment" | "resource" | "project" | "holidayCalendar" | "country" | "metroCity"
>;

export type TimelineEntriesFilters = {
  startDate: Date;
  endDate: Date;
  resourceIds?: string[] | undefined;
  projectIds?: string[] | undefined;
  clientIds?: string[] | undefined;
  chapters?: string[] | undefined;
  eids?: string[] | undefined;
  countryCodes?: string[] | undefined;
};

type TimelineWindowFiltersInput = z.infer<typeof TimelineWindowFiltersSchema>;

export function getAssignmentResourceIds(
  readModel: ReturnType<typeof buildSplitAllocationReadModel>,
): string[] {
  return [
    ...new Set(
      readModel.assignments
        .map((assignment) => assignment.resourceId)
        .filter((resourceId): resourceId is string => resourceId !== null),
    ),
  ];
}

export function fmtDate(value: Date | null | undefined): string | null {
  if (!value) {
    return null;
  }
  return value.toISOString().slice(0, 10);
}

export function createEmptyTimelineEntriesView() {
  return buildSplitAllocationReadModel({
    demandRequirements: [],
    assignments: [],
  });
}

export function rangesOverlap(
  leftStart: Date,
  leftEnd: Date,
  rightStart: Date,
  rightEnd: Date,
): boolean {
  return leftStart <= rightEnd && rightStart <= leftEnd;
}

export function toDate(value: Date | string): Date {
  return value instanceof Date ? value : new Date(value);
}

export async function loadTimelineEntriesReadModel(
  db: TimelineEntriesDbClient,
  input: TimelineEntriesFilters,
) {
  const { demandRequirements, assignments } = await loadTimelineEntryRecords(db, input);
  return buildSplitAllocationReadModel({ demandRequirements, assignments });
}
