require "./spec_helper"

describe JosieHealth::Utils::Recurrence do
  describe ".parse_interval" do
    it "parses weeks (1w)" do
      JosieHealth::Utils::Recurrence.parse_interval("1w").should eq(604800)
    end

    it "parses days (5d)" do
      JosieHealth::Utils::Recurrence.parse_interval("5d").should eq(432000)
    end

    it "parses hours (2h)" do
      JosieHealth::Utils::Recurrence.parse_interval("2h").should eq(7200)
    end

    it "parses minutes (30m)" do
      JosieHealth::Utils::Recurrence.parse_interval("30m").should eq(1800)
    end

    it "parses seconds (45s)" do
      JosieHealth::Utils::Recurrence.parse_interval("45s").should eq(45)
    end

    it "parses combined units (1h30m)" do
      JosieHealth::Utils::Recurrence.parse_interval("1h30m").should eq(5400)
    end

    it "parses complex combined (1w2d3h)" do
      JosieHealth::Utils::Recurrence.parse_interval("1w2d3h").should eq(788400)
    end

    it "is case insensitive (1H30M)" do
      JosieHealth::Utils::Recurrence.parse_interval("1H30M").should eq(5400)
    end

    it "parses decimal weeks (1.5w)" do
      JosieHealth::Utils::Recurrence.parse_interval("1.5w").should eq(907200)
    end

    it "parses decimal hours (2.5h)" do
      JosieHealth::Utils::Recurrence.parse_interval("2.5h").should eq(9000)
    end

    it "parses decimal days (0.5d)" do
      JosieHealth::Utils::Recurrence.parse_interval("0.5d").should eq(43200)
    end

    it "returns nil for invalid pattern" do
      JosieHealth::Utils::Recurrence.parse_interval("invalid").should be_nil
    end

    it "returns nil for empty string" do
      JosieHealth::Utils::Recurrence.parse_interval("").should be_nil
    end

    it "returns nil for day names" do
      JosieHealth::Utils::Recurrence.parse_interval("monday").should be_nil
    end
  end

  describe ".parse_day_of_week" do
    it "parses monday" do
      JosieHealth::Utils::Recurrence.parse_day_of_week("monday").should eq(1)
    end

    it "parses friday" do
      JosieHealth::Utils::Recurrence.parse_day_of_week("friday").should eq(5)
    end

    it "parses sunday" do
      JosieHealth::Utils::Recurrence.parse_day_of_week("sunday").should eq(7)
    end

    it "is case insensitive (MONDAY)" do
      JosieHealth::Utils::Recurrence.parse_day_of_week("MONDAY").should eq(1)
    end

    it "returns nil for invalid day" do
      JosieHealth::Utils::Recurrence.parse_day_of_week("notaday").should be_nil
    end

    it "returns nil for interval patterns" do
      JosieHealth::Utils::Recurrence.parse_day_of_week("1h").should be_nil
    end
  end

  describe ".valid?" do
    it "returns true for interval patterns" do
      JosieHealth::Utils::Recurrence.valid?("1h").should be_true
    end

    it "returns true for day names" do
      JosieHealth::Utils::Recurrence.valid?("monday").should be_true
    end

    it "returns false for empty string" do
      JosieHealth::Utils::Recurrence.valid?("").should be_false
    end

    it "returns false for invalid patterns" do
      JosieHealth::Utils::Recurrence.valid?("invalid").should be_false
    end
  end

  describe ".next_trigger" do
    it "adds interval to current time" do
      base_time = Time.utc(2025, 1, 1, 12, 0, 0)
      result = JosieHealth::Utils::Recurrence.next_trigger("1h", base_time)
      result.should eq(Time.utc(2025, 1, 1, 13, 0, 0).to_unix)
    end

    it "adds combined intervals" do
      base_time = Time.utc(2025, 1, 1, 12, 0, 0)
      result = JosieHealth::Utils::Recurrence.next_trigger("1d12h", base_time)
      result.should eq(Time.utc(2025, 1, 3, 0, 0, 0).to_unix)
    end

    it "calculates next monday from wednesday" do
      base_time = Time.utc(2025, 1, 1, 12, 0, 0) # Wednesday
      result = JosieHealth::Utils::Recurrence.next_trigger("monday", base_time)
      expected = Time.utc(2025, 1, 6, 12, 0, 0) # Next Monday
      result.should eq(expected.to_unix)
    end

    it "calculates next friday from wednesday" do
      base_time = Time.utc(2025, 1, 1, 12, 0, 0) # Wednesday
      result = JosieHealth::Utils::Recurrence.next_trigger("friday", base_time)
      expected = Time.utc(2025, 1, 3, 12, 0, 0) # Friday
      result.should eq(expected.to_unix)
    end

    it "skips to next week if same day" do
      base_time = Time.utc(2025, 1, 1, 12, 0, 0) # Wednesday
      result = JosieHealth::Utils::Recurrence.next_trigger("wednesday", base_time)
      expected = Time.utc(2025, 1, 8, 12, 0, 0) # Next Wednesday
      result.should eq(expected.to_unix)
    end

    it "returns current time for invalid pattern" do
      base_time = Time.utc(2025, 1, 1, 12, 0, 0)
      result = JosieHealth::Utils::Recurrence.next_trigger("invalid", base_time)
      result.should eq(base_time.to_unix)
    end

    it "uses Time.utc as default" do
      result = JosieHealth::Utils::Recurrence.next_trigger("1h")
      result.should be > Time.utc.to_unix
    end
  end

  describe ".format_compact" do
    it "formats weeks" do
      JosieHealth::Utils::Recurrence.format_compact(604800).should eq("1w")
    end

    it "formats days" do
      JosieHealth::Utils::Recurrence.format_compact(86400).should eq("1d")
    end

    it "formats hours" do
      JosieHealth::Utils::Recurrence.format_compact(3600).should eq("1h")
    end

    it "formats minutes" do
      JosieHealth::Utils::Recurrence.format_compact(60).should eq("1m")
    end

    it "formats seconds only" do
      JosieHealth::Utils::Recurrence.format_compact(45).should eq("45s")
    end

    it "formats combined (1d12h)" do
      JosieHealth::Utils::Recurrence.format_compact(129600).should eq("1d12h")
    end

    it "formats complex combined (1w2d3h30m)" do
      JosieHealth::Utils::Recurrence.format_compact(790200).should eq("1w2d3h30m")
    end
  end

  describe ".format_human" do
    it "formats single week" do
      JosieHealth::Utils::Recurrence.format_human(604800).should eq("1 week")
    end

    it "formats multiple weeks" do
      JosieHealth::Utils::Recurrence.format_human(1209600).should eq("2 weeks")
    end

    it "formats single day" do
      JosieHealth::Utils::Recurrence.format_human(86400).should eq("1 day")
    end

    it "formats multiple days" do
      JosieHealth::Utils::Recurrence.format_human(172800).should eq("2 days")
    end

    it "formats single hour" do
      JosieHealth::Utils::Recurrence.format_human(3600).should eq("1 hour")
    end

    it "formats combined (1 day, 1 hour, 1 minute)" do
      JosieHealth::Utils::Recurrence.format_human(90060).should eq("1 day, 1 hour, 1 minute")
    end

    it "formats seconds when only seconds" do
      JosieHealth::Utils::Recurrence.format_human(45).should eq("45 seconds")
    end

    it "formats single second" do
      JosieHealth::Utils::Recurrence.format_human(1).should eq("1 second")
    end
  end

  describe ".format" do
    it "formats interval patterns compactly" do
      JosieHealth::Utils::Recurrence.format("1h30m").should eq("1h30m")
    end

    it "capitalizes day names" do
      JosieHealth::Utils::Recurrence.format("monday").should eq("Monday")
    end

    it "capitalizes uppercase day names" do
      JosieHealth::Utils::Recurrence.format("FRIDAY").should eq("Friday")
    end

    it "returns invalid pattern as-is" do
      JosieHealth::Utils::Recurrence.format("invalid").should eq("invalid")
    end
  end
end
