import { DrizzleCli } from "@/db/initDrizzle.js";
import { AppEnv, Customer, Organization, ProcessorType } from "@autumn/shared";
import { createStripeCli } from "../../external/stripe/utils.js";
import { Autumn } from "autumn-js";
import {
  attachPmToCus,
  createStripeCustomer,
} from "../../external/stripe/stripeCusUtils.js";
import { CusService } from "@/internal/customers/CusService.js";
import Stripe from "stripe";

export const createCusInStripe = async ({
  customer,
  org,
  env,
  db,
  testClockId,
}: {
  customer: Customer;
  org: Organization;
  env: AppEnv;
  db: DrizzleCli;
  testClockId?: string;
}) => {
  const stripeCustomer = await createStripeCustomer({
    org,
    env,
    customer,
    testClockId,
  });

  await CusService.update({
    db,
    internalCusId: customer.internal_id,
    update: {
      processor: {
        type: ProcessorType.Stripe,
        id: stripeCustomer.id,
      },
    },
  });

  customer.processor = {
    id: stripeCustomer.id,
    type: "stripe",
  };

  return stripeCustomer;
};

export const initCustomer = async ({
  autumn,
  customerId,
  fingerprint,
  org,
  env,
  db,
  attachPm,
  withTestClock = true,
}: {
  autumn: Autumn;
  customerId: string;
  fingerprint?: string;
  org: Organization;
  env: AppEnv;
  db: DrizzleCli;
  attachPm?: "success" | "fail";
  withTestClock?: boolean;
}) => {
  let customerData = {
    id: customerId,
    name: customerId,
    email: `${customerId}@example.com`,
    fingerprint,
  };

  // Create and delete customer
  try {
    await autumn.customers.delete(customerId);
  } catch (error) {}

  let testClockId = null;
  try {
    await autumn.customers.create(customerData);
    let customer = (await CusService.get({
      db,
      idOrInternalId: customerId,
      orgId: org.id,
      env: env,
    })) as Customer;

    const stripeCli = createStripeCli({ org: org, env: env });
    let testClockId = "";
    if (withTestClock) {
      const testClock = await stripeCli.testHelpers.testClocks.create({
        frozen_time: Math.floor(Date.now() / 1000),
      });
      testClockId = testClock.id;
    }

    if (attachPm) {
      await attachPmToCus({
        customer,
        org: org,
        env: env,
        db: db,
        willFail: attachPm === "fail",
        testClockId: testClockId || undefined,
      });
    } else {
      await createCusInStripe({
        customer,
        org,
        env,
        db,
        testClockId,
      });
    }

    return {
      customer,
      testClockId: testClockId,
    };
  } catch (error) {
    console.log("Failed to create customer", error);
    throw error;
  }
};
