import {
  approveEstimateVersion,
  createEstimate,
  createEstimateExport,
  createEstimateRevision,
  submitEstimateVersion,
  updateEstimateDraft,
} from "../../packages/application/src/index.js";
import { PrismaClient } from "../../packages/db/src/index.js";
import { loadWorkspaceEnv } from "../../packages/db/src/load-workspace-env.js";
import { EstimateExportFormat } from "../../packages/shared/src/index.js";

loadWorkspaceEnv();

const prisma = new PrismaClient();

async function main() {
  const created = await createEstimate(prisma, {
    name: "Codex Smoke Estimate",
    baseCurrency: "EUR",
    assumptions: [
      {
        category: "commercial",
        key: "delivery_model",
        label: "Delivery Model",
        valueType: "string",
        value: "hybrid",
        sortOrder: 0,
      },
    ],
    scopeItems: [
      {
        sequenceNo: 1,
        scopeType: "SHOT",
        name: "Smoke Scope",
        technicalSpec: {},
        sortOrder: 0,
        metadata: {},
      },
    ],
    demandLines: [
      {
        lineType: "LABOR",
        name: "Senior Comp",
        hours: 40,
        costRateCents: 5000,
        billRateCents: 9000,
        costTotalCents: 200000,
        priceTotalCents: 360000,
        currency: "EUR",
        monthlySpread: {},
        staffingAttributes: {},
        metadata: {},
      },
    ],
    resourceSnapshots: [],
    metrics: [
      {
        key: "total_hours",
        label: "Total Hours",
        metricGroup: "summary",
        valueDecimal: 40,
        metadata: {},
      },
      {
        key: "total_cost",
        label: "Total Cost",
        metricGroup: "summary",
        valueDecimal: 2000,
        valueCents: 200000,
        currency: "EUR",
        metadata: {},
      },
      {
        key: "total_price",
        label: "Total Price",
        metricGroup: "summary",
        valueDecimal: 3600,
        valueCents: 360000,
        currency: "EUR",
        metadata: {},
      },
      {
        key: "margin",
        label: "Margin",
        metricGroup: "summary",
        valueDecimal: 1600,
        valueCents: 160000,
        currency: "EUR",
        metadata: {},
      },
      {
        key: "margin_percent",
        label: "Margin %",
        metricGroup: "summary",
        valueDecimal: 44.4444,
        metadata: {},
      },
    ],
  });

  try {
    const workingVersion = created.versions[0];

    const updated = await updateEstimateDraft(prisma, {
      id: created.id,
      name: "Codex Smoke Estimate Updated",
      baseCurrency: "EUR",
      versionLabel: "Working Draft",
      versionNotes: "updated by smoke test",
      assumptions: [
        {
          id: workingVersion.assumptions[0]?.id,
          category: "commercial",
          key: "delivery_model",
          label: "Delivery Model",
          valueType: "string",
          value: "onsite",
          sortOrder: 0,
        },
      ],
      scopeItems: workingVersion.scopeItems.map((item, index) => ({
        id: item.id,
        sequenceNo: item.sequenceNo,
        scopeType: item.scopeType,
        ...(item.description ? { description: item.description } : {}),
        name: item.name,
        technicalSpec: {},
        sortOrder: index,
        metadata: {},
      })),
      demandLines: workingVersion.demandLines.map((line) => ({
        id: line.id,
        ...(line.scopeItemId ? { scopeItemId: line.scopeItemId } : {}),
        ...(line.roleId ? { roleId: line.roleId } : {}),
        ...(line.resourceId ? { resourceId: line.resourceId } : {}),
        lineType: line.lineType,
        name: line.name,
        hours: 48,
        costRateCents: line.costRateCents,
        billRateCents: line.billRateCents,
        costTotalCents: 240000,
        priceTotalCents: 432000,
        currency: line.currency,
        monthlySpread: {},
        staffingAttributes: {},
        metadata: {},
      })),
      resourceSnapshots: workingVersion.resourceSnapshots.map((snapshot) => ({
        id: snapshot.id,
        ...(snapshot.resourceId ? { resourceId: snapshot.resourceId } : {}),
        ...(snapshot.sourceEid ? { sourceEid: snapshot.sourceEid } : {}),
        displayName: snapshot.displayName,
        ...(snapshot.chapter ? { chapter: snapshot.chapter } : {}),
        ...(snapshot.roleId ? { roleId: snapshot.roleId } : {}),
        currency: snapshot.currency,
        lcrCents: snapshot.lcrCents,
        ucrCents: snapshot.ucrCents,
        ...(snapshot.fte != null ? { fte: snapshot.fte } : {}),
        ...(snapshot.location ? { location: snapshot.location } : {}),
        ...(snapshot.country ? { country: snapshot.country } : {}),
        ...(snapshot.level ? { level: snapshot.level } : {}),
        ...(snapshot.workType ? { workType: snapshot.workType } : {}),
        attributes:
          typeof snapshot.attributes === "object" &&
          snapshot.attributes !== null &&
          !Array.isArray(snapshot.attributes)
            ? snapshot.attributes
            : {},
      })),
      metrics: [
        {
          key: "total_hours",
          label: "Total Hours",
          metricGroup: "summary",
          valueDecimal: 48,
          metadata: {},
        },
        {
          key: "total_cost",
          label: "Total Cost",
          metricGroup: "summary",
          valueDecimal: 2400,
          valueCents: 240000,
          currency: "EUR",
          metadata: {},
        },
        {
          key: "total_price",
          label: "Total Price",
          metricGroup: "summary",
          valueDecimal: 4320,
          valueCents: 432000,
          currency: "EUR",
          metadata: {},
        },
        {
          key: "margin",
          label: "Margin",
          metricGroup: "summary",
          valueDecimal: 1920,
          valueCents: 192000,
          currency: "EUR",
          metadata: {},
        },
        {
          key: "margin_percent",
          label: "Margin %",
          metricGroup: "summary",
          valueDecimal: 44.4444,
          metadata: {},
        },
      ],
    });

    const submitted = await submitEstimateVersion(prisma, {
      estimateId: created.id,
    });

    const approved = await approveEstimateVersion(prisma, {
      estimateId: created.id,
    });

    const revised = await createEstimateRevision(prisma, {
      estimateId: created.id,
      sourceVersionId:
        approved.versions.find((version) => version.status === "APPROVED")?.id ??
        approved.versions[0]?.id,
    });

    const exported = await createEstimateExport(prisma, {
      estimateId: created.id,
      versionId: revised.versions.find((version) => version.status === "WORKING")?.id,
      format: EstimateExportFormat.JSON,
    });

    const refreshed = await prisma.estimate.findUnique({
      where: { id: created.id },
      include: {
        versions: {
          include: {
            assumptions: true,
            demandLines: true,
            metrics: true,
            exports: true,
          },
          orderBy: { versionNumber: "desc" },
        },
      },
    });

    console.log(
      JSON.stringify({
        createdId: created.id,
        updatedName: updated.name,
        versionLabel: updated.versions[0]?.label ?? null,
        assumptionValue: refreshed?.versions[0]?.assumptions[0]?.value ?? null,
        updatedHours: refreshed?.versions[0]?.demandLines[0]?.hours ?? null,
        metricKeys: refreshed?.versions[0]?.metrics.map((metric) => metric.key) ?? [],
        submittedStatus:
          submitted.versions.find((version) => version.status === "SUBMITTED")?.status ??
          null,
        approvedStatus:
          approved.versions.find((version) => version.status === "APPROVED")?.status ??
          null,
        revisionVersionNumber:
          revised.versions.find((version) => version.status === "WORKING")
            ?.versionNumber ?? null,
        exportFileName:
          exported.versions[0]?.exports[0]?.fileName ??
          refreshed?.versions[0]?.exports[0]?.fileName ??
          null,
      }),
    );
  } finally {
    await prisma.estimate.delete({ where: { id: created.id } });
  }
}

main()
  .catch((error) => {
    console.error(error);
    process.exit(1);
  })
  .finally(async () => {
    await prisma.$disconnect();
  });
