import type { IAppConfig } from "@digiresilience/metamigo-config";
import camelcaseKeys from "camelcase-keys";
import PgSimplifyInflectorPlugin from "@graphile-contrib/pg-simplify-inflector";
import PgManyToManyPlugin from "@graphile-contrib/pg-many-to-many";
import ConnectionFilterPlugin from "postgraphile-plugin-connection-filter";
import type { PostGraphileOptions } from "postgraphile";

import {
  UserRecordRepository,
  AccountRecordRepository,
  SessionRecordRepository,
} from "@digiresilience/metamigo-common";

import {
  SettingRecordRepository,
  VoiceProviderRecordRepository,
  VoiceLineRecordRepository,
  WebhookRecordRepository,
  WhatsappBotRecordRepository,
  WhatsappMessageRecordRepository,
  WhatsappAttachmentRecordRepository,
  SignalBotRecordRepository,
} from "./records/index.js";

import type { IInitOptions, IDatabase } from "pg-promise";

export interface IRepositories {
  users: UserRecordRepository;
  sessions: SessionRecordRepository;
  accounts: AccountRecordRepository;
  settings: SettingRecordRepository;
  voiceLines: VoiceLineRecordRepository;
  voiceProviders: VoiceProviderRecordRepository;
  webhooks: WebhookRecordRepository;
  whatsappBots: WhatsappBotRecordRepository;
  whatsappMessages: WhatsappMessageRecordRepository;
  whatsappAttachments: WhatsappAttachmentRecordRepository;
  signalBots: SignalBotRecordRepository;
}

export type AppDatabase = IDatabase<IRepositories> & IRepositories;

export const dbInitOptions = (
  _config: IAppConfig
): IInitOptions<IRepositories> => ({
  noWarnings: true,
  receive(e) {
    const { data, result } = e;
    if (result) result.rows = camelcaseKeys(data);
  },

  // Extending the database protocol with our custom repositories;
  // API: http://vitaly-t.github.io/pg-promise/global.html#event:extend
  extend(obj: any, _dc) {
    // AppDatase was obj type
    // Database Context (_dc) is mainly needed for extending multiple databases with different access API.

    // NOTE:
    // This event occurs for every task and transaction being executed (which could be every request!)
    // so it should be as fast as possible. Do not use 'require()' or do any other heavy lifting.
    obj.users = new UserRecordRepository(obj);
    obj.sessions = new SessionRecordRepository(obj);
    obj.accounts = new AccountRecordRepository(obj);
    obj.settings = new SettingRecordRepository(obj);
    obj.voiceLines = new VoiceLineRecordRepository(obj);
    obj.voiceProviders = new VoiceProviderRecordRepository(obj);
    obj.webhooks = new WebhookRecordRepository(obj);
    obj.whatsappBots = new WhatsappBotRecordRepository(obj);
    obj.whatsappMessages = new WhatsappMessageRecordRepository(obj);
    obj.whatsappAttachments = new WhatsappAttachmentRecordRepository(obj);
    obj.signalBots = new SignalBotRecordRepository(obj);
  },
});

export const getPostGraphileOptions = (): PostGraphileOptions => ({
  ignoreRBAC: false,
  dynamicJson: true,
  ignoreIndexes: false,
  appendPlugins: [
    PgSimplifyInflectorPlugin,
    PgManyToManyPlugin,
    ConnectionFilterPlugin as any,
  ],
});

export * from "./helpers.js";
export * from "./records/index.js";
