"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateDetectDeltaTypes = generateDetectDeltaTypes;
const generator_1 = require("@postxl/generator");
function generateDetectDeltaTypes(context) {
    const { types, repositories } = context;
    const dto = types.dto;
    const imports = generator_1.ImportGenerator
        //
        .from(context.import.detectDelta.types.generic.modelType.location)
        .addType(dto.create)
        .addType(dto.update)
        .addType(dto.genericModel)
        .addType(dto.idType)
        .addType(repositories.bulkMutation)
        .addType(context.import.detectDelta.allModels.type);
    const generic = context.import.detectDelta.types.generic;
    return /* ts */ `
${imports.generate()}

/**
 * Generic type that contains all changes between an existing item and an updated item.
 */
export type ${generic.delta_Fields.name}<Model extends ${dto.genericModel.name}<ID>, ID extends ${dto.idType.name}> = Partial<{
  [K in keyof Omit<Model, 'id'>]?: { old: Model[K]; new: Model[K] }
}>

/**
 * For a given imported item of a model, this type contains the determined action to take - create, update, delete or unchanged.
 */

export type ${generic.modelType.name}<Model extends ${dto.genericModel.name}<ID>, ID extends ${dto.idType.name}, ModelErrors> =
  | ${generic.unchanged.type.name}<Model, ID>
  | ${generic.create.type.name}<Model, ID>
  | ${generic.update.type.name}<Model, ID>
  | ${generic.delete.type.name}<Model, ID>
  | ${generic.errors.type.name}<Model, ID, ModelErrors>

export type ${generic.unchanged.type.name}<Model extends ${dto.genericModel.name}<ID>, ID extends ${dto.idType.name}> = {
  type: '${generic.unchanged.discriminant}'
  input: Model
}

export function ${generic.unchanged.typeGuard.name}<Model extends ${dto.genericModel.name}<ID>, ID extends ${dto.idType.name}>(
  delta: Delta_Model<Model, ID, unknown>,
): delta is ${generic.unchanged.type.name}<Model, ID> {
  return delta.type === 'unchanged'
}

export type ${generic.create.type.name}<Model extends ${dto.genericModel.name}<ID>, ID extends ${dto.idType.name}> = {
  type: '${generic.create.discriminant}'
  input: Model
  createDto: ${dto.create.name}<Model, ID>
}

export function ${generic.create.typeGuard.name}<Model extends ${dto.genericModel.name}<ID>, ID extends ${dto.idType.name}>(
  delta: Delta_Model<Model, ID, unknown>,
): delta is ${generic.create.type.name}<Model, ID> {
  return delta.type === 'create'
}

export type ${generic.update.type.name}<Model extends ${dto.genericModel.name}<ID>, ID extends ${dto.idType.name}> = {
  type: '${generic.update.discriminant}'
  input: Model
  updateDto: ${dto.update.name}<Model, ID>
  delta: ${generic.delta_Fields.name}<Model, ID>
}

export function ${generic.update.typeGuard.name}<Model extends ${dto.genericModel.name}<ID>, ID extends ${dto.idType.name}>(
  delta: Delta_Model<Model, ID, unknown>,
): delta is ${generic.update.type.name}<Model, ID> {
  return delta.type === 'update'
}

export type ${generic.delete.type.name}<Model extends ${dto.genericModel.name}<ID>, ID extends ${dto.idType.name}> = {
  type: '${generic.delete.discriminant}'
  input: Model
}

export function ${generic.delete.typeGuard.name}<Model extends ${dto.genericModel.name}<ID>, ID extends ${dto.idType.name}>(
  delta: Delta_Model<Model, ID, unknown>,
): delta is ${generic.delete.type.name}<Model, ID> {
  return delta.type === 'delete'
}

export type ${generic.errors.type.name}<Model extends GenericModel<ID>, ID extends ${dto.idType.name}, ModelErrors> = {
  type: '${generic.errors.discriminant}'
  input: Model
  errors: ModelErrors[]
}

export function ${generic.errors.typeGuard.name}<Model extends GenericModel<ID>, ID extends ${dto.idType.name}, ModelErrors>(
  delta: Delta_Model<Model, ID, unknown>,
): delta is ${generic.errors.type.name}<Model, ID, ModelErrors> {
  return delta.type === 'errors'
}

export type ${generic.errors.missingField.type.name}<FieldName extends string> = {
  error: '${generic.errors.missingField.discriminant}'
  fieldName: FieldName
}

export type ${generic.errors.invalidReference.type.name}<
  RelatedModel extends string, FieldName extends string, Value
  > = {
  error: '${generic.errors.invalidReference.discriminant}'
  relatedModel: RelatedModel
  fieldName: FieldName
  value: Value
}

export type ${generic.errors.nonUnique.type.name}<FieldName extends string, Value> = {
  error: '${generic.errors.nonUnique.discriminant}'
  fieldName: FieldName
  value: Value
}

export type ${generic.errors.invalidType.type.name}<FieldName extends string, TypeName extends string, Value> = {
  error: '${generic.errors.invalidType.discriminant}'
  fieldName: FieldName
  typeExpected: TypeName
  value: Value
}

export type ${generic.errors.isRequiredDependency.type.name}<
    RelatedModelName extends string,
    RelatedField extends string,
    RelatedModel extends GenericModel<ID>,
   ID extends ${dto.idType.name}
  > = { 
  error: '${generic.errors.isRequiredDependency.discriminant}'
  relatedModel: RelatedModelName
  relatedField: RelatedField
  relatedItems: RelatedModel[]
}

export type DataChanges = {
  /**
   * The delta of all models.
   */
  delta: ${context.import.detectDelta.allModels.type.name}

  /**
   * The bulk mutations derived from the delta.
   */
  bulkMutations: ${context.update.bulk.type.name}[]
}`;
}
//# sourceMappingURL=types.generator.js.map