import { z } from 'zod';

const Env = z.object({
  NODE_ENV: z.enum(['development', 'test', 'production']).default('development'),
  DATABASE_URL: z.string(),
  REDIS_URL: z.string().default('redis://localhost:6379'),
  PORT: z.coerce.number().default(4000),
  NEXT_PUBLIC_APP_URL: z.string().default('http://localhost:3001'),
  OAUTH_KEY_DIR: z.string().default('./keys'),
  ANTHROPIC_API_KEY: z.string().optional(),
  GLM_API_KEY: z.string().optional(),
  SECRETS_ENCRYPTION_KEY: z
    .string()
    .min(64, '32 bytes hex required')
    .default('0000000000000000000000000000000000000000000000000000000000000000'),
  CONTROL_PLANE_PUBLIC_URL: z.string().default('http://localhost:4000'),
  ADMIN_EMAIL: z.string().email().optional(),
  ADMIN_PASSWORD: z.string().min(8).optional(),
  ADMIN_NAME: z.string().optional(),
  GOOGLE_OAUTH_ID: z.string().optional(),
  GOOGLE_OAUTH_SECRET: z.string().optional(),
  GITHUB_OAUTH_ID: z.string().optional(),
  GITHUB_OAUTH_SECRET: z.string().optional(),
  TWILIO_ACCOUNT_SID: z.string().optional(),
  TWILIO_AUTH_TOKEN: z.string().optional(),
  TWILIO_SMS_FROM: z.string().optional(),
  // Email magic-link login is OFF by default — no SMTP/Resend wired yet.
  // Set EMAIL_AUTH_ENABLED=true once an email sender is configured; the
  // magic-link routes + login-page form section will switch back on.
  EMAIL_AUTH_ENABLED: z
    .union([z.literal('true'), z.literal('false'), z.literal('1'), z.literal('0')])
    .transform((v) => v === 'true' || v === '1')
    .default('false'),
  STRIPE_SECRET_KEY: z.string().optional(),
  STRIPE_PUBLISHABLE_KEY: z.string().optional(),
  STRIPE_WEBHOOK_SECRET: z.string().optional(),
  STRIPE_PRICE_PRO_MONTHLY: z.string().optional(),
  STRIPE_PRICE_PRO_YEARLY: z.string().optional(),
  STRIPE_PRICE_TEAM_MONTHLY: z.string().optional(),
  STRIPE_PRICE_TEAM_YEARLY: z.string().optional(),
});

export const config = Env.parse({
  NODE_ENV: process.env.NODE_ENV,
  DATABASE_URL: process.env.DATABASE_URL,
  REDIS_URL: process.env.REDIS_URL,
  PORT: process.env.PORT,
  NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL,
  OAUTH_KEY_DIR: process.env.OAUTH_KEY_DIR,
  ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY,
  GLM_API_KEY: process.env.GLM_API_KEY,
  SECRETS_ENCRYPTION_KEY: process.env.SECRETS_ENCRYPTION_KEY,
  CONTROL_PLANE_PUBLIC_URL: process.env.CONTROL_PLANE_PUBLIC_URL,
  ADMIN_EMAIL: process.env.ADMIN_EMAIL,
  ADMIN_PASSWORD: process.env.ADMIN_PASSWORD,
  ADMIN_NAME: process.env.ADMIN_NAME,
  GOOGLE_OAUTH_ID: process.env.GOOGLE_OAUTH_ID,
  GOOGLE_OAUTH_SECRET: process.env.GOOGLE_OAUTH_SECRET,
  GITHUB_OAUTH_ID: process.env.GITHUB_OAUTH_ID,
  GITHUB_OAUTH_SECRET: process.env.GITHUB_OAUTH_SECRET,
  TWILIO_ACCOUNT_SID: process.env.TWILIO_ACCOUNT_SID,
  TWILIO_AUTH_TOKEN: process.env.TWILIO_AUTH_TOKEN,
  TWILIO_SMS_FROM: process.env.TWILIO_SMS_FROM,
  EMAIL_AUTH_ENABLED: process.env.EMAIL_AUTH_ENABLED,
  STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY,
  STRIPE_PUBLISHABLE_KEY: process.env.STRIPE_PUBLISHABLE_KEY,
  STRIPE_WEBHOOK_SECRET: process.env.STRIPE_WEBHOOK_SECRET,
  STRIPE_PRICE_PRO_MONTHLY: process.env.STRIPE_PRICE_PRO_MONTHLY,
  STRIPE_PRICE_PRO_YEARLY: process.env.STRIPE_PRICE_PRO_YEARLY,
  STRIPE_PRICE_TEAM_MONTHLY: process.env.STRIPE_PRICE_TEAM_MONTHLY,
  STRIPE_PRICE_TEAM_YEARLY: process.env.STRIPE_PRICE_TEAM_YEARLY,
});

// INFRA-001: refuse to boot in production with the placeholder encryption key.
// The zero-key passes the min(64) length check but would render every stored
// secret effectively plaintext.
const ZERO_KEY = '0'.repeat(64);
if (config.NODE_ENV === 'production' && config.SECRETS_ENCRYPTION_KEY === ZERO_KEY) {
  throw new Error(
    'SECRETS_ENCRYPTION_KEY is the all-zero placeholder. Set a real 32-byte hex key ' +
      '(openssl rand -hex 32) before running in production.',
  );
}

export type Config = z.infer<typeof Env>;
