import type { Prisma } from "@capakraken/db";
import { EstimateVersionStatus, type CreateEstimateInput } from "@capakraken/shared";
import {
  buildProjectSnapshot,
  ESTIMATE_DETAIL_INCLUDE,
  type EstimateDbClient,
  type EstimateWithDetails,
} from "./shared.js";

export async function createEstimate(
  db: EstimateDbClient,
  input: CreateEstimateInput,
): Promise<EstimateWithDetails> {
  const projectSnapshot = await buildProjectSnapshot(db, input.projectId);

  const estimate = await db.estimate.create({
    data: {
      ...(input.projectId !== undefined ? { projectId: input.projectId } : {}),
      name: input.name,
      ...(input.opportunityId !== undefined
        ? { opportunityId: input.opportunityId }
        : {}),
      baseCurrency: input.baseCurrency,
      status: input.status,
      latestVersionNumber: 1,
      versions: {
        create: {
          versionNumber: 1,
          ...(input.versionLabel !== undefined ? { label: input.versionLabel } : {}),
          status: EstimateVersionStatus.WORKING,
          ...(input.versionNotes !== undefined
            ? { notes: input.versionNotes }
            : {}),
          projectSnapshot,
          assumptions: {
            create: input.assumptions.map((assumption) => ({
              category: assumption.category,
              key: assumption.key,
              label: assumption.label,
              valueType: assumption.valueType,
              value: assumption.value as Prisma.InputJsonValue,
              sortOrder: assumption.sortOrder,
              ...(assumption.notes !== undefined ? { notes: assumption.notes } : {}),
            })),
          },
          scopeItems: {
            create: input.scopeItems.map((scopeItem) => ({
              sequenceNo: scopeItem.sequenceNo,
              scopeType: scopeItem.scopeType,
              ...(scopeItem.packageCode !== undefined
                ? { packageCode: scopeItem.packageCode }
                : {}),
              name: scopeItem.name,
              ...(scopeItem.description !== undefined
                ? { description: scopeItem.description }
                : {}),
              ...(scopeItem.scene !== undefined ? { scene: scopeItem.scene } : {}),
              ...(scopeItem.page !== undefined ? { page: scopeItem.page } : {}),
              ...(scopeItem.location !== undefined
                ? { location: scopeItem.location }
                : {}),
              ...(scopeItem.assumptionCategory !== undefined
                ? { assumptionCategory: scopeItem.assumptionCategory }
                : {}),
              technicalSpec: scopeItem.technicalSpec as Prisma.InputJsonValue,
              ...(scopeItem.frameCount !== undefined
                ? { frameCount: scopeItem.frameCount }
                : {}),
              ...(scopeItem.itemCount !== undefined
                ? { itemCount: scopeItem.itemCount }
                : {}),
              ...(scopeItem.unitMode !== undefined
                ? { unitMode: scopeItem.unitMode }
                : {}),
              ...(scopeItem.internalComments !== undefined
                ? { internalComments: scopeItem.internalComments }
                : {}),
              ...(scopeItem.externalComments !== undefined
                ? { externalComments: scopeItem.externalComments }
                : {}),
              sortOrder: scopeItem.sortOrder,
              metadata: scopeItem.metadata as Prisma.InputJsonValue,
            })),
          },
          demandLines: {
            create: input.demandLines.map((line) => ({
              ...(line.scopeItemId !== undefined ? { scopeItemId: line.scopeItemId } : {}),
              ...(line.roleId !== undefined ? { roleId: line.roleId } : {}),
              ...(line.resourceId !== undefined
                ? { resourceId: line.resourceId }
                : {}),
              lineType: line.lineType,
              name: line.name,
              ...(line.chapter !== undefined ? { chapter: line.chapter } : {}),
              hours: line.hours,
              ...(line.days !== undefined ? { days: line.days } : {}),
              ...(line.fte !== undefined ? { fte: line.fte } : {}),
              ...(line.rateSource !== undefined
                ? { rateSource: line.rateSource }
                : {}),
              costRateCents: line.costRateCents,
              billRateCents: line.billRateCents,
              currency: line.currency,
              costTotalCents: line.costTotalCents,
              priceTotalCents: line.priceTotalCents,
              monthlySpread: line.monthlySpread as Prisma.InputJsonValue,
              staffingAttributes: line.staffingAttributes as Prisma.InputJsonValue,
              metadata: line.metadata as Prisma.InputJsonValue,
            })),
          },
          resourceSnapshots: {
            create: input.resourceSnapshots.map((snapshot) => ({
              ...(snapshot.resourceId !== undefined
                ? { resourceId: snapshot.resourceId }
                : {}),
              ...(snapshot.sourceEid !== undefined
                ? { sourceEid: snapshot.sourceEid }
                : {}),
              displayName: snapshot.displayName,
              ...(snapshot.chapter !== undefined ? { chapter: snapshot.chapter } : {}),
              ...(snapshot.roleId !== undefined ? { roleId: snapshot.roleId } : {}),
              currency: snapshot.currency,
              lcrCents: snapshot.lcrCents,
              ucrCents: snapshot.ucrCents,
              ...(snapshot.fte !== undefined ? { fte: snapshot.fte } : {}),
              ...(snapshot.location !== undefined
                ? { location: snapshot.location }
                : {}),
              ...(snapshot.country !== undefined ? { country: snapshot.country } : {}),
              ...(snapshot.level !== undefined ? { level: snapshot.level } : {}),
              ...(snapshot.workType !== undefined
                ? { workType: snapshot.workType }
                : {}),
              attributes: snapshot.attributes as Prisma.InputJsonValue,
            })),
          },
          metrics: {
            create: input.metrics.map((metric) => ({
              key: metric.key,
              label: metric.label,
              ...(metric.metricGroup !== undefined
                ? { metricGroup: metric.metricGroup }
                : {}),
              valueDecimal: metric.valueDecimal,
              ...(metric.valueCents !== undefined
                ? { valueCents: metric.valueCents }
                : {}),
              ...(metric.currency !== undefined ? { currency: metric.currency } : {}),
              metadata: metric.metadata as Prisma.InputJsonValue,
            })),
          },
        },
      },
    },
    include: ESTIMATE_DETAIL_INCLUDE,
  });

  return estimate;
}
