import { EnvRequirements, EnvValue } from "@mcpx/shared-model";

/**
 * Resolves env requirements from a catalog template with user-provided values
 * to create runtime env config.
 *
 * Resolution rules:
 * - fixed: always use catalog's prefilled value (user cannot override)
 * - required: user must provide value (no fallback to prefilled)
 * - optional: use user value if provided, otherwise skip
 *
 * Note: prefilled is only a UI hint for required/optional. The UI shows it
 * as a default, and the user sends back the actual value they want.
 */
export function resolveEnvToRuntime(
  requirements: EnvRequirements | undefined,
  userValues: Record<string, EnvValue>,
): Record<string, EnvValue> {
  if (!requirements) {
    return {};
  }

  const result: Record<
    string,
    string | { fromEnv: string } | { fromSecret: string } | null
  > = {};
  const missingRequired: string[] = [];

  for (const [key, requirement] of Object.entries(requirements)) {
    const userValue = userValues[key];

    if (requirement.kind === "fixed") {
      // Fixed: enforce catalog value, ignore user input
      result[key] = requirement.prefilled;
    } else if (userValue !== undefined) {
      // User provided a value
      result[key] = userValue;
    } else if (requirement.kind === "required") {
      // Required but user didn't provide value
      missingRequired.push(key);
    }
    // Optional without user value: skip
  }

  if (missingRequired.length > 0) {
    throw new MissingRequiredEnvError(missingRequired);
  }

  return result;
}

export function enforceFixedEnvVars(
  env: Record<string, EnvValue>,
  requirements?: EnvRequirements,
): Record<string, EnvValue> {
  if (!requirements) return env;

  const result = { ...env };
  for (const [key, req] of Object.entries(requirements)) {
    if (req.kind === "fixed") {
      result[key] = req.prefilled;
    }
  }
  return result;
}

export class MissingRequiredEnvError extends Error {
  constructor(public readonly missingKeys: string[]) {
    super(`Missing required environment variables: ${missingKeys.join(", ")}`);
    this.name = "MissingRequiredEnvError";
  }
}
