import dotenv from "dotenv";
import type { Secrets } from "./secrets.js";

export interface AppConfig {
  NODE_ENV: "development" | "production" | "test" | "staging";
  PORT: number;
  SUPABASE_URL: string;
  SUPABASE_SERVICE_ROLE_KEY: string;
  SUPABASE_CONNECTION_STRING: string;
  SUPABASE_CA_CERT: string;
  STREAM_CHAT_API_KEY: string;
  STREAM_CHAT_API_SECRET: string;
  STRIPE_SECRET_KEY: string;
  STRIPE_WEBHOOK_SECRET: string;
  STRIPE_SOLO_PRICE_ID: string;
  STRIPE_TEAM_MONTHLY_PRICE_ID: string;
  STRIPE_FOUNDER_PRICE_ID: string;
  EMAIL_USER: string;
  EMAIL_CLIENT_ID: string;
  EMAIL_CLIENT_SECRET: string;
  EMAIL_REFRESH_TOKEN: string;
  XTABLO_URL: string;
  R2_ACCOUNT_ID: string;
  R2_ACCESS_KEY_ID: string;
  R2_SECRET_ACCESS_KEY: string;
  LOG_LEVEL: "debug" | "info" | "warn" | "error";
  TASKS_SECRET: string;

  /**
   * Test user
   */
  TEST_USER_DATA: {
    id: string;
    email: string;
    user_metadata: Record<string, unknown>;
    app_metadata: Record<string, unknown>;
    aud: string;
    created_at: string;
  };
}

function validateEnvVar(name: string, value: string | undefined): string {
  if (!value) {
    throw new Error(`Missing required environment variable: ${name}`);
  }
  return value;
}

export function createConfig(secrets?: Secrets): AppConfig {
  const NODE_ENV = (process.env.NODE_ENV || "development") as
    | "development"
    | "production"
    | "staging"
    | "test";

  dotenv.config({ path: `.env.${NODE_ENV}` });

  // In test mode, use environment variables directly instead of secrets
  const isTestMode = NODE_ENV === "test";

  const isStagingMode = NODE_ENV === "staging";
  const getStreamChatApiSecret = (isStagingMode: boolean) =>
    isStagingMode ? secrets!.streamChatApiSecretStaging : secrets!.streamChatApiSecret;
  const getStripeSecretKey = (isStagingMode: boolean) =>
    isStagingMode ? secrets!.stripeSecretKeyStaging : secrets!.stripeSecretKey;
  const getStripeWebhookSecret = (isStagingMode: boolean) =>
    isStagingMode ? secrets!.stripeWebhookSecretStaging : secrets!.stripeWebhookSecret;
  const getStripeSecretKeyFromEnv = () => process.env.STRIPE_SECRET_KEY;
  const getStripeWebhookSecretFromEnv = () => process.env.STRIPE_WEBHOOK_SECRET;

  // Base configuration
  const baseConfig: AppConfig = {
    NODE_ENV,
    PORT: parseInt(process.env.PORT || "8080", 10),
    SUPABASE_URL: validateEnvVar("SUPABASE_URL", process.env.SUPABASE_URL),
    SUPABASE_SERVICE_ROLE_KEY: isTestMode
      ? validateEnvVar("SUPABASE_SERVICE_ROLE_KEY", process.env.SUPABASE_SERVICE_ROLE_KEY)
      : secrets!.supabaseServiceRoleKey,
    SUPABASE_CONNECTION_STRING: isTestMode
      ? validateEnvVar("SUPABASE_CONNECTION_STRING", process.env.SUPABASE_CONNECTION_STRING)
      : secrets!.supabaseConnectionString,
    SUPABASE_CA_CERT: isTestMode
      ? validateEnvVar("SUPABASE_CA_CERT", process.env.SUPABASE_CA_CERT)
      : secrets!.supabaseCaCert,
    STREAM_CHAT_API_KEY: validateEnvVar("STREAM_CHAT_API_KEY", process.env.STREAM_CHAT_API_KEY),
    // Env dependent
    STREAM_CHAT_API_SECRET: isTestMode
      ? validateEnvVar("STREAM_CHAT_API_SECRET", process.env.STREAM_CHAT_API_SECRET)
      : getStreamChatApiSecret(isStagingMode),
    STRIPE_SECRET_KEY: isTestMode
      ? validateEnvVar("STRIPE_SECRET_KEY", process.env.STRIPE_SECRET_KEY)
      : getStripeSecretKeyFromEnv() || getStripeSecretKey(isStagingMode),
    STRIPE_WEBHOOK_SECRET: isTestMode
      ? validateEnvVar("STRIPE_WEBHOOK_SECRET", process.env.STRIPE_WEBHOOK_SECRET)
      : getStripeWebhookSecretFromEnv() || getStripeWebhookSecret(isStagingMode),
    STRIPE_SOLO_PRICE_ID: validateEnvVar(
      "STRIPE_SOLO_PRICE_ID",
      process.env.STRIPE_SOLO_PRICE_ID
    ),
    STRIPE_TEAM_MONTHLY_PRICE_ID: validateEnvVar(
      "STRIPE_TEAM_MONTHLY_PRICE_ID",
      process.env.STRIPE_TEAM_MONTHLY_PRICE_ID
    ),
    STRIPE_FOUNDER_PRICE_ID: validateEnvVar(
      "STRIPE_FOUNDER_PRICE_ID",
      process.env.STRIPE_FOUNDER_PRICE_ID
    ),
    EMAIL_USER: validateEnvVar("EMAIL_USER", process.env.EMAIL_USER),
    EMAIL_CLIENT_ID: validateEnvVar("EMAIL_CLIENT_ID", process.env.EMAIL_CLIENT_ID),
    EMAIL_CLIENT_SECRET: isTestMode
      ? validateEnvVar("EMAIL_CLIENT_SECRET", process.env.EMAIL_CLIENT_SECRET)
      : secrets!.emailClientSecret,
    EMAIL_REFRESH_TOKEN: isTestMode
      ? validateEnvVar("EMAIL_REFRESH_TOKEN", process.env.EMAIL_REFRESH_TOKEN)
      : secrets!.emailRefreshToken,
    XTABLO_URL: process.env.XTABLO_URL || "https://app.xtablo.com",
    R2_ACCOUNT_ID: validateEnvVar("R2_ACCOUNT_ID", process.env.R2_ACCOUNT_ID),
    R2_ACCESS_KEY_ID: isTestMode
      ? validateEnvVar("R2_ACCESS_KEY_ID", process.env.R2_ACCESS_KEY_ID)
      : secrets!.r2AccessKeyId,
    R2_SECRET_ACCESS_KEY: isTestMode
      ? validateEnvVar("R2_SECRET_ACCESS_KEY", process.env.R2_SECRET_ACCESS_KEY)
      : secrets!.r2SecretAccessKey,
    TASKS_SECRET: process.env.TASKS_SECRET || "",
    LOG_LEVEL: "info",
    TEST_USER_DATA: {
      id: "test",
      email: "test@test.com",
      user_metadata: {},
      app_metadata: {},
      aud: "test",
      created_at: new Date("2025-01-01").toISOString(),
    },
  };

  // Environment-specific configurations
  if (NODE_ENV === "development") {
    baseConfig.LOG_LEVEL = "debug";
  } else if (NODE_ENV === "production") {
    baseConfig.LOG_LEVEL = "info";
  }

  console.log("✓ Configuration loaded successfully");

  return baseConfig;
}

// Helper functions for common environment checks
// export const isDevelopment = () => config.NODE_ENV === "development";
// export const isProduction = () => config.NODE_ENV === "production";
