import { describe, it, expect, vi } from "vitest"

// Mock server-only and db dependencies so the module loads in jsdom
vi.mock("@/shared/db", () => ({
  db: {
    delete: vi.fn(),
    select: vi.fn(),
  },
}))
vi.mock("@/shared/db/schema", () => ({
  auditLogs: { createdAt: "created_at" },
  loginLogs: { createdAt: "created_at" },
  dataChangeLogs: { createdAt: "created_at" },
}))
vi.mock("@/modules/settings/data-access-system-settings", () => ({
  getSystemSetting: vi.fn(),
  upsertSystemSetting: vi.fn(),
}))

import {
  calculateRetentionThreshold,
  isValidRetentionDays,
  DEFAULT_RETENTION_DAYS,
  MIN_RETENTION_DAYS,
  MAX_RETENTION_DAYS,
} from "./retention"

describe("calculateRetentionThreshold", () => {
  it("should return a date N days before the reference date", () => {
    const now = new Date("2026-06-24T12:00:00Z")
    const threshold = calculateRetentionThreshold(180, now)
    const expected = new Date("2025-12-26T12:00:00Z")
    expect(threshold.toISOString()).toBe(expected.toISOString())
  })

  it("should return today minus retentionDays for 0 days", () => {
    const now = new Date("2026-06-24T00:00:00Z")
    const threshold = calculateRetentionThreshold(0, now)
    expect(threshold.toISOString()).toBe(now.toISOString())
  })

  it("should handle leap year correctly", () => {
    const now = new Date("2024-03-01T00:00:00Z")
    const threshold = calculateRetentionThreshold(1, now)
    const expected = new Date("2024-02-29T00:00:00Z")
    expect(threshold.toISOString()).toBe(expected.toISOString())
  })

  it("should use current time when no reference date provided", () => {
    const before = new Date()
    const threshold = calculateRetentionThreshold(90)
    const after = new Date()
    const expectedMin = new Date(before)
    expectedMin.setDate(expectedMin.getDate() - 90)
    const expectedMax = new Date(after)
    expectedMax.setDate(expectedMax.getDate() - 90)
    expect(threshold.getTime()).toBeGreaterThanOrEqual(expectedMin.getTime())
    expect(threshold.getTime()).toBeLessThanOrEqual(expectedMax.getTime())
  })
})

describe("isValidRetentionDays", () => {
  it("should accept values within the valid range", () => {
    expect(isValidRetentionDays(MIN_RETENTION_DAYS)).toBe(true)
    expect(isValidRetentionDays(90)).toBe(true)
    expect(isValidRetentionDays(180)).toBe(true)
    expect(isValidRetentionDays(365)).toBe(true)
    expect(isValidRetentionDays(MAX_RETENTION_DAYS)).toBe(true)
  })

  it("should reject values below the minimum", () => {
    expect(isValidRetentionDays(0)).toBe(false)
    expect(isValidRetentionDays(1)).toBe(false)
    expect(isValidRetentionDays(MIN_RETENTION_DAYS - 1)).toBe(false)
  })

  it("should reject values above the maximum", () => {
    expect(isValidRetentionDays(MAX_RETENTION_DAYS + 1)).toBe(false)
    expect(isValidRetentionDays(99999)).toBe(false)
  })

  it("should reject non-integer values", () => {
    expect(isValidRetentionDays(90.5)).toBe(false)
    expect(isValidRetentionDays(100.1)).toBe(false)
    expect(isValidRetentionDays(NaN)).toBe(false)
    expect(isValidRetentionDays(Infinity)).toBe(false)
  })

  it("should have DEFAULT_RETENTION_DAYS within valid range", () => {
    expect(isValidRetentionDays(DEFAULT_RETENTION_DAYS)).toBe(true)
  })
})
