# frozen_string_literal: true

require "test_helper"

class DsnTest < ActiveSupport::TestCase
  # Disable fixtures since we're creating test data manually
  self.use_instantiated_fixtures = false
  def setup
    @dsn = Dsn.new(name: "Test DSN")
  end

  test "should be valid with valid attributes" do
    assert @dsn.valid?
  end

  test "should not be valid without name" do
    @dsn.name = nil
    assert_not @dsn.valid?
    assert_includes @dsn.errors[:name], "can't be blank"
  end

  test "should automatically generate key on create" do
    @dsn.save!
    assert_not_nil @dsn.key
    assert_equal 64, @dsn.key.length # hex(32) = 64 characters
    assert_match /\A[a-f0-9]{64}\z/, @dsn.key
  end

  test "should not override existing key when saved" do
    @dsn.key = "existing-key-123"
    @dsn.save!
    assert_equal "existing-key-123", @dsn.key
  end

  test "should enforce unique keys" do
    @dsn.save!
    dsn2 = Dsn.new(name: "Another DSN", key: @dsn.key)
    assert_not dsn2.valid?
    assert_includes dsn2.errors[:key], "has already been taken"
  end

  test "should default to enabled" do
    @dsn.save!
    assert @dsn.enabled?
  end

  test "should authenticate with valid key" do
    @dsn.save!
    authenticated_dsn = Dsn.authenticate(@dsn.key)
    assert_equal @dsn, authenticated_dsn
  end

  test "should not authenticate with invalid key" do
    @dsn.save!
    assert_nil Dsn.authenticate("invalid-key")
  end

  test "should not authenticate disabled DSNs" do
    @dsn.save!
    @dsn.update!(enabled: false)
    assert_nil Dsn.authenticate(@dsn.key)
  end

  # URL Generation Tests
  test "should generate full DSN URL in development" do
    @dsn.key = "test-key-1234567890abcdef"
    @dsn.save!

    expected = "http://test-key-1234567890abcdef@localhost"
    assert_equal expected, @dsn.full_dsn_url
  end

  test "should generate API endpoint URL in development" do
    @dsn.save!

    expected = "http://localhost"
    assert_equal expected, @dsn.api_endpoint_url
  end

  test "should use HTTPS in production environment" do
    # Temporarily switch to production environment
    original_env = Rails.env
    Rails.env = "production"

    @dsn.key = "prod-key-1234567890abcdef"
    @dsn.save!

    assert_equal "https://prod-key-1234567890abcdef@localhost", @dsn.full_dsn_url
    assert_equal "https://localhost", @dsn.api_endpoint_url

    # Restore original environment
    Rails.env = original_env
  end

  test "should use custom host from environment variable" do
    ENV['RAILS_HOST'] = 'baffle.example.com'

    @dsn.key = "custom-key-1234567890abcdef"
    @dsn.save!

    assert_equal "http://custom-key-1234567890abcdef@baffle.example.com", @dsn.full_dsn_url
    assert_equal "http://baffle.example.com", @dsn.api_endpoint_url

    ENV.delete('RAILS_HOST')
  end

  test "should use action mailer default host if configured" do
    Rails.application.config.action_mailer.default_url_options = { host: 'mail.baffle.com' }

    @dsn.key = "mail-key-1234567890abcdef"
    @dsn.save!

    assert_equal "http://mail-key-1234567890abcdef@mail.baffle.com", @dsn.full_dsn_url
    assert_equal "http://mail.baffle.com", @dsn.api_endpoint_url

    Rails.application.config.action_mailer.default_url_options = {}
  end

  test "should handle long hex keys in URLs" do
    long_key = "c92b7f8ad94ea3400299d8a6ff19e409c2df8c4540022c3167b8ac1002931624"
    @dsn.key = long_key
    @dsn.save!

    expected = "http://#{long_key}@localhost"
    assert_equal expected, @dsn.full_dsn_url
  end

  # Scope Tests
  test "enabled scope should return only enabled DSNs" do
    enabled_dsn = Dsn.create!(name: "Enabled DSN", enabled: true)
    disabled_dsn = Dsn.create!(name: "Disabled DSN", enabled: false)

    enabled_dsns = Dsn.enabled

    assert_includes enabled_dsns, enabled_dsn
    assert_not_includes enabled_dsns, disabled_dsn
  end

  # Security Tests
  test "should generate cryptographically secure keys" do
    keys = []
    10.times do
      dsn = Dsn.create!(name: "Test DSN #{Time.current.to_f}")
      keys << dsn.key
    end

    # All keys should be unique
    assert_equal keys.length, keys.uniq.length

    # All keys should be valid hex
    keys.each do |key|
      assert_equal 64, key.length
      assert_match /\A[a-f0-9]{64}\z/, key
    end
  end

  test "should not allow nil keys" do
    @dsn.key = nil
    assert_not @dsn.valid?
    assert_includes @dsn.errors[:key], "can't be blank"
  end
end