import { type TailorAnyDBField } from "@tailor-platform/sdk";
import type { defineModule as definePrimitivesModule } from "../primitives";
import { createCompany } from "./command/createCompany.generated";
import { updateCompany } from "./command/updateCompany.generated";
import { activateCompany } from "./command/activateCompany.generated";
import { deactivateCompany } from "./command/deactivateCompany.generated";
import { reactivateCompany } from "./command/reactivateCompany.generated";
import { deleteCompany } from "./command/deleteCompany.generated";
import { createSite } from "./command/createSite.generated";
import { updateSite } from "./command/updateSite.generated";
import { deactivateSite } from "./command/deactivateSite.generated";
import { reactivateSite } from "./command/reactivateSite.generated";
import { createDepartment } from "./command/createDepartment.generated";
import { updateDepartment } from "./command/updateDepartment.generated";
import { deactivateDepartment } from "./command/deactivateDepartment.generated";
import { reactivateDepartment } from "./command/reactivateDepartment.generated";
import { getCompany } from "./query/getCompany.generated";
import { getDepartment } from "./query/getDepartment.generated";
import { getDepartmentChildren } from "./query/getDepartmentChildren.generated";
import { detectDepartmentCircularReference } from "./query/detectDepartmentCircularReference.generated";
import { getSite } from "./query/getSite.generated";
import { listDepartmentsByCompany } from "./query/listDepartmentsByCompany.generated";
import { listSitesByCompany } from "./query/listSitesByCompany.generated";
import { createCompanyType, type CreateCompanyTypeParams } from "./db/company";
import { createSiteType, type CreateSiteTypeParams } from "./db/site";
import { createDepartmentType, type CreateDepartmentTypeParams } from "./db/department";
import { type EmptyFields, type FieldsToInsertable } from "@tailor-platform/erp-kit/module";

type PrimitivesModule = ReturnType<typeof definePrimitivesModule>;
type PrimitivesDB = PrimitivesModule["db"];
export type PrimitivesQueries = PrimitivesModule["queries"];

export interface DefineModuleParams<
  CF extends Record<string, TailorAnyDBField>,
  SF extends Record<string, TailorAnyDBField>,
  DF extends Record<string, TailorAnyDBField>,
> {
  company?: CreateCompanyTypeParams<CF>;
  site?: CreateSiteTypeParams<SF>;
  department?: CreateDepartmentTypeParams<DF>;
  primitives: {
    db: { currency: PrimitivesDB["currency"] };
    queries: Pick<PrimitivesQueries, "getCurrency">;
  };
}

/* @__NO_SIDE_EFFECTS__ */
export const defineModule = <
  const CF extends Record<string, TailorAnyDBField> = EmptyFields,
  const SF extends Record<string, TailorAnyDBField> = EmptyFields,
  const DF extends Record<string, TailorAnyDBField> = EmptyFields,
>(
  params: DefineModuleParams<CF, SF, DF>,
) => {
  const company = createCompanyType({
    ...params.company,
    currencyType: params.primitives.db.currency,
  });
  const site = createSiteType(params.site ?? {});
  const department = createDepartmentType(params.department ?? {});

  return {
    db: { company, site, department },
    commands: {
      createCompany: createCompany<FieldsToInsertable<CF>>(params.primitives.queries),
      updateCompany: updateCompany<FieldsToInsertable<CF>>(params.primitives.queries),
      activateCompany: activateCompany(params.primitives.queries),
      deactivateCompany: deactivateCompany(),
      reactivateCompany: reactivateCompany(),
      deleteCompany: deleteCompany(),
      createSite: createSite<FieldsToInsertable<SF>>(),
      updateSite: updateSite<FieldsToInsertable<SF>>(),
      deactivateSite: deactivateSite(),
      reactivateSite: reactivateSite(),
      createDepartment: createDepartment<FieldsToInsertable<DF>>(),
      updateDepartment: updateDepartment<FieldsToInsertable<DF>>(),
      deactivateDepartment: deactivateDepartment(),
      reactivateDepartment: reactivateDepartment(),
    },
    queries: {
      getCompany,
      getDepartment,
      getDepartmentChildren,
      detectDepartmentCircularReference,
      getSite,
      listDepartmentsByCompany,
      listSitesByCompany,
    },
  };
};
