import ms from "ms";

export type SettingTopic = "club" | "app" | "session" | "mail" | "backup" | "security";
export type SettingString =
  | "club.icon"
  | "club.logo"
  | "club.name"
  | "club.imprint"
  | "club.privacy"
  | "club.website"
  | "app.custom_login_message"
  | "app.show_link_to_calendar"
  | "session.jwt_expiration"
  | "session.refresh_expiration"
  | "session.pwa_refresh_expiration"
  | "mail.username"
  | "mail.password"
  | "mail.host"
  | "mail.port"
  | "mail.secure"
  | "backup.interval"
  | "backup.copies";

export type SettingTypeAtom = "longstring" | "string" | "ms" | "number" | "boolean" | "url";
export type SettingType = SettingTypeAtom | `${SettingTypeAtom}/crypt` | `${SettingTypeAtom}/rand`;

export type SettingValueMapping = {
  "club.icon": string;
  "club.logo": string;
  "club.name": string;
  "club.imprint": string;
  "club.privacy": string;
  "club.website": string;
  "app.custom_login_message": string;
  "app.show_link_to_calendar": boolean;
  "session.jwt_expiration": ms.StringValue;
  "session.refresh_expiration": ms.StringValue;
  "session.pwa_refresh_expiration": ms.StringValue;
  "mail.username": string;
  "mail.password": string;
  "mail.host": string;
  "mail.port": number;
  "mail.secure": boolean;
  "backup.interval": number;
  "backup.copies": number;
};

// Typsicherer Zugriff auf Settings
export type SettingDefinition<T extends SettingType | SettingTypeAtom[]> = {
  type: T;
  default?: string | number | boolean;
  optional?: boolean;
  min?: T extends "number" | `number/crypt` | `number/rand` ? number : never;
};

export type SettingsSchema = {
  [key in SettingString]: SettingDefinition<SettingType | SettingTypeAtom[]>;
};

export const settingsType: SettingsSchema = {
  "club.icon": { type: "string", optional: true },
  "club.logo": { type: "string", optional: true },
  "club.name": { type: "string", default: "FF Admin" },
  "club.imprint": { type: "url", optional: true },
  "club.privacy": { type: "url", optional: true },
  "club.website": { type: "url", optional: true },
  "app.custom_login_message": { type: "string", optional: true },
  "app.show_link_to_calendar": { type: "boolean", default: true },
  "session.jwt_expiration": { type: "ms", default: "15m" },
  "session.refresh_expiration": { type: "ms", default: "1d" },
  "session.pwa_refresh_expiration": { type: "ms", default: "5d" },
  "mail.username": { type: "string", optional: false },
  "mail.password": { type: "string/crypt", optional: false },
  "mail.host": { type: "url", optional: false },
  "mail.port": { type: "number", default: 587 },
  "mail.secure": { type: "boolean", default: false },
  "backup.interval": { type: "number", default: 1, min: 1 },
  "backup.copies": { type: "number", default: 7, min: 1 },
};

/** ENV Settings */
export type EnvSettingString =
  | "database.type"
  | "database.host"
  | "database.port"
  | "database.name"
  | "database.username"
  | "database.password"
  | "application.secret"
  | "security.strict_limit"
  | "security.strict_limit_window"
  | "security.strict_limit_request_count"
  | "security.limit"
  | "security.limit_window"
  | "security.limit_request_count"
  | "security.trust_proxy";

export const envSettingsType: {
  [key in EnvSettingString]: {
    type: SettingType | SettingType[];
    default?: string | number | boolean;
  };
} = {
  "database.type": { type: "string", default: "postgres" },
  "database.host": { type: "string" },
  "database.port": { type: "string", default: "5432" },
  "database.name": { type: "string" },
  "database.username": { type: "string" },
  "database.password": { type: "string" },
  "application.secret": { type: "string" },
  "security.strict_limit": { type: "boolean", default: true },
  "security.strict_limit_window": { type: "ms", default: "15m" },
  "security.strict_limit_request_count": { type: "number", default: 15 },
  "security.limit": { type: "boolean", default: true },
  "security.limit_window": { type: "ms", default: "1m" },
  "security.limit_request_count": { type: "number", default: 500 },
  "security.trust_proxy": { type: ["boolean", "number", "string"] },
};