# frozen_string_literal: true

require "rails_helper"

RSpec.describe TrackingLink, type: :model do

  let(:user) { create(:user) }

  context "validations" do

    subject {
      TrackingLink.new(
        destination_url: "https://www.google.com",
        slug: "foo",
        creator: user,
      )
    }

    it { is_expected.to validate_presence_of(:destination_url) }
    it { is_expected.to validate_length_of(:destination_url).is_at_most(1000) }

    it { is_expected.to validate_presence_of(:slug) }
    it { is_expected.to validate_length_of(:slug).is_at_most(256) }

    it "should validate that slugs only contain letters, numbers, and hyphens" do
      is_expected.to allow_value("foo-BAR-1234").for(:slug)
      is_expected.not_to allow_value(" ").for(:slug)
      is_expected.not_to allow_value("").for(:slug)
      is_expected.not_to allow_value("!").for(:slug)
      is_expected.not_to allow_value("?").for(:slug)
    end

    it "should validate that destination url is a url " do
      is_expected.to allow_value("https://example.com").for(:destination_url)
      is_expected.to allow_value("https://www.example.com").for(:destination_url)
      is_expected.to allow_value("http://www.bar.baz.example.com").for(:destination_url)
      is_expected.to allow_value("http://www.bar.baz.example.com").for(:destination_url)

      # Longest TLD per https://stackoverflow.com/questions/9238640/how-long-can-a-tld-possibly-be
      is_expected.to allow_value("http://www.bar.vermögensberatung/foo/bar/baz").for(:destination_url)

      is_expected.not_to allow_value(" ").for(:destination_url)
      is_expected.not_to allow_value("aa").for(:destination_url)
      is_expected.not_to allow_value("something.com").for(:slug)
      is_expected.not_to allow_value("!").for(:slug)
      is_expected.not_to allow_value("?").for(:slug)
    end

    context "when published" do
      subject {
        TrackingLink.new(
          destination_url: "https://www.google.com",
          slug: "foo",
          creator: user,
          status: :published,
        )
      }

      it "should validate slug uniqueness" do
        is_expected.to validate_uniqueness_of(:slug)
      end

      it "an publisher is required" do
        is_expected.to validate_presence_of(:publisher)
      end

      it "the publish time is required" do
        is_expected.to validate_presence_of(:published_at)
      end
    end

    context "when hidden" do
      subject {
        TrackingLink.new(
          destination_url: "https://www.google.com",
          slug: "foo",
          creator: user,
          status: "hidden",
          publisher: user,
          hider: user,
          hidden_at: Time.now,
          published_at: Time.now
        )
      }

      it "validates the presence of a hider" do
        is_expected.to validate_presence_of(:hider)
      end

      it "validates the presence of hidden_at" do
        is_expected.to validate_presence_of(:hidden_at)
      end
    end
  end

  describe "associations" do
    subject {
      TrackingLink.new(
        destination_url: "https://www.google.com",
        slug: "foo",
        creator: user,
      )
    }

    it { is_expected.to have_many(:tracking_link_redirect_events) }
    it { is_expected.to belong_to(:creator).with_foreign_key(:creator_id).class_name("User") }
    it { is_expected.to belong_to(:publisher).with_foreign_key(:publisher_id).class_name("User") }
    it { is_expected.to belong_to(:hider).with_foreign_key(:hider_id).class_name("User") }
  end

  describe "all fields that could change the redirect url are readonly" do
    it { is_expected.to have_readonly_attribute(:slug) }
  end

end
