import { db } from "../db";
import type { PayRate } from "../types";
import { todayIso } from "../util/date";

/** The rate is the most recent one with valid_from <= the given date — a new rate implicitly ends the previous one. */
export function getRateAt(employeeId: number, dateOnly: string): number {
  const row = db
    .prepare<[number, string], { hourly_rate: number }>(
      "SELECT hourly_rate FROM pay_rates WHERE employee_id = ? AND valid_from <= ? ORDER BY valid_from DESC LIMIT 1"
    )
    .get(employeeId, dateOnly);
  return row?.hourly_rate ?? 0;
}

export function getCurrentRate(employeeId: number): number {
  return getRateAt(employeeId, todayIso());
}

export function setRate(employeeId: number, hourlyRate: number, validFrom?: string): PayRate {
  if (!Number.isFinite(hourlyRate) || hourlyRate < 0) {
    throw new Error("Sazba musí být nezáporné číslo.");
  }

  const from = validFrom && /^\d{4}-\d{2}-\d{2}$/.test(validFrom) ? validFrom : defaultValidFrom(employeeId);

  db.prepare(
    `INSERT INTO pay_rates (employee_id, hourly_rate, valid_from) VALUES (?, ?, ?)
     ON CONFLICT (employee_id, valid_from) DO UPDATE SET hourly_rate = excluded.hourly_rate`
  ).run(employeeId, hourlyRate, from);

  return db
    .prepare<[number, string], PayRate>("SELECT * FROM pay_rates WHERE employee_id = ? AND valid_from = ?")
    .get(employeeId, from)!;
}

/**
 * The first rate ever set for an employee applies retroactively to their whole history
 * (back to when they were added), so hours worked before the admin got around to setting
 * a rate still get paid out. Later raises only take effect from today.
 */
function defaultValidFrom(employeeId: number): string {
  const hasExisting = db
    .prepare<[number], { n: number }>("SELECT COUNT(*) as n FROM pay_rates WHERE employee_id = ?")
    .get(employeeId)!.n;
  if (hasExisting > 0) {
    return todayIso();
  }
  const employee = db
    .prepare<[number], { created_at: string }>("SELECT created_at FROM employees WHERE id = ?")
    .get(employeeId);
  return employee ? employee.created_at.slice(0, 10) : todayIso();
}
