import { ApiError } from "./ApiError.js";

const toUtcDate = (value) => {
  if (!value) {
    return null;
  }

  const date = new Date(value);

  if (Number.isNaN(date.getTime())) {
    return null;
  }

  return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));
};

export const parseFiscalDate = (value, fieldName) => {
  const date = toUtcDate(value);

  if (!date) {
    throw new ApiError(400, `${fieldName} invalide.`);
  }

  return date;
};

export const formatDateOnly = (value) => {
  const date = value instanceof Date ? value : new Date(value);

  return date.toISOString().slice(0, 10);
};

export const getInclusiveMonthSpan = (startDate, endDate) =>
  (endDate.getUTCFullYear() - startDate.getUTCFullYear()) * 12 +
  (endDate.getUTCMonth() - startDate.getUTCMonth()) +
  1;

export const buildFiscalPeriods = (startDate, count = 12) =>
  Array.from({ length: count }, (_, index) => {
    const currentDate = new Date(
      Date.UTC(startDate.getUTCFullYear(), startDate.getUTCMonth() + index, 1),
    );

    return {
      month: currentDate.getUTCMonth() + 1,
      year: currentDate.getUTCFullYear(),
    };
  });

export const syncFiscalYearPeriods = async (db, fiscalYear) => {
  const startDate = parseFiscalDate(fiscalYear.start_date, "Date de début");
  const periods = buildFiscalPeriods(startDate, 12);
  const insertedRows = [];

  for (const period of periods) {
    const { rows } = await db.query(
      `
        INSERT INTO accounting_periods (
          fiscal_year_id,
          company_id,
          month,
          year,
          is_closed
        )
        VALUES ($1, $2, $3, $4, FALSE)
        ON CONFLICT (fiscal_year_id, month, year) DO NOTHING
        RETURNING *
      `,
      [fiscalYear.id, fiscalYear.company_id, period.month, period.year],
    );

    if (rows[0]) {
      insertedRows.push(rows[0]);
    }
  }

  return insertedRows;
};
