import stringify from "json-stable-stringify";
import objectHash from "object-hash";
import { guilds, matches, tpMessages } from "~/drizzle/schema";
import { ExtractDataTypes, GetColumns } from "~/types/db";
import { components } from "~/types/liljudd";

export const buildMatches = (
  queryMatches: ExtractDataTypes<GetColumns<typeof matches>>[],
): components["schemas"]["match"][] =>
  queryMatches.map(
    ({
      channelId,
      createrId,
      roleId,
      messageId,
      matchType,
      opponentName,
      utc_ts,
    }) => ({
      channelId: channelId.toString(),
      createrId: createrId.toString(),
      roleId: roleId.toString(),
      messageId: messageId.toString(),
      matchType,
      opponentName,
      utc_ts: utc_ts.toISOString(),
    }),
  );

export function buildConfig(
  guildQuery: ExtractDataTypes<GetColumns<typeof guilds>> & {
    tpMessages: ExtractDataTypes<GetColumns<typeof tpMessages>>[];
    matches: ExtractDataTypes<GetColumns<typeof matches>>[];
  },
): components["schemas"]["guildConfig"] {
  const {
    id,
    timezone,
    tpEnabled,
    tpChannelId,
    tpInterval,
    tpRolesEnabled: tpRoles,
    isAvailableRoleId,
    wantsToBeNotifieRoledId,
  } = guildQuery;

  const targetMinute = tpInterval & 63;
  const targetHour = (tpInterval >> 6) & 31;
  const targetDay = (tpInterval >> 11) & 7;

  const payload = {
    guildId: id.toString(),
    timezone,
    features: {
      timePlanning: {
        enabled: tpEnabled,
        channelId: tpChannelId?.toString() ?? null,
        targetMinute,
        targetHour,
        targetDay,
        roles: {
          enabled: tpRoles,
          isAvailableRoleId: isAvailableRoleId?.toString() ?? null,
          wantsToBeNotifieRoledId: wantsToBeNotifieRoledId?.toString() ?? null,
        },
      },
    },
    matches: buildMatches(guildQuery.matches),
  };

  // generate checksum from payload because
  // from guildQuery results in bigint serialization error
  return { ...payload, checksum: objectHash(stringify(payload)) };
}
