// The Lucia project.
// Copyright 2026-2026 DSP, inc.  All rights reserved.
// Authors:
//   imacat.yang@dsp.im (imacat), 2026/03/05

import { describe, it, expect } from "vitest";
import {
  getTimeLabel,
  simpleTimeLabel,
  followTimeLabel,
  getStepSizeOfYTicks,
  getYTicksByIndex,
  setTimeStringFormatBaseOnTimeDifference,
  mapTimestampToAxisTicksByFormat,
} from "@/module/timeLabel.js";

describe("getTimeLabel", () => {
  it("returns days for >= 86400 seconds", () => {
    expect(getTimeLabel(86400)).toBe("1 days");
    expect(getTimeLabel(172800)).toBe("2 days");
  });

  it("returns hours for >= 3600 seconds", () => {
    expect(getTimeLabel(3600)).toBe("1 hrs");
    expect(getTimeLabel(7200)).toBe("2 hrs");
  });

  it("returns minutes for >= 60 seconds", () => {
    expect(getTimeLabel(60)).toBe("1 mins");
    expect(getTimeLabel(120)).toBe("2 mins");
  });

  it("returns seconds for < 60", () => {
    expect(getTimeLabel(30)).toBe("30 sec");
  });

  it("returns 0 sec for zero", () => {
    expect(getTimeLabel(0)).toBe("0 sec");
  });

  it("respects fixedNumber parameter", () => {
    expect(getTimeLabel(5400, 1)).toBe("1.5 hrs");
  });
});

describe("simpleTimeLabel", () => {
  it("returns days with d suffix", () => {
    expect(simpleTimeLabel(86400)).toBe("1d");
  });

  it("returns hours with h suffix", () => {
    expect(simpleTimeLabel(3600)).toBe("1h");
    expect(simpleTimeLabel(7200)).toBe("2h");
  });

  it("returns minutes with m suffix", () => {
    expect(simpleTimeLabel(60)).toBe("1m");
    expect(simpleTimeLabel(120)).toBe("2m");
  });

  it("returns seconds with s suffix for small values", () => {
    expect(simpleTimeLabel(30)).toBe("30s");
  });

  it("returns 0s for zero", () => {
    expect(simpleTimeLabel(0)).toBe("0s");
  });

  it("correctly calculates hours for values between 1h and 1d", () => {
    // 5 hours = 18000 seconds -> should be "5h"
    expect(simpleTimeLabel(18000)).toBe("5h");
  });

  it("correctly calculates minutes for values between 1m and 1h", () => {
    // 30 minutes = 1800 seconds -> should be "30m"
    expect(simpleTimeLabel(1800)).toBe("30m");
  });
});

describe("followTimeLabel", () => {
  it("uses day unit when max > 1 day", () => {
    // max = 100000 (> 86400), second = 86400 => 1d
    expect(followTimeLabel(86400, 100000)).toBe("1d");
  });

  it("uses hour unit when max > 1 hour", () => {
    // max = 7200 (> 3600), second = 3600 => 1h
    expect(followTimeLabel(3600, 7200)).toBe("1h");
  });

  it("uses minute unit when max > 1 minute", () => {
    // max = 120 (> 60), second = 60 => 1m
    expect(followTimeLabel(60, 120)).toBe("1m");
  });

  it("uses second unit when max <= 60", () => {
    expect(followTimeLabel(30, 50)).toBe("30s");
  });

  it("returns 0 without decimals when value is 0", () => {
    expect(followTimeLabel(0, 7200, 2)).toBe("0h");
  });
});

describe("getStepSizeOfYTicks", () => {
  it("returns object with resultStepSize and unitToUse", () => {
    const result = getStepSizeOfYTicks(7200, 5);
    expect(result).toHaveProperty("resultStepSize");
    expect(result).toHaveProperty("unitToUse");
    expect(result.unitToUse).toBe("h");
  });

  it("uses day unit for large values", () => {
    const result = getStepSizeOfYTicks(200000, 5);
    expect(result.unitToUse).toBe("d");
  });

  it("uses second unit for small values", () => {
    const result = getStepSizeOfYTicks(30, 5);
    expect(result.unitToUse).toBe("s");
  });
});

describe("getYTicksByIndex", () => {
  it("formats tick label with unit", () => {
    expect(getYTicksByIndex(2, 3, "h")).toBe("6.0h");
  });

  it("truncates to 1 decimal place", () => {
    expect(getYTicksByIndex(1.5, 1, "h")).toBe("1.5h");
  });
});

describe("setTimeStringFormatBaseOnTimeDifference", () => {
  it("returns seconds format for < 60s difference", () => {
    expect(setTimeStringFormatBaseOnTimeDifference(0, 30)).toBe("HH:mm:ss");
  });

  it("returns minute format for < 3600s difference", () => {
    expect(setTimeStringFormatBaseOnTimeDifference(0, 1800)).toBe(
      "MM/DD HH:mm",
    );
  });

  it("returns hour format for < 86400s difference", () => {
    expect(setTimeStringFormatBaseOnTimeDifference(0, 43200)).toBe(
      "MM/DD HH:mm",
    );
  });

  it("returns day format for < 30 days difference", () => {
    expect(setTimeStringFormatBaseOnTimeDifference(0, 864000)).toBe(
      "YYYY/MM/DD",
    );
  });

  it("returns month format for >= 30 days difference", () => {
    expect(setTimeStringFormatBaseOnTimeDifference(0, 5000000)).toBe(
      "YYYY/MM/DD",
    );
  });
});

describe("mapTimestampToAxisTicksByFormat", () => {
  it("formats timestamps with given format", () => {
    const ts = [new Date("2023-01-15").getTime()];
    const result = mapTimestampToAxisTicksByFormat(ts, "YYYY/MM/DD");
    expect(result[0]).toBe("2023/01/15");
  });

  it("returns empty array for falsy input", () => {
    expect(mapTimestampToAxisTicksByFormat(null, "YYYY")).toEqual([]);
  });
});
