import Config

if config_env() == :prod do
  import Domain.Config, only: [env_var_to_config!: 1, env_var_to_config: 1]

  ###############################
  ##### Domain ##################
  ###############################

  config :domain,
         Domain.Repo,
         [
           {:database, env_var_to_config!(:database_name)},
           {:username, env_var_to_config!(:database_user)},
           {:port, env_var_to_config!(:database_port)},
           {:pool_size, env_var_to_config!(:database_pool_size)},
           {:queue_target, env_var_to_config!(:database_queue_target)},
           {:queue_interval, env_var_to_config!(:database_queue_interval)},
           {:ssl, env_var_to_config!(:database_ssl_enabled)},
           {:ssl_opts, env_var_to_config!(:database_ssl_opts)},
           {:parameters, env_var_to_config!(:database_parameters)}
         ] ++
           if(env_var_to_config(:database_password),
             do: [{:password, env_var_to_config!(:database_password)}],
             else: []
           ) ++
           if(env_var_to_config(:database_socket_dir),
             do: [{:socket_dir, env_var_to_config!(:database_socket_dir)}],
             else: [{:hostname, env_var_to_config!(:database_host)}]
           )

  config :domain, Domain.ChangeLogs.ReplicationConnection,
    enabled: env_var_to_config!(:background_jobs_enabled),
    replication_slot_name: env_var_to_config!(:database_change_logs_replication_slot_name),
    publication_name: env_var_to_config!(:database_change_logs_publication_name),
    connection_opts:
      [
        port: env_var_to_config!(:database_port),
        ssl: env_var_to_config!(:database_ssl_enabled),
        ssl_opts: env_var_to_config!(:database_ssl_opts),
        parameters: env_var_to_config!(:database_parameters),
        username: env_var_to_config!(:database_user),
        database: env_var_to_config!(:database_name)
      ] ++
        if(env_var_to_config(:database_password),
          do: [{:password, env_var_to_config!(:database_password)}],
          else: []
        ) ++
        if(env_var_to_config(:database_socket_dir),
          do: [{:socket_dir, env_var_to_config!(:database_socket_dir)}],
          else: [{:hostname, env_var_to_config!(:database_host)}]
        )

  config :domain, Domain.Changes.ReplicationConnection,
    enabled: env_var_to_config!(:background_jobs_enabled),
    replication_slot_name: env_var_to_config!(:database_changes_replication_slot_name),
    publication_name: env_var_to_config!(:database_changes_publication_name),
    connection_opts:
      [
        port: env_var_to_config!(:database_port),
        ssl: env_var_to_config!(:database_ssl_enabled),
        ssl_opts: env_var_to_config!(:database_ssl_opts),
        parameters: env_var_to_config!(:database_parameters),
        username: env_var_to_config!(:database_user),
        database: env_var_to_config!(:database_name)
      ] ++
        if(env_var_to_config(:database_password),
          do: [{:password, env_var_to_config!(:database_password)}],
          else: []
        ) ++
        if(env_var_to_config(:database_socket_dir),
          do: [{:socket_dir, env_var_to_config!(:database_socket_dir)}],
          else: [{:hostname, env_var_to_config!(:database_host)}]
        )

  config :domain, run_manual_migrations: env_var_to_config!(:run_manual_migrations)

  config :domain, Domain.Tokens,
    key_base: env_var_to_config!(:tokens_key_base),
    salt: env_var_to_config!(:tokens_salt)

  config :domain, Domain.Auth.Adapters.GoogleWorkspace.APIClient,
    finch_transport_opts: env_var_to_config!(:http_client_ssl_opts)

  config :domain, Domain.Billing.Stripe.APIClient,
    endpoint: "https://api.stripe.com",
    finch_transport_opts: []

  config :domain, Domain.Billing,
    enabled: env_var_to_config!(:billing_enabled),
    secret_key: env_var_to_config!(:stripe_secret_key),
    webhook_signing_secret: env_var_to_config!(:stripe_webhook_signing_secret),
    default_price_id: env_var_to_config!(:stripe_default_price_id)

  config :domain, platform_adapter: env_var_to_config!(:platform_adapter)

  if platform_adapter = env_var_to_config!(:platform_adapter) do
    config :domain, platform_adapter, env_var_to_config!(:platform_adapter_config)
  end

  config :domain, Domain.Cluster,
    adapter: env_var_to_config!(:erlang_cluster_adapter),
    adapter_config: env_var_to_config!(:erlang_cluster_adapter_config)

  config :domain, Domain.Instrumentation,
    client_logs_enabled: env_var_to_config!(:instrumentation_client_logs_enabled),
    client_logs_bucket: env_var_to_config!(:instrumentation_client_logs_bucket)

  config :domain, Domain.Analytics,
    mixpanel_token: env_var_to_config!(:mixpanel_token),
    hubspot_workspace_id: env_var_to_config!(:hubspot_workspace_id)

  config :domain, :enabled_features,
    idp_sync: env_var_to_config!(:feature_idp_sync_enabled),
    sign_up: env_var_to_config!(:feature_sign_up_enabled),
    self_hosted_relays: env_var_to_config!(:feature_self_hosted_relays_enabled),
    policy_conditions: env_var_to_config!(:feature_policy_conditions_enabled),
    multi_site_resources: env_var_to_config!(:feature_multi_site_resources_enabled),
    rest_api: env_var_to_config!(:feature_rest_api_enabled),
    internet_resource: env_var_to_config!(:feature_internet_resource_enabled)

  config :domain, sign_up_whitelisted_domains: env_var_to_config!(:sign_up_whitelisted_domains)

  config :domain, docker_registry: env_var_to_config!(:docker_registry)

  config :domain,
    outbound_email_adapter_configured?: !!env_var_to_config!(:outbound_email_adapter)

  config :domain, web_external_url: env_var_to_config!(:web_external_url)

  # Enable background jobs only on dedicated nodes
  config :domain, Domain.Tokens.Jobs.DeleteExpiredTokens,
    enabled: env_var_to_config!(:background_jobs_enabled)

  config :domain, Domain.Billing.Jobs.CheckAccountLimits,
    enabled: env_var_to_config!(:background_jobs_enabled)

  config :domain, Domain.Auth.Adapters.GoogleWorkspace.Jobs.RefreshAccessTokens,
    enabled: env_var_to_config!(:background_jobs_enabled)

  config :domain, Domain.Auth.Adapters.GoogleWorkspace.Jobs.SyncDirectory,
    enabled: env_var_to_config!(:background_jobs_enabled)

  config :domain, Domain.Auth.Adapters.MicrosoftEntra.Jobs.RefreshAccessTokens,
    enabled: env_var_to_config!(:background_jobs_enabled)

  config :domain, Domain.Auth.Adapters.MicrosoftEntra.Jobs.SyncDirectory,
    enabled: env_var_to_config!(:background_jobs_enabled)

  config :domain, Domain.Auth.Adapters.Okta.Jobs.RefreshAccessTokens,
    enabled: env_var_to_config!(:background_jobs_enabled)

  config :domain, Domain.Auth.Adapters.Okta.Jobs.SyncDirectory,
    enabled: env_var_to_config!(:background_jobs_enabled)

  config :domain, Domain.Auth.Adapters.JumpCloud.Jobs.SyncDirectory,
    enabled: env_var_to_config!(:background_jobs_enabled)

  # Enable the mock sync directory job in staging
  config :domain, Domain.Auth.Adapters.Mock.Jobs.SyncDirectory,
    enabled:
      env_var_to_config!(:background_jobs_enabled) and
        Enum.member?(env_var_to_config!(:auth_provider_adapters), :mock)

  # Oban has its own config validation that prevents overriding config in runtime.exs,
  # so we explicitly set the config in dev.exs, test.exs, and runtime.exs (for prod) only.
  config :domain, Oban,
    # Periodic jobs don't make sense in tests
    plugins: [
      # Keep the last 90 days of completed, cancelled, and discarded jobs
      {Oban.Plugins.Pruner, max_age: 60 * 60 * 24 * 90},

      # Rescue jobs that may have failed due to transient errors like deploys
      # or network issues. It's not guaranteed that the job won't be executed
      # twice, so for now we disable it since all of our Oban jobs can be retried
      # without loss.
      # {Oban.Plugins.Lifeline, rescue_after: :timer.minutes(30)}

      # Periodic jobs
      {Oban.Plugins.Cron,
       crontab: [
         # Delete expired flows every minute
         {"* * * * *", Domain.Flows.Jobs.DeleteExpiredFlows}
       ]}
    ],
    queues: if(env_var_to_config!(:background_jobs_enabled), do: [default: 10], else: []),
    engine: Oban.Engines.Basic,
    repo: Domain.Repo

  if web_external_url = env_var_to_config!(:web_external_url) do
    %{
      scheme: web_external_url_scheme,
      host: web_external_url_host,
      port: web_external_url_port,
      path: web_external_url_path
    } = URI.parse(web_external_url)

    ###############################
    ##### Web #####################
    ###############################

    config :web, Web.Endpoint,
      http: [
        ip: env_var_to_config!(:phoenix_listen_address).address,
        port: env_var_to_config!(:phoenix_http_web_port),
        protocol_options: env_var_to_config!(:phoenix_http_protocol_options)
      ],
      url: [
        scheme: web_external_url_scheme,
        host: web_external_url_host,
        port: web_external_url_port,
        path: web_external_url_path
      ],
      secret_key_base: env_var_to_config!(:secret_key_base),
      check_origin: [
        "#{web_external_url_scheme}://#{web_external_url_host}:#{web_external_url_port}",
        "#{web_external_url_scheme}://*.#{web_external_url_host}:#{web_external_url_port}",
        "#{web_external_url_scheme}://#{web_external_url_host}",
        "#{web_external_url_scheme}://*.#{web_external_url_host}"
      ],
      live_view: [
        signing_salt: env_var_to_config!(:live_view_signing_salt)
      ]

    config :web,
      external_trusted_proxies: env_var_to_config!(:phoenix_external_trusted_proxies),
      private_clients: env_var_to_config!(:phoenix_private_clients)

    config :web,
      cookie_secure: env_var_to_config!(:phoenix_secure_cookies),
      cookie_signing_salt: env_var_to_config!(:cookie_signing_salt),
      cookie_encryption_salt: env_var_to_config!(:cookie_encryption_salt)

    config :web, api_url_override: env_var_to_config!(:api_url_override)
  end

  if api_external_url = env_var_to_config!(:api_external_url) do
    %{
      scheme: api_external_url_scheme,
      host: api_external_url_host,
      port: api_external_url_port,
      path: api_external_url_path
    } = URI.parse(api_external_url)

    ###############################
    ##### API #####################
    ###############################

    config :api, API.Endpoint,
      http: [
        ip: env_var_to_config!(:phoenix_listen_address).address,
        port: env_var_to_config!(:phoenix_http_api_port),
        protocol_options: env_var_to_config!(:phoenix_http_protocol_options)
      ],
      url: [
        scheme: api_external_url_scheme,
        host: api_external_url_host,
        port: api_external_url_port,
        path: api_external_url_path
      ],
      secret_key_base: env_var_to_config!(:secret_key_base)

    config :api,
      cookie_secure: env_var_to_config!(:phoenix_secure_cookies),
      cookie_signing_salt: env_var_to_config!(:cookie_signing_salt),
      cookie_encryption_salt: env_var_to_config!(:cookie_encryption_salt)

    config :api,
      external_trusted_proxies: env_var_to_config!(:phoenix_external_trusted_proxies),
      private_clients: env_var_to_config!(:phoenix_private_clients)

    config :api, API.RateLimit,
      refill_rate: env_var_to_config!(:api_refill_rate),
      capacity: env_var_to_config!(:api_capacity)

    config :web,
      api_external_url: api_external_url
  end

  ###############################
  ##### Third-party configs #####
  ###############################

  if System.get_env("OTLP_ENDPOINT") do
    config :opentelemetry,
      resource_detectors: [:otel_resource_env_var, :otel_resource_app_env],
      resource: %{
        service: %{
          # These are populated on our GCP VMs
          name: System.get_env("APPLICATION_NAME"),
          namespace: System.get_env("GCP_PROJECT_ID"),
          version: System.get_env("RELEASE_VSN"),
          instance: %{id: System.get_env("GCP_INSTANCE_NAME")}
        }
      }

    config :opentelemetry,
      span_processor: :batch,
      traces_exporter: :otlp

    config :opentelemetry_exporter,
      otlp_protocol: :http_protobuf,
      otlp_traces_protocol: :http_protobuf,
      otlp_endpoint: System.get_env("OTLP_ENDPOINT")
  end

  config :domain, Domain.Telemetry,
    healthz_port: env_var_to_config!(:healthz_port),
    metrics_reporter: env_var_to_config!(:telemetry_metrics_reporter)

  if telemetry_metrics_reporter = env_var_to_config!(:telemetry_metrics_reporter) do
    config :domain,
           telemetry_metrics_reporter,
           env_var_to_config!(:telemetry_metrics_reporter_opts)
  end

  config :domain,
    http_client_ssl_opts: env_var_to_config!(:http_client_ssl_opts)

  config :openid_connect,
    finch_transport_opts: env_var_to_config!(:http_client_ssl_opts)

  config :domain,
         Domain.Mailer,
         [
           adapter: env_var_to_config!(:outbound_email_adapter),
           from_email: env_var_to_config!(:outbound_email_from)
         ] ++ env_var_to_config!(:outbound_email_adapter_opts)

  config :workos, WorkOS.Client,
    api_key: env_var_to_config!(:workos_api_key),
    client_id: env_var_to_config!(:workos_client_id)

  # Sentry

  with api_external_url when not is_nil(api_external_url) <-
         env_var_to_config!(:api_external_url),
       api_external_url_host <- URI.parse(api_external_url).host,
       environment_name when environment_name in [:staging, :production] <-
         (case api_external_url_host do
            "api.firezone.dev" -> :production
            "api.firez.one" -> :staging
            _ -> :unknown
          end) do
    config :sentry,
      environment_name: environment_name,
      dsn:
        "https://29f4ab7c6c473c17bc01f8aeffb0ac16@o4507971108339712.ingest.us.sentry.io/4508756715569152"
  end
end
