defmodule Towerops.Devices.VersionComparatorTest do
  use ExUnit.Case, async: true

  alias Towerops.Devices.VersionComparator

  describe "compare/2" do
    test "returns :eq for equal versions" do
      assert VersionComparator.compare("7.14.1", "7.14.1") == :eq
    end

    test "returns :lt when first version is older (major)" do
      assert VersionComparator.compare("6.14.1", "7.14.1") == :lt
    end

    test "returns :gt when first version is newer (major)" do
      assert VersionComparator.compare("8.14.1", "7.14.1") == :gt
    end

    test "returns :lt when first version is older (minor)" do
      assert VersionComparator.compare("7.13.1", "7.14.1") == :lt
    end

    test "returns :gt when first version is newer (minor)" do
      assert VersionComparator.compare("7.15.1", "7.14.1") == :gt
    end

    test "returns :lt when first version is older (patch)" do
      assert VersionComparator.compare("7.14.0", "7.14.1") == :lt
    end

    test "returns :gt when first version is newer (patch)" do
      assert VersionComparator.compare("7.14.2", "7.14.1") == :gt
    end

    test "handles missing patch version (pads with 0)" do
      assert VersionComparator.compare("7.14", "7.14.0") == :eq
      assert VersionComparator.compare("7.14", "7.14.1") == :lt
    end

    test "handles missing minor and patch versions (pads with 0)" do
      assert VersionComparator.compare("7", "7.0.0") == :eq
      assert VersionComparator.compare("7", "8.0.0") == :lt
    end

    test "strips 'v' prefix (lowercase)" do
      assert VersionComparator.compare("v7.14.1", "7.14.1") == :eq
    end

    test "strips 'V' prefix (uppercase)" do
      assert VersionComparator.compare("V7.14.1", "7.14.1") == :eq
    end

    test "trims whitespace" do
      assert VersionComparator.compare("  7.14.1  ", "7.14.1") == :eq
    end

    test "ignores suffixes after hyphen" do
      assert VersionComparator.compare("7.14.1-beta", "7.14.1") == :eq
      assert VersionComparator.compare("7.14.1-beta", "7.14.1-release") == :eq
    end

    test "ignores suffixes after space" do
      assert VersionComparator.compare("7.14.1 beta", "7.14.1") == :eq
    end

    test "handles leading zeros" do
      assert VersionComparator.compare("007.014.001", "7.14.1") == :eq
    end

    test "handles empty string as invalid (falls back to 0.0.0)" do
      assert VersionComparator.compare("", "1.0.0") == :lt
      assert VersionComparator.compare("1.0.0", "") == :gt
      assert VersionComparator.compare("", "") == :eq
    end

    test "handles non-numeric parts as invalid (falls back to 0.0.0)" do
      assert VersionComparator.compare("abc", "1.0.0") == :lt
      assert VersionComparator.compare("1.0.0", "abc") == :gt
      assert VersionComparator.compare("7.abc.1", "7.0.1") == :lt
    end

    test "handles versions with dots but no numbers as invalid" do
      assert VersionComparator.compare("v.1.2", "1.2.0") == :lt
    end

    test "handles 4-part versions as invalid (falls back to 0.0.0)" do
      assert VersionComparator.compare("7.14.1.2", "7.14.1") == :lt
      assert VersionComparator.compare("7.14.1", "7.14.1.2") == :gt
    end

    test "handles 5-part versions as invalid (falls back to 0.0.0)" do
      assert VersionComparator.compare("7.14.1.2.3", "7.14.1") == :lt
      assert VersionComparator.compare("7.14.1", "7.14.1.2.3") == :gt
    end

    test "handles negative numbers as invalid (falls back to 0.0.0)" do
      assert VersionComparator.compare("7.-1.0", "7.0.0") == :lt
      assert VersionComparator.compare("7.0.0", "7.-1.0") == :gt
    end

    test "compares invalid versions as equal" do
      assert VersionComparator.compare("abc", "xyz") == :eq
      assert VersionComparator.compare("7.14.1.2.3", "1.2.3.4.5") == :eq
    end
  end

  describe "newer?/2" do
    test "returns true when second version is newer" do
      assert VersionComparator.newer?("7.14.1", "7.14.2") == true
      assert VersionComparator.newer?("7.14.1", "7.15.0") == true
      assert VersionComparator.newer?("7.14.1", "8.0.0") == true
    end

    test "returns false when second version is older" do
      assert VersionComparator.newer?("7.14.2", "7.14.1") == false
      assert VersionComparator.newer?("7.15.0", "7.14.1") == false
      assert VersionComparator.newer?("8.0.0", "7.14.1") == false
    end

    test "returns false when versions are equal" do
      assert VersionComparator.newer?("7.14.1", "7.14.1") == false
    end

    test "handles version prefixes and suffixes" do
      assert VersionComparator.newer?("v7.14.1-beta", "V7.14.2") == true
      assert VersionComparator.newer?("7.14.2", "v7.14.1-beta") == false
    end

    test "handles invalid versions" do
      assert VersionComparator.newer?("abc", "1.0.0") == true
      assert VersionComparator.newer?("1.0.0", "abc") == false
      assert VersionComparator.newer?("abc", "xyz") == false
    end
  end
end
