import { prisma } from "./prisma";

export type AccessSettings = {
  publicAccessEnabled: boolean;
};

export type SystemSettings = AccessSettings & {
  apiKey: string;
  provider: "google" | "osm";
  registrationEnabled: boolean;
};

const PUBLIC_ACCESS_KEY = "public_access_enabled";
const LEGACY_ACCESS_KEYS = [
  "public_events_enabled",
  "anonymous_access_enabled"
] as const;
const SYSTEM_KEYS = [
  "google_places_api_key",
  "geocoding_provider",
  "registration_enabled"
] as const;

const getSettingMap = async (keys: readonly string[]) => {
  const records = await prisma.setting.findMany({
    where: { key: { in: [...keys] } }
  });
  return new Map(records.map((record) => [record.key, record.value]));
};

const readBoolean = (value: string | undefined, fallback: boolean) => {
  if (value === undefined) return fallback;
  return value !== "false";
};

const ensurePublicAccessSetting = async (
  prefetched?: Map<string, string>
) => {
  const existingValue = prefetched?.get(PUBLIC_ACCESS_KEY);
  if (existingValue !== undefined) {
    return existingValue !== "false";
  }

  const existing = await prisma.setting.findUnique({
    where: { key: PUBLIC_ACCESS_KEY }
  });
  if (existing) {
    return existing.value !== "false";
  }

  const legacy = await prisma.setting.findMany({
    where: { key: { in: [...LEGACY_ACCESS_KEYS] } }
  });
  const legacyMap = new Map(legacy.map((record) => [record.key, record.value]));
  const publicEventsEnabled = readBoolean(
    legacyMap.get("public_events_enabled"),
    true
  );
  const anonymousAccessEnabled = readBoolean(
    legacyMap.get("anonymous_access_enabled"),
    true
  );
  const combined = publicEventsEnabled && anonymousAccessEnabled;

  await prisma.setting.upsert({
    where: { key: PUBLIC_ACCESS_KEY },
    update: { value: combined ? "true" : "false" },
    create: { key: PUBLIC_ACCESS_KEY, value: combined ? "true" : "false" }
  });

  if (legacy.length > 0) {
    await prisma.setting.deleteMany({
      where: { key: { in: [...LEGACY_ACCESS_KEYS] } }
    });
  }

  return combined;
};

export async function getAccessSettings(): Promise<AccessSettings> {
  const publicAccessEnabled = await ensurePublicAccessSetting();
  return { publicAccessEnabled };
}

export async function getSystemSettings(): Promise<SystemSettings> {
  const settings = await getSettingMap(SYSTEM_KEYS);
  const apiKey = settings.get("google_places_api_key") || "";
  const storedProvider = settings.get("geocoding_provider");
  const provider =
    storedProvider === "google" || storedProvider === "osm"
      ? storedProvider
      : apiKey
      ? "google"
      : "osm";
  const registrationEnabled = readBoolean(
    settings.get("registration_enabled"),
    true
  );
  const publicAccessEnabled = await ensurePublicAccessSetting(settings);

  return {
    apiKey,
    provider,
    registrationEnabled,
    publicAccessEnabled
  };
}
