import { matchStep } from "./step-conventions.js";
function generateBehaviorBody(behavior, opMeta, context) {
  const result = generateBehaviorWithHelpers(behavior, opMeta, context);
  return result.body;
}
function generateBehaviorWithHelpers(behavior, opMeta, context) {
  const parts = [];
  const helperMethods = [];
  const preconditions = generatePreconditionChecks(
    behavior.preconditions || [],
    context
  );
  if (preconditions) parts.push(preconditions);
  const { code, helpers } = generateStepLogic(
    behavior.steps || [],
    context
  );
  parts.push(code);
  helperMethods.push(...helpers);
  const postconditions = generatePostconditionVerification(
    behavior.postconditions || []
  );
  if (postconditions) parts.push(postconditions);
  const events = generateEventPublishing(
    behavior.sideEffects || [],
    context.operationName
  );
  if (events) parts.push(events);
  let body = parts.join("\n\n");
  if (behavior.transactional) {
    body = generateTransactionWrapper(body, context);
  }
  return { body, helperMethods };
}
function generatePreconditionChecks(preconditions, context) {
  if (preconditions.length === 0) return "";
  const checks = preconditions.map((pc) => matchPreconditionPattern(pc, context));
  return `    // === PRECONDITIONS ===
${checks.join("\n")}`;
}
function matchPreconditionPattern(precondition, context) {
  const pc = precondition.toLowerCase();
  const prismaModel = context.prismaModel || context.modelName;
  const existsMatch = precondition.match(/^(\w+)\s+exists/i);
  if (existsMatch) {
    const entity = existsMatch[1];
    const entityVar = entity.charAt(0).toLowerCase() + entity.slice(1);
    return `    // Guard: ${precondition}
    const ${entityVar} = await prisma.${entityVar}.findUnique({ where: { id: params.id } });
    if (!${entityVar}) {
      throw new Error('Precondition failed: ${precondition}');
    }`;
  }
  if (pc.includes("is not empty") || pc.includes("is required")) {
    const fieldMatch = precondition.match(/^(\w+)\s+is/i);
    if (fieldMatch) {
      const field = fieldMatch[1];
      return `    // Guard: ${precondition}
    if (!params.${field}) {
      throw new Error('Precondition failed: ${precondition}');
    }`;
    }
  }
  if (pc.includes("is valid")) {
    return `    // Guard: ${precondition}
    const validation = this.validate(params, { operation: '${context.operationName}' });
    if (!validation.valid) {
      throw new Error('Precondition failed: ${precondition} \u2014 ' + validation.errors.join(', '));
    }`;
  }
  const matchesMatch = precondition.match(/^(\w+)\s+(?:matches|equals)\s+(.+)/i);
  if (matchesMatch) {
    const left = matchesMatch[1];
    const right = matchesMatch[2];
    return `    // Guard: ${precondition}
    if (params.${left.charAt(0).toLowerCase() + left.slice(1)} !== params.${right.charAt(0).toLowerCase() + right.slice(1)}) {
      throw new Error('Precondition failed: ${precondition}');
    }`;
  }
  const stateMatch = precondition.match(/^(\w+)\s+is\s+(\w+)$/i);
  if (stateMatch) {
    const model = stateMatch[1];
    const state = stateMatch[2];
    const modelVar = model.charAt(0).toLowerCase() + model.slice(1);
    return `    // Guard: ${precondition}
    const ${modelVar}State = await prisma.${modelVar}.findUniqueOrThrow({ where: { id: params.id } });
    if (${modelVar}State.status !== '${state}') {
      throw new Error('Precondition failed: ${precondition} (current: ' + ${modelVar}State.status + ')');
    }`;
  }
  return `    // Guard: ${precondition}
    // TODO: Implement precondition check`;
}
function generateStepLogic(steps, context) {
  const helpers = [];
  if (steps && steps.length > 0) {
    const stepCode = steps.map((step, i) => {
      if (typeof step !== "string") {
        return `    // Step ${i + 1}: Complex operation \u2014 see expanded definition`;
      }
      const ctx = {
        modelName: context.modelName,
        prismaModel: context.prismaModel || context.modelName,
        serviceName: context.serviceName,
        operationName: context.operationName,
        stepNum: i + 1
      };
      const result = matchStep(step, ctx);
      if (result.helperMethod) {
        helpers.push(result.helperMethod);
      }
      return result.call;
    });
    return {
      code: `    // === EXECUTE ===
${stepCode.join("\n\n")}`,
      helpers
    };
  }
  return {
    code: `    // === EXECUTE ===
${inferLogicFromOperationName(context)}`,
    helpers
  };
}
function inferLogicFromOperationName(context) {
  const op = context.operationName;
  const prismaModel = context.prismaModel || context.modelName;
  const modelVar = prismaModel.charAt(0).toLowerCase() + prismaModel.slice(1);
  if (op.startsWith("handle")) {
    const event = op.replace("handle", "");
    return `    // Event handler: ${op}
    console.log('[${context.serviceName}] Processing ${event}', params);
    return { handled: true, event: '${event}' };`;
  }
  if (op.startsWith("validate")) {
    return `    // Validation: ${op}
    const records = await prisma.${modelVar}.findMany({ where: { id: params.id } });
    return { valid: records.length > 0, checked: records.length };`;
  }
  if (op.startsWith("get") || op.startsWith("list") || op.startsWith("find")) {
    return `    return await prisma.${modelVar}.findMany({});`;
  }
  return `    // TODO: Implement ${op}
    return { success: true };`;
}
function generatePostconditionVerification(postconditions) {
  if (postconditions.length === 0) return "";
  const checks = postconditions.map(
    (pc) => `      console.assert(true, 'POSTCONDITION: ${pc}');`
  );
  return `    // === POSTCONDITIONS (dev-mode) ===
    if (process.env.NODE_ENV === 'development') {
${checks.join("\n")}
    }`;
}
function generateEventPublishing(sideEffects, operationName) {
  if (!sideEffects || sideEffects.length === 0) return "";
  const publishes = sideEffects.map(
    (event) => `    this.emit('${event}', { operation: '${operationName}', timestamp: new Date().toISOString() });`
  );
  return `    // === EVENTS ===
${publishes.join("\n")}`;
}
function generateTransactionWrapper(body, context) {
  return `    return await prisma.$transaction(async (tx) => {
${body}
    });`;
}
export {
  generateBehaviorBody,
  generateBehaviorWithHelpers,
  generateEventPublishing,
  generatePostconditionVerification,
  generatePreconditionChecks,
  generateTransactionWrapper
};
