defmodule Berrypod.KeyValidationTest do
  use ExUnit.Case, async: true

  alias Berrypod.KeyValidation

  describe "validate_stripe_key/1" do
    test "accepts valid test key" do
      key = "sk_test_51OUJ0abc123XYZdef456"
      assert {:ok, ^key} = KeyValidation.validate_stripe_key(key)
    end

    test "accepts valid live key" do
      key = "sk_live_51OUJ0abc123XYZdef456"
      assert {:ok, ^key} = KeyValidation.validate_stripe_key(key)
    end

    test "strips whitespace" do
      key = "sk_test_51OUJ0abc123XYZdef456"
      assert {:ok, ^key} = KeyValidation.validate_stripe_key("  #{key}  ")
    end

    test "strips newlines from paste" do
      key = "sk_test_51OUJ0abc123XYZdef456"
      assert {:ok, ^key} = KeyValidation.validate_stripe_key("#{key}\n")
    end

    test "rejects empty key" do
      assert {:error, msg} = KeyValidation.validate_stripe_key("")
      assert msg =~ "Please enter"
    end

    test "rejects nil" do
      assert {:error, msg} = KeyValidation.validate_stripe_key(nil)
      assert msg =~ "Please enter"
    end

    test "rejects whitespace-only" do
      assert {:error, msg} = KeyValidation.validate_stripe_key("   ")
      assert msg =~ "Please enter"
    end

    test "detects publishable key" do
      assert {:error, msg} = KeyValidation.validate_stripe_key("pk_test_abc123")
      assert msg =~ "publishable key"
      assert msg =~ "secret key"
    end

    test "detects restricted key" do
      assert {:error, msg} = KeyValidation.validate_stripe_key("rk_live_abc123")
      assert msg =~ "restricted key"
    end

    test "rejects key without correct prefix" do
      assert {:error, msg} = KeyValidation.validate_stripe_key("some_random_key_value")
      assert msg =~ "sk_test_"
    end

    test "rejects too-short key with correct prefix" do
      assert {:error, msg} = KeyValidation.validate_stripe_key("sk_test_x")
      assert msg =~ "too short"
    end
  end

  describe "validate_provider_key/2 - Printify" do
    @printify_uuid "12345678-1234-1234-1234-123456789012"

    test "accepts valid UUID format key" do
      assert {:ok, @printify_uuid} =
               KeyValidation.validate_provider_key(@printify_uuid, "printify")
    end

    test "strips whitespace" do
      assert {:ok, @printify_uuid} =
               KeyValidation.validate_provider_key("  #{@printify_uuid}  ", "printify")
    end

    test "rejects empty key" do
      assert {:error, msg} = KeyValidation.validate_provider_key("", "printify")
      assert msg =~ "Please enter"
    end

    test "rejects nil" do
      assert {:error, msg} = KeyValidation.validate_provider_key(nil, "printify")
      assert msg =~ "Please enter"
    end

    test "rejects too-short key" do
      assert {:error, msg} = KeyValidation.validate_provider_key("short", "printify")
      assert msg =~ "too short"
    end

    test "rejects too-long key" do
      long_key = String.duplicate("a", 50)
      assert {:error, msg} = KeyValidation.validate_provider_key(long_key, "printify")
      assert msg =~ "too long"
    end

    test "gives helpful error for non-UUID format" do
      assert {:error, msg} =
               KeyValidation.validate_provider_key("12345678123412341234123456789012", "printify")

      assert msg =~ "UUID format"
    end
  end

  describe "validate_provider_key/2 - Printful" do
    test "accepts reasonable length key" do
      key = String.duplicate("x", 40)
      assert {:ok, ^key} = KeyValidation.validate_provider_key(key, "printful")
    end

    test "strips whitespace" do
      key = String.duplicate("x", 40)
      assert {:ok, ^key} = KeyValidation.validate_provider_key("  #{key}  ", "printful")
    end

    test "rejects too-short key" do
      assert {:error, msg} = KeyValidation.validate_provider_key("short", "printful")
      assert msg =~ "too short"
    end
  end

  describe "validate_provider_key/2 - generic" do
    test "works without provider type" do
      key = String.duplicate("x", 20)
      assert {:ok, ^key} = KeyValidation.validate_provider_key(key)
    end
  end

  describe "validate_email_key/3 - SendGrid" do
    test "accepts valid SendGrid key" do
      key = "SG.abcdefghijklmnopqrstuv.abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG"
      assert {:ok, ^key} = KeyValidation.validate_email_key(key, "sendgrid", "api_key")
    end

    test "rejects key without SG. prefix" do
      assert {:error, msg} =
               KeyValidation.validate_email_key("not_a_sendgrid_key", "sendgrid", "api_key")

      assert msg =~ "SG."
    end

    test "strips whitespace" do
      key = "SG.abcdefghijklmnopqrstuv.abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG"
      assert {:ok, ^key} = KeyValidation.validate_email_key("  #{key}  ", "sendgrid", "api_key")
    end
  end

  describe "validate_email_key/3 - Brevo" do
    test "accepts valid Brevo key" do
      key = "xkeysib-" <> String.duplicate("ab", 32)
      assert {:ok, ^key} = KeyValidation.validate_email_key(key, "brevo", "api_key")
    end

    test "rejects key without xkeysib- prefix" do
      assert {:error, msg} = KeyValidation.validate_email_key("not_brevo_key", "brevo", "api_key")
      assert msg =~ "xkeysib-"
    end
  end

  describe "validate_email_key/3 - Mailjet" do
    test "accepts valid api_key" do
      key = String.duplicate("a1b2c3d4", 4)
      assert {:ok, ^key} = KeyValidation.validate_email_key(key, "mailjet", "api_key")
    end

    test "accepts valid secret" do
      key = String.duplicate("e5f6a7b8", 4)
      assert {:ok, ^key} = KeyValidation.validate_email_key(key, "mailjet", "secret")
    end

    test "rejects short api_key" do
      assert {:error, msg} = KeyValidation.validate_email_key("short", "mailjet", "api_key")
      assert msg =~ "too short"
      assert msg =~ "Mailjet"
    end

    test "rejects short secret" do
      assert {:error, msg} = KeyValidation.validate_email_key("short", "mailjet", "secret")
      assert msg =~ "too short"
      assert msg =~ "Mailjet"
    end
  end

  describe "validate_email_key/3 - MailerSend" do
    test "accepts key with mlsn. prefix" do
      key = "mlsn." <> String.duplicate("ab", 20)
      assert {:ok, ^key} = KeyValidation.validate_email_key(key, "mailersend", "api_key")
    end

    test "accepts long key without known prefix" do
      key = String.duplicate("x", 40)
      assert {:ok, ^key} = KeyValidation.validate_email_key(key, "mailersend", "api_key")
    end

    test "rejects short key" do
      assert {:error, msg} = KeyValidation.validate_email_key("short", "mailersend", "api_key")
      assert msg =~ "mlsn."
    end
  end

  describe "validate_email_key/3 - cross-provider detection" do
    test "detects Brevo key pasted into SendGrid" do
      key = "xkeysib-abc123def456"
      assert {:error, msg} = KeyValidation.validate_email_key(key, "sendgrid", "api_key")
      assert msg =~ "Brevo key"
    end

    test "detects SendGrid key pasted into Brevo" do
      key = "SG.abc123.def456"
      assert {:error, msg} = KeyValidation.validate_email_key(key, "brevo", "api_key")
      assert msg =~ "SendGrid key"
    end

    test "detects MailerSend key pasted into Brevo" do
      key = "mlsn.abc123"
      assert {:error, msg} = KeyValidation.validate_email_key(key, "brevo", "api_key")
      assert msg =~ "MailerSend key"
    end
  end

  describe "validate_email_key/3 - non-api_key fields" do
    test "accepts reasonable value for relay" do
      assert {:ok, "smtp.example.com"} =
               KeyValidation.validate_email_key("smtp.example.com", "smtp", "relay")
    end

    test "rejects very short value" do
      assert {:error, msg} = KeyValidation.validate_email_key("ab", "smtp", "relay")
      assert msg =~ "too short"
    end

    test "rejects empty" do
      assert {:error, msg} = KeyValidation.validate_email_key("", "mailersend", "api_key")
      assert msg =~ "Please enter"
    end
  end
end
