import { describe, it, expect } from "bun:test";
import { msToDuration, secondsToDuration } from "./time";

describe("msToDuration", () => {
  it("should convert milliseconds to duration with all units", () => {
    // 1 day, 2 hours, 3 minutes, 4 seconds = 93784000 ms
    const ms = 1 * 24 * 60 * 60 * 1000 + 2 * 60 * 60 * 1000 + 3 * 60 * 1000 + 4 * 1000;
    const result = msToDuration(ms);

    expect(result).toEqual({
      days: 1,
      hours: 2,
      minutes: 3,
      seconds: 4
    });
  });

  it("should handle zero milliseconds", () => {
    const result = msToDuration(0);

    expect(result).toEqual({
      days: 0,
      hours: 0,
      minutes: 0,
      seconds: 0
    });
  });

  it("should handle only seconds", () => {
    const result = msToDuration(5000); // 5 seconds

    expect(result).toEqual({
      days: 0,
      hours: 0,
      minutes: 0,
      seconds: 5
    });
  });

  it("should handle only minutes", () => {
    const result = msToDuration(2 * 60 * 1000); // 2 minutes

    expect(result).toEqual({
      days: 0,
      hours: 0,
      minutes: 2,
      seconds: 0
    });
  });

  it("should handle only hours", () => {
    const result = msToDuration(3 * 60 * 60 * 1000); // 3 hours

    expect(result).toEqual({
      days: 0,
      hours: 3,
      minutes: 0,
      seconds: 0
    });
  });

  it("should handle only days", () => {
    const result = msToDuration(2 * 24 * 60 * 60 * 1000); // 2 days

    expect(result).toEqual({
      days: 2,
      hours: 0,
      minutes: 0,
      seconds: 0
    });
  });

  it("should handle partial seconds (floor down)", () => {
    const result = msToDuration(1500); // 1.5 seconds

    expect(result).toEqual({
      days: 0,
      hours: 0,
      minutes: 0,
      seconds: 1
    });
  });

  it("should handle large values", () => {
    // 365 days, 5 hours, 30 minutes, 45 seconds
    const ms = 365 * 24 * 60 * 60 * 1000 + 5 * 60 * 60 * 1000 + 30 * 60 * 1000 + 45 * 1000;
    const result = msToDuration(ms);

    expect(result).toEqual({
      days: 365,
      hours: 5,
      minutes: 30,
      seconds: 45
    });
  });

  it("should handle rollover correctly", () => {
    // 25 hours should be 1 day, 1 hour
    const ms = 25 * 60 * 60 * 1000;
    const result = msToDuration(ms);

    expect(result).toEqual({
      days: 1,
      hours: 1,
      minutes: 0,
      seconds: 0
    });
  });

  it("should handle 61 minutes correctly", () => {
    // 61 minutes should be 1 hour, 1 minute
    const ms = 61 * 60 * 1000;
    const result = msToDuration(ms);

    expect(result).toEqual({
      days: 0,
      hours: 1,
      minutes: 1,
      seconds: 0
    });
  });

  it("should handle negative values", () => {
    const result = msToDuration(-5000);

    expect(result).toEqual({
      days: -1,
      hours: -1,
      minutes: -1,
      seconds: -5
    });
  });
});

describe("secondsToDuration", () => {
  it("should convert seconds to duration with all units", () => {
    // 1 day, 2 hours, 3 minutes, 4 seconds = 93784 seconds
    const seconds = 1 * 24 * 60 * 60 + 2 * 60 * 60 + 3 * 60 + 4;
    const result = secondsToDuration(seconds);

    expect(result).toEqual({
      days: 1,
      hours: 2,
      minutes: 3,
      seconds: 4
    });
  });

  it("should handle zero seconds", () => {
    const result = secondsToDuration(0);

    expect(result).toEqual({
      days: 0,
      hours: 0,
      minutes: 0,
      seconds: 0
    });
  });

  it("should handle only seconds", () => {
    const result = secondsToDuration(45);

    expect(result).toEqual({
      days: 0,
      hours: 0,
      minutes: 0,
      seconds: 45
    });
  });

  it("should handle only minutes", () => {
    const result = secondsToDuration(5 * 60); // 5 minutes

    expect(result).toEqual({
      days: 0,
      hours: 0,
      minutes: 5,
      seconds: 0
    });
  });

  it("should handle only hours", () => {
    const result = secondsToDuration(4 * 60 * 60); // 4 hours

    expect(result).toEqual({
      days: 0,
      hours: 4,
      minutes: 0,
      seconds: 0
    });
  });

  it("should handle only days", () => {
    const result = secondsToDuration(3 * 24 * 60 * 60); // 3 days

    expect(result).toEqual({
      days: 3,
      hours: 0,
      minutes: 0,
      seconds: 0
    });
  });

  it("should handle decimal seconds (floor down)", () => {
    const result = secondsToDuration(59.7);

    expect(result).toEqual({
      days: 0,
      hours: 0,
      minutes: 0,
      seconds: 59
    });
  });

  it("should handle large values", () => {
    // 100 days, 12 hours, 45 minutes, 30 seconds
    const seconds = 100 * 24 * 60 * 60 + 12 * 60 * 60 + 45 * 60 + 30;
    const result = secondsToDuration(seconds);

    expect(result).toEqual({
      days: 100,
      hours: 12,
      minutes: 45,
      seconds: 30
    });
  });

  it("should handle rollover correctly", () => {
    // 25 hours should be 1 day, 1 hour
    const seconds = 25 * 60 * 60;
    const result = secondsToDuration(seconds);

    expect(result).toEqual({
      days: 1,
      hours: 1,
      minutes: 0,
      seconds: 0
    });
  });

  it("should handle 61 minutes correctly", () => {
    // 61 minutes should be 1 hour, 1 minute
    const seconds = 61 * 60;
    const result = secondsToDuration(seconds);

    expect(result).toEqual({
      days: 0,
      hours: 1,
      minutes: 1,
      seconds: 0
    });
  });

  it("should handle 61 seconds correctly", () => {
    // 61 seconds should be 1 minute, 1 second
    const result = secondsToDuration(61);

    expect(result).toEqual({
      days: 0,
      hours: 0,
      minutes: 1,
      seconds: 1
    });
  });

  it("should handle negative values", () => {
    const result = secondsToDuration(-3665); // -1 hour, -1 minute, -5 seconds

    expect(result).toEqual({
      days: -1,
      hours: -2,
      minutes: -2,
      seconds: -5
    });
  });

  it("should match msToDuration for equivalent values", () => {
    const seconds = 3665; // 1 hour, 1 minute, 5 seconds
    const ms = seconds * 1000;

    const fromSeconds = secondsToDuration(seconds);
    const fromMs = msToDuration(ms);

    expect(fromSeconds).toEqual(fromMs);
  });
});
