import "server-only";
import { inArray } from "drizzle-orm";
import { db } from "@/lib/db/client";
import { adminSettings } from "@/lib/db/schema";

/**
 * Canonical site-wide admin settings with sensible defaults. Each key maps
 * to a concrete TypeScript type; `loadSiteSettings` fills in any missing
 * keys from the defaults, so callers always get a complete object.
 */
export type SiteSettings = {
  siteName: string;
  tagline: string;
  contactEmail: string;
  reviewSlaHours: number;
  applicationsOpen: boolean;
  maintenanceMode: boolean;
  maintenanceMessage: string;
  announcementBarEnabled: boolean;
  // SEO defaults — applied to pages that don't set their own metadata.
  seoDefaultTitle: string;
  seoTitleTemplate: string;
  seoDefaultDescription: string;
  seoKeywords: string;
  seoOgImage: string;
  seoTwitterHandle: string;
  seoRobots: string;
};

export const DEFAULT_SITE_SETTINGS: SiteSettings = {
  siteName: "OrthoGlobe",
  tagline: "International Orthopaedic Charity Collaboration",
  contactEmail: "Info@OrthoGlobe.org",
  reviewSlaHours: 72,
  applicationsOpen: true,
  maintenanceMode: false,
  maintenanceMessage:
    "OrthoGlobe is briefly offline for maintenance. We'll be back shortly.",
  announcementBarEnabled: true,
  seoDefaultTitle: "OrthoGlobe — International Orthopaedic Charity Collaboration",
  seoTitleTemplate: "%s — OrthoGlobe",
  seoDefaultDescription:
    "An international orthopaedic charity collaboration — a non-profit coalition of surgeons building open tools, atlases, and education for clinicians and trainees worldwide.",
  seoKeywords: "orthopaedics, orthopaedic charity, surgery, musculoskeletal, medical education",
  seoOgImage: "/brand/orthoglobe-og.png",
  seoTwitterHandle: "",
  seoRobots: "index,follow",
};

const KEYS = Object.keys(DEFAULT_SITE_SETTINGS) as Array<keyof SiteSettings>;

export async function loadSiteSettings(): Promise<SiteSettings> {
  const rows = await db
    .select()
    .from(adminSettings)
    .where(inArray(adminSettings.key, KEYS as string[]));
  const byKey = new Map(rows.map((r) => [r.key, r.value]));
  const out = { ...DEFAULT_SITE_SETTINGS };
  for (const k of KEYS) {
    if (byKey.has(k)) {
      // The DB column is jsonb so values arrive as the correct JS type; we
      // still coerce defensively to guard against someone writing a string
      // where a boolean is expected.
      const raw = byKey.get(k);
      if (typeof raw === typeof out[k]) {
        (out as Record<string, unknown>)[k] = raw as never;
      } else if (k === "reviewSlaHours" && typeof raw === "number") {
        out.reviewSlaHours = raw;
      } else if (typeof out[k] === "string" && raw != null) {
        (out as Record<string, unknown>)[k] = String(raw);
      }
    }
  }
  return out;
}

export async function saveSiteSettings(
  partial: Partial<SiteSettings>,
  adminUserId: string,
): Promise<void> {
  for (const [key, value] of Object.entries(partial)) {
    if (value === undefined) continue;
    await db
      .insert(adminSettings)
      .values({ key, value, updatedBy: adminUserId })
      .onConflictDoUpdate({
        target: adminSettings.key,
        set: {
          value,
          updatedBy: adminUserId,
          updatedAt: new Date(),
        },
      });
  }
}
