/**
 * Environment Variable Validation — Convex + Clerk + Upstash Stack
 *
 * Validates critical environment variables on startup.
 * Run this early to fail fast on misconfiguration.
 */

interface EnvVar {
  name: string;
  required: boolean;
  validator?: (value: string) => boolean;
  description: string;
  category?:
    | "convex"
    | "clerk"
    | "auth"
    | "payment"
    | "email"
    | "redis"
    | "api"
    | "security";
}

const CRITICAL_ENV_VARS: EnvVar[] = [
  // Convex
  {
    name: "NEXT_PUBLIC_CONVEX_URL",
    required: true,
    validator: (v) => v.startsWith("https://") && v.includes(".convex.cloud"),
    description: "Convex deployment URL",
    category: "convex",
  },

  // Clerk
  {
    name: "NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY",
    required: true,
    validator: (v) => v.startsWith("pk_"),
    description: "Clerk publishable key",
    category: "clerk",
  },
  {
    name: "CLERK_SECRET_KEY",
    required: true,
    validator: (v) => v.startsWith("sk_"),
    description: "Clerk secret key",
    category: "clerk",
  },

  // Security
  {
    name: "NEXTAUTH_SECRET",
    required: true,
    validator: (v) => v.length >= 32,
    description: "JWT signing secret (min 32 chars)",
    category: "auth",
  },
  {
    name: "ENCRYPTION_KEY",
    required: true,
    validator: (v) => /^[a-f0-9]{64}$/i.test(v),
    description: "AES-256 encryption key (64 hex chars)",
    category: "security",
  },
];

const RECOMMENDED_ENV_VARS: EnvVar[] = [
  // Stripe
  {
    name: "STRIPE_SECRET_KEY",
    required: false,
    validator: (v) => v.startsWith("sk_"),
    description: "Stripe secret key",
    category: "payment",
  },
  {
    name: "STRIPE_WEBHOOK_SECRET",
    required: false,
    validator: (v) => v.startsWith("whsec_"),
    description: "Stripe webhook signing secret",
    category: "payment",
  },
  {
    name: "NEXT_PUBLIC_STRIPE_PUBLIC_KEY",
    required: false,
    validator: (v) => v.startsWith("pk_"),
    description: "Stripe publishable key",
    category: "payment",
  },

  // Upstash Redis (for BullMQ)
  {
    name: "UPSTASH_REDIS_REST_URL",
    required: false,
    validator: (v) => v.startsWith("https://"),
    description: "Upstash Redis REST URL",
    category: "redis",
  },
  {
    name: "UPSTASH_REDIS_REST_TOKEN",
    required: false,
    description: "Upstash Redis REST token",
    category: "redis",
  },

  // Email
  {
    name: "SMTP_HOST",
    required: false,
    description: "SMTP server host",
    category: "email",
  },
  {
    name: "SMTP_PORT",
    required: false,
    validator: (v) => !isNaN(parseInt(v)),
    description: "SMTP server port",
    category: "email",
  },

  // reCAPTCHA
  {
    name: "RECAPTCHA_SECRET_KEY",
    required: false,
    description: "Google reCAPTCHA v3 secret key",
    category: "security",
  },
];

interface ValidationResult {
  valid: boolean;
  errors: string[];
  warnings: string[];
}

/**
 * Validate all environment variables and return results
 */
export function validateEnv(): ValidationResult {
  const errors: string[] = [];
  const warnings: string[] = [];

  // Check critical vars
  for (const envVar of CRITICAL_ENV_VARS) {
    const value = process.env[envVar.name];

    if (!value) {
      errors.push(
        `Missing required env var: ${envVar.name} — ${envVar.description}`,
      );
      continue;
    }

    if (envVar.validator && !envVar.validator(value)) {
      errors.push(`Invalid ${envVar.name}: ${envVar.description}`);
    }
  }

  // Check recommended vars
  for (const envVar of RECOMMENDED_ENV_VARS) {
    const value = process.env[envVar.name];

    if (!value) {
      warnings.push(
        `Missing recommended env var: ${envVar.name} — ${envVar.description}`,
      );
      continue;
    }

    if (envVar.validator && !envVar.validator(value)) {
      warnings.push(`Invalid format for ${envVar.name}: ${envVar.description}`);
    }
  }

  return {
    valid: errors.length === 0,
    errors,
    warnings,
  };
}

/**
 * Run validation and log results. Throws in production if critical vars missing.
 */
export function validateEnvironment(): void {
  // Skip validation in test environment
  if (
    process.env.NODE_ENV === "test" ||
    process.env.SKIP_ENV_VALIDATION === "1"
  ) {
    return;
  }

  const result = validateEnv();

  if (result.warnings.length > 0) {
    console.warn("[env] Warnings:", result.warnings.join("; "));
  }

  if (!result.valid) {
    const msg = `[env] Critical environment variables missing or invalid:\n${result.errors.join("\n")}`;

    if (process.env.NODE_ENV === "production") {
      throw new Error(msg);
    } else {
      console.error(msg);
    }
  }
}

/**
 * Check if a specific feature is configured
 */
export function isFeatureConfigured(
  feature: "convex" | "clerk" | "stripe" | "email" | "bullmq" | "recaptcha",
): boolean {
  switch (feature) {
    case "convex":
      return Boolean(process.env.NEXT_PUBLIC_CONVEX_URL);
    case "clerk":
      return Boolean(
        process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY &&
        process.env.CLERK_SECRET_KEY,
      );
    case "stripe":
      return Boolean(process.env.STRIPE_SECRET_KEY);
    case "email":
      return Boolean(process.env.SMTP_HOST && process.env.SMTP_PORT);
    case "bullmq":
      return Boolean(
        process.env.UPSTASH_REDIS_REST_URL || process.env.REDIS_URL,
      );
    case "recaptcha":
      return Boolean(process.env.RECAPTCHA_SECRET_KEY);
    default:
      return false;
  }
}
