import db from "../db/db.js";
import { siteDataKeys } from "./siteDataKeys.js";
import type { Cookies } from "@sveltejs/kit";
import type {
  DataRetentionPolicy,
  EventDisplaySettings,
  GlobalPageVisibilitySettings,
  PageOrderingSettings,
  SiteAnalyticsItem,
  SiteAnnouncement,
  SiteCategory,
  SiteFont,
  SiteHero,
  SiteHomeDataMaxDays,
  SiteI18nConfig,
  SiteMetaTag,
  SiteNavItem,
  SiteStatusColors,
  SiteSubMenuOptions,
  SiteDateTimeFormat,
  SiteSubscriptionsSettings,
  SitemapXMLConfig,
  GlobalMaintenanceNotificationSettings,
} from "../../types/site.js";

export interface SiteDataTransformed {
  title?: string;
  siteName?: string;
  siteURL: string;
  home?: string;
  logo?: string;
  favicon?: string;
  metaTags?: SiteMetaTag[];
  nav?: SiteNavItem[];
  hero?: SiteHero;
  footerHTML?: string;
  i18n: SiteI18nConfig;
  pattern?: string;
  analytics?: SiteAnalyticsItem[];
  theme?: string;
  themeToggle?: string;
  tzToggle?: string;
  barStyle: string;
  barRoundness?: string;
  summaryStyle?: string;
  colors: SiteStatusColors;
  colorsDark: SiteStatusColors;
  font: SiteFont;
  categories?: SiteCategory[];
  homeIncidentCount?: number | null;
  homeIncidentStartTimeWithin?: number;
  homeDataMaxDays?: SiteHomeDataMaxDays;
  kenerTheme?: string;
  subscriptionsSettings?: SiteSubscriptionsSettings;
  showSiteStatus?: string;
  monitorSort?: number[];

  subMenuOptions?: SiteSubMenuOptions;
  announcement?: SiteAnnouncement;
  dataRetentionPolicy?: DataRetentionPolicy;
  eventDisplaySettings?: EventDisplaySettings;
  socialPreviewImage?: string;
  customCSS?: string;
  globalPageVisibilitySettings?: GlobalPageVisibilitySettings;
  pageOrderingSettings?: PageOrderingSettings;
  dateAndTimeFormat?: SiteDateTimeFormat;
  metaSiteTitle?: string;
  metaSiteDescription?: string;
  sitemap?: SitemapXMLConfig;
  globalMaintenanceNotificationSettings?: GlobalMaintenanceNotificationSettings;
}

export function InsertKeyValue(key: string, value: string): Promise<number[]> {
  let f = siteDataKeys.find((k) => k.key === key);
  if (!f) {
    console.trace(`Invalid key: ${key}`);
    throw new Error(`Invalid key: ${key}`);
  }
  if (!f.isValid(value)) {
    console.trace(`Invalid value for key: ${key}`);
    throw new Error(`Invalid value for key: ${key}`);
  }
  return db.insertOrUpdateSiteData(key, value, f.data_type);
}

export async function GetAllSiteData(): Promise<SiteDataTransformed> {
  let data = await db.getAllSiteData();
  //return all data as key value pairs, transform using data_type
  const transformedData: Record<string, unknown> = {};
  for (const d of data) {
    if (d.data_type === "object") {
      transformedData[d.key] = JSON.parse(d.value);
    } else {
      transformedData[d.key] = d.value;
    }
  }
  return transformedData as unknown as SiteDataTransformed;
}

export const GetLocaleFromCookie = (site: SiteDataTransformed, cookies: Cookies): string => {
  let selectedLang = site.i18n?.defaultLocale || "en";
  const localLangCookie = cookies.get("localLang");
  if (!!localLangCookie && site.i18n?.locales?.find((l) => l.code === localLangCookie)) {
    selectedLang = localLangCookie;
  } else if (site.i18n?.defaultLocale && site.i18n?.locales?.length) {
    selectedLang = site.i18n.defaultLocale;
  }
  return selectedLang;
};

/**
 * Returns the site URL used for building absolute public URLs, without a trailing slash.
 * Prefers the configured siteURL and falls back to the ORIGIN env var; only absolute
 * http(s) values are returned. Returns an empty string when neither is usable, in which
 * case callers degrade to a relative path.
 */
export const GetSiteURL = async (): Promise<string> => {
  const siteURL = await GetSiteDataByKey("siteURL");
  for (const candidate of [siteURL, process.env.ORIGIN]) {
    if (typeof candidate === "string" && /^https?:\/\//i.test(candidate)) {
      return candidate.replace(/\/+$/, "");
    }
  }
  return "";
};

export const GetSiteLogoURL = async (siteURL: string, logo: string, base: string): Promise<string> => {
  if (logo.startsWith("http")) {
    return logo;
  }
  return siteURL + base + logo;
};

export async function GetAllAnalyticsData() {
  let data = await db.getAllSiteDataAnalytics();
  //return all data as key value pairs, transform using data_type
  let transformedData = [];
  for (const d of data) {
    transformedData.push({
      key: d.key,
      value: JSON.parse(d.value),
    });
  }
  return transformedData;
}
export const GetSiteDataByKey = async (key: string): Promise<unknown> => {
  let data = await db.getSiteDataByKey(key);
  if (!data) {
    return null;
  }
  if (data.data_type == "object") {
    return JSON.parse(data.value);
  }
  return data.value;
};

/** Checks the env vars required for setup, without touching the database. */
export const HasRequiredEnv = (): boolean => {
  return (
    process.env.KENER_SECRET_KEY !== undefined &&
    process.env.ORIGIN !== undefined &&
    process.env.REDIS_URL !== undefined
  );
};

export const IsSetupComplete = async (): Promise<boolean> => {
  if (!HasRequiredEnv()) {
    return false;
  }
  let data = await db.getAllSiteData();

  if (!data) {
    return false;
  }
  return data.length > 0;
};
