import type { Prisma } from "@capakraken/db";
import {
  CreateRateCardLineSchema,
  CreateRateCardSchema,
  UpdateRateCardLineSchema,
  UpdateRateCardSchema,
} from "@capakraken/shared";
import { z } from "zod";

type RateCardListInput = {
  isActive?: boolean | undefined;
  search?: string | undefined;
  clientId?: string | undefined;
  effectiveAt?: Date | undefined;
};

type CreateRateCardInput = z.infer<typeof CreateRateCardSchema>;
type CreateRateCardLineInput = z.infer<typeof CreateRateCardLineSchema>;
type UpdateRateCardInput = z.infer<typeof UpdateRateCardSchema>;
type UpdateRateCardLineInput = z.infer<typeof UpdateRateCardLineSchema>;

export const rateCardSummaryInclude = {
  _count: { select: { lines: true } },
  client: { select: { id: true, name: true, code: true } },
} as const;

export const rateCardLineOrderBy: Prisma.RateCardLineOrderByWithRelationInput[] = [
  { chapter: "asc" },
  { seniority: "asc" },
  { createdAt: "asc" },
];

export const rateCardDetailInclude = {
  client: { select: { id: true, name: true, code: true } },
  lines: {
    select: {
      id: true,
      rateCardId: true,
      roleId: true,
      chapter: true,
      seniority: true,
      location: true,
      workType: true,
      serviceGroup: true,
      costRateCents: true,
      billRateCents: true,
      machineRateCents: true,
      attributes: true,
      role: { select: { id: true, name: true } },
    },
    orderBy: rateCardLineOrderBy,
  },
} as const;

export const rateCardCreateInclude = {
  lines: {
    select: rateCardDetailInclude.lines.select,
  },
} as const;

function buildRateCardLineCoreData(
  line: CreateRateCardLineInput,
) {
  return {
    ...(line.roleId !== undefined ? { roleId: line.roleId } : {}),
    ...(line.chapter !== undefined ? { chapter: line.chapter } : {}),
    ...(line.location !== undefined ? { location: line.location } : {}),
    ...(line.seniority !== undefined ? { seniority: line.seniority } : {}),
    ...(line.workType !== undefined ? { workType: line.workType } : {}),
    ...(line.serviceGroup !== undefined ? { serviceGroup: line.serviceGroup } : {}),
    costRateCents: line.costRateCents,
    ...(line.billRateCents !== undefined ? { billRateCents: line.billRateCents } : {}),
    ...(line.machineRateCents !== undefined ? { machineRateCents: line.machineRateCents } : {}),
    attributes: line.attributes as Prisma.InputJsonValue,
  };
}

export function buildRateCardListWhere(
  input?: RateCardListInput,
): Prisma.RateCardWhereInput {
  return {
    ...(input?.isActive !== undefined ? { isActive: input.isActive } : {}),
    ...(input?.clientId !== undefined ? { clientId: input.clientId } : {}),
    ...(input?.search
      ? { name: { contains: input.search, mode: "insensitive" } }
      : {}),
    ...(input?.effectiveAt
      ? {
          OR: [
            { effectiveFrom: null },
            { effectiveFrom: { lte: input.effectiveAt } },
          ],
          AND: [
            {
              OR: [
                { effectiveTo: null },
                { effectiveTo: { gte: input.effectiveAt } },
              ],
            },
          ],
        }
      : {}),
  };
}

export function buildRateCardCreateData(
  input: CreateRateCardInput,
): Prisma.RateCardUncheckedCreateInput {
  const { lines, ...cardData } = input;

  return {
    name: cardData.name,
    currency: cardData.currency,
    ...(cardData.effectiveFrom !== undefined ? { effectiveFrom: cardData.effectiveFrom } : {}),
    ...(cardData.effectiveTo !== undefined ? { effectiveTo: cardData.effectiveTo } : {}),
    ...(cardData.source !== undefined ? { source: cardData.source } : {}),
    ...(cardData.clientId !== undefined ? { clientId: cardData.clientId } : {}),
    lines: {
      create: lines.map((line) => buildRateCardNestedLineCreateData(line)),
    },
  } as Prisma.RateCardUncheckedCreateInput;
}

export function buildRateCardUpdateData(
  input: UpdateRateCardInput,
): Prisma.RateCardUncheckedUpdateInput {
  return {
    ...(input.name !== undefined ? { name: input.name } : {}),
    ...(input.currency !== undefined ? { currency: input.currency } : {}),
    ...(input.effectiveFrom !== undefined ? { effectiveFrom: input.effectiveFrom } : {}),
    ...(input.effectiveTo !== undefined ? { effectiveTo: input.effectiveTo } : {}),
    ...(input.source !== undefined ? { source: input.source } : {}),
    ...(input.clientId !== undefined ? { clientId: input.clientId } : {}),
    ...(input.isActive !== undefined ? { isActive: input.isActive } : {}),
  };
}

export function buildRateCardNestedLineCreateData(
  line: CreateRateCardLineInput,
): Prisma.RateCardLineUncheckedCreateWithoutRateCardInput {
  return buildRateCardLineCoreData(line) as Prisma.RateCardLineUncheckedCreateWithoutRateCardInput;
}

export function buildRateCardLineCreateData(
  rateCardId: string,
  line: CreateRateCardLineInput,
): Prisma.RateCardLineUncheckedCreateInput {
  return {
    rateCardId,
    ...buildRateCardLineCoreData(line),
  } as Prisma.RateCardLineUncheckedCreateInput;
}

export function buildRateCardLineUpdateData(
  input: UpdateRateCardLineInput,
): Prisma.RateCardLineUpdateInput {
  const updateData: Prisma.RateCardLineUpdateInput = {};

  if (input.roleId !== undefined) {
    updateData.role = input.roleId
      ? { connect: { id: input.roleId } }
      : { disconnect: true };
  }
  if (input.chapter !== undefined) updateData.chapter = input.chapter;
  if (input.location !== undefined) updateData.location = input.location;
  if (input.seniority !== undefined) updateData.seniority = input.seniority;
  if (input.workType !== undefined) updateData.workType = input.workType;
  if (input.serviceGroup !== undefined) updateData.serviceGroup = input.serviceGroup;
  if (input.costRateCents !== undefined) updateData.costRateCents = input.costRateCents;
  if (input.billRateCents !== undefined) updateData.billRateCents = input.billRateCents;
  if (input.machineRateCents !== undefined) updateData.machineRateCents = input.machineRateCents;
  if (input.attributes !== undefined) updateData.attributes = input.attributes as Prisma.InputJsonValue;

  return updateData;
}

export function buildRateCardCreateAuditAfter(
  input: Pick<CreateRateCardInput, "name" | "currency" | "lines">,
) {
  return {
    name: input.name,
    currency: input.currency,
    lineCount: input.lines.length,
  };
}

export function buildRateCardLineCreateAuditAfter(
  input: {
    rateCardId: string;
    line: Pick<CreateRateCardLineInput, "costRateCents" | "billRateCents" | "chapter">;
  },
) {
  return {
    rateCardId: input.rateCardId,
    costRateCents: input.line.costRateCents,
    billRateCents: input.line.billRateCents,
    chapter: input.line.chapter ?? null,
  };
}

export function buildRateCardReplaceLinesAuditAfter(
  replacedLineCount: number,
) {
  return { replacedLineCount };
}
