/**
 * Test formatting integers with special time formats like "hh:mm".
 */
USING OpenEdge.Core.Assert.

ROUTINE-LEVEL ON ERROR UNDO, THROW.

CLASS unittests.base.numeric.TestIntegerFormattedAsTime:

   /**
    * Test legacy time formats for integer values
    */
   @Test.
   METHOD PUBLIC VOID TestTimeFormats():
      DEFINE VARIABLE i3_2_1 AS INTEGER NO-UNDO.
      i3_2_1 = 3 * 3600 + 2 * 60 + 1.

      DEFINE VARIABLE i13_2_1 AS INTEGER NO-UNDO.
      i13_2_1 = 13 * 3600 + 2 * 60 + 1.

      DEFINE VARIABLE i24_2_1 AS INTEGER NO-UNDO.
      i24_2_1 = 24 * 3600 + 2 * 60 + 1.

      DEFINE VARIABLE i13_3 AS INTEGER NO-UNDO.
      i13_3 = 13 * 60 + 3.

      DEFINE VARIABLE i13_2_3 AS INTEGER NO-UNDO.
      i13_2_3 = 13 * 3600 + 2 * 60 + 3.

      // prefix '+hh:mm' with no suffix, hour = 3
      test(i3_2_1, "+hh:mm", "+02:01").

      // prefix '+hh:mm' with no suffix, hour = 24 → rolls over
      test(i24_2_1, "+hh:mm", "+02:01").

      // prefix '+hh:mm' with suffix 'a' / 'A' / 'aa'
      test(i3_2_1, "+hh:mma", "+02:01a").
      test(i24_2_1, "+hh:mma", "+02:01a").
      test(i3_2_1, "+hh:mmA", "+02:01A").
      test(i24_2_1, "+hh:mmA", "+02:01A").
      test(i3_2_1, "+hh:mmaa", "+02:01aa").
      test(i24_2_1, "+hh:mmaa", "+02:01aa").

      // prefix 'hh:mm:ss' with no suffix
      test(i3_2_1, "hh:mm:ss", "03:02:01").
      test(i24_2_1, "hh:mm:ss", "00:02:01").

      // prefix 'hh:mm:ss' with suffix 'a' / 'A' (12-hour + AM/PM)
      test(i3_2_1, "hh:mm:ssa", " 3:02:01a").
      test(i24_2_1, "hh:mm:ssa", "12:02:01a").
      test(i3_2_1, "hh:mm:ssA", " 3:02:01A").
      test(i24_2_1, "hh:mm:ssA", "12:02:01A").

      // 13:02:03 variations
      test(i13_2_3, "hh:mm", "13:02").
      test(i13_2_3, "hh:mm:SS", "13:02:03").
      test(i13_2_3, "hh:mma", " 1:02p").
      test(i13_2_3, "hh:mm:SSa", " 1:02:03p").

      // Large hour values
      test(59 * 60 + 3, "+hh:mm", "+59:03").
      test(60 * 60 + 3, "+hh:mm", "+00:03").

      // High hour without rollover issues
      test(1000 * 3600 + 2 * 60 + 3, "hh:mm:ss", "16:02:03").
   END METHOD.

   /**
    * Additional edge cases: midnight/noon, negative, large values, literal suffixes
    */
   @Test.
   METHOD PUBLIC VOID TestTimeFormatsEdgeCases():
      // Midnight / noon / rollover
      test(0,        "hh:mm:ss A", "12:00:00 A").
      test(12 * 3600,"hh:mm:ss P", "12:00:00 P").
      test(24 * 3600,"hh:mm:ss",   "00:00:00").
      test(48 * 3600,"hh:mm:ss",   "00:00:00").

      /**
      * Negative seconds cases – backward wrap-around for non-plus formats,
      * negative cumulative time display for + prefix formats.
      */
      // Non-plus formats: backward wrap from midnight (modulo 86400)
      test(-60,      "hh:mm",     "23:59").
      test(-20000,   "hh:mm",     "18:26").
      test(-100000,  "hh:mm",     "20:13").

      test(-1,       "hh:mm:ss",  "23:59:59").
      test(-60,      "hh:mm:ss",  "23:59:00").
      test(-20000,   "hh:mm:ss",  "18:26:40").
      test(-100000,  "hh:mm:ss",  "20:13:20").
      test(-200000,  "hh:mm:ss",  "16:26:40").

      // + prefix formats: shows negative cumulative time (no modulo on hours)
      test(-1,       "+hh:mm",    "-00:01").
      test(-60,      "+hh:mm",    "-01:00").
      test(-20000,   "+hh:mm",    "-33:20").
      test(-100000,  "+hh:mm",    "-46:40").
      test(-200000,  "+hh:mm",    "-33:20").

      // Large values: modulo 86400 for time-of-day
      test(123456,        "hh:mm:ss", "10:17:36").
      test(1000001234,    "hh:mm:ss", "02:07:14").

      // + prefix shows cumulative time (no modulo on hours)
      test(1000001234,    "+hh:mm",   "+07:14").

      // Midnight display: 24h vs 12h
      test(0, "hh:mmxyz",     "00:00xyz").
      test(0, "hh:mmabc",     "12:00abc").
      test(0, "hh:mm:ssdef",  "00:00:00def").

      // Multiple trailing colons or mixed literals
      test(13 * 3600 + 2 * 60 + 3, "hh:mm:ss::",   "13:02:03::").
      test(13 * 3600 + 2 * 60 + 3, "hh:mm:ssa!!",  " 1:02:03p!!").

      // AM/PM at boundaries
      test(11 * 3600 + 59 * 60 + 59 + 12 * 3600, "hh:mm:ss A", "11:59:59 P").
      test(24 * 3600,                            "hh:mm:ss A", "12:00:00 A").
      test(0, "hh:mm  ", "00:00  ").
      test(0, "hh:mm s d f ", "00:00 s d f ").
      
      test(0, "+hh:mm  ", "+00:00  ").
      test(0, "+hh:mm s d f ", "+00:00 s d f ").
   END METHOD.

   /**
    * Execute the test, compare result with the expected value.
    */
   METHOD PRIVATE VOID test(INPUT v AS INTEGER, INPUT fmt AS CHARACTER, INPUT expectedResult AS CHARACTER):
      DEFINE VARIABLE rc AS CHARACTER NO-UNDO.
      rc = STRING(v, fmt).
      Assert:Equals(expectedResult, rc).
      Assert:Equals(LENGTH(expectedResult), LENGTH(rc)).
   END METHOD.

   /**
    * Verify that decimal values cannot be formatted with legacy time formats, expecting an error.
    */
   @Test.
   METHOD PUBLIC VOID TestFormattingDecimalWithTimeFormatErrors():
      DEFINE VARIABLE rc AS CHARACTER NO-UNDO.
      rc = STRING(1.0, "+hh:ss") NO-ERROR.
      Assert:Equals(22, ERROR-STATUS:GET-NUMBER(1)).
   END METHOD.

END CLASS.