import { describe, expect, it } from "vitest";

import {
  DEFAULT_SITE_NAME,
  MAINTENANCE_MODE_KEY,
  SITE_NAME_KEY,
  SITE_SETTINGS_ENTITY_ID,
  SITE_SETTINGS_ENTITY_TYPE,
  SITE_SETTINGS_FAVICON_FIELD_KEY,
  SITE_SETTINGS_LOGO_LIGHT_FIELD_KEY,
  buildDefaultMailSettings,
  buildDefaultMarqueeSettings,
  getMailSettings,
  getMaintenanceMode,
  getMarqueeSettings,
  getSiteSettings,
  getSiteSettingsMediaBindings,
  setMaintenanceMode,
  updateMailSettings,
  updateMarqueeSettings,
  updateSiteSettings,
} from "@/lib/app-config";
import { eq } from "drizzle-orm";

import { db } from "@/lib/db";
import { appConfig, mediaUsage } from "@/lib/db/schema";
import { createMediaAsset } from "@/tests/helpers/factories";

describe("maintenance mode", () => {
  it("defaults to false when unset", async () => {
    expect(await getMaintenanceMode()).toBe(false);
  });

  it("persists and reads back the enabled flag", async () => {
    await setMaintenanceMode(true);
    expect(await getMaintenanceMode()).toBe(true);
    const row = await db.query.appConfig.findFirst({ where: eq(appConfig.key, MAINTENANCE_MODE_KEY) });
    expect(row?.value).toBe("true");
    await setMaintenanceMode(false);
    expect(await getMaintenanceMode()).toBe(false);
  });
});

describe("site settings", () => {
  it("returns defaults (with fallback name) when nothing stored", async () => {
    const settings = await getSiteSettings();
    expect(settings.defaultLocale).toBe("de");
    expect(settings.locales.en.siteName).toBe(DEFAULT_SITE_NAME);
  });

  it("uses the stored siteName key as the fallback name", async () => {
    await db.insert(appConfig).values({ key: SITE_NAME_KEY, value: "My Studio" });
    const settings = await getSiteSettings();
    expect(settings.locales.ar.siteName).toBe("My Studio");
  });

  it("round-trips an updated settings object", async () => {
    const next = await getSiteSettings();
    next.defaultLocale = "ar";
    next.brand.primaryColor = "#123456";
    next.locales.en.siteName = "Updated EN";
    await updateSiteSettings(next);

    const reloaded = await getSiteSettings();
    expect(reloaded.defaultLocale).toBe("ar");
    expect(reloaded.brand.primaryColor).toBe("#123456");
    expect(reloaded.locales.en.siteName).toBe("Updated EN");
  });
});

describe("mail settings", () => {
  it("returns defaults when unset", async () => {
    expect(await getMailSettings()).toEqual(buildDefaultMailSettings());
  });

  it("round-trips stored mail settings", async () => {
    const next = buildDefaultMailSettings();
    next.smtp.host = "smtp.test";
    next.smtp.port = 465;
    next.sender.email = "from@test";
    next.recipients.contact = "c@test";
    await updateMailSettings(next);

    const reloaded = await getMailSettings();
    expect(reloaded.smtp.host).toBe("smtp.test");
    expect(reloaded.smtp.port).toBe(465);
    expect(reloaded.recipients.contact).toBe("c@test");
  });
});

describe("marquee settings", () => {
  it("returns defaults when unset", async () => {
    const settings = await getMarqueeSettings();
    expect(settings.locales.de.row1).toBe(buildDefaultMarqueeSettings().locales.de.row1);
  });

  it("stores german-synced values", async () => {
    const next = buildDefaultMarqueeSettings();
    next.locales.de.row1 = "GERMAN ROW";
    next.locales.en.row1 = "will be overwritten";
    await updateMarqueeSettings(next);

    const reloaded = await getMarqueeSettings();
    expect(reloaded.locales.de.row1).toBe("GERMAN ROW");
    expect(reloaded.locales.en.row1).toBe("GERMAN ROW");
    expect(reloaded.locales.ar.row1).toBe("GERMAN ROW");
  });
});

describe("getSiteSettingsMediaBindings", () => {
  it("returns nulls when there are no usages", async () => {
    const bindings = await getSiteSettingsMediaBindings();
    expect(bindings).toEqual({ siteLogoLight: null, siteLogoDark: null, favicon: null, defaultOgImage: null });
  });

  it("maps media usages to their field bindings", async () => {
    const logo = await createMediaAsset({ url: "https://cdn/logo.png" });
    const favicon = await createMediaAsset({ url: "https://cdn/favicon.svg" });
    await db.insert(mediaUsage).values({
        assetId: logo.id,
        usageType: "GENERIC",
        entityType: SITE_SETTINGS_ENTITY_TYPE,
        entityId: SITE_SETTINGS_ENTITY_ID,
        fieldKey: SITE_SETTINGS_LOGO_LIGHT_FIELD_KEY,
      });
    await db.insert(mediaUsage).values({
        assetId: favicon.id,
        usageType: "GENERIC",
        entityType: SITE_SETTINGS_ENTITY_TYPE,
        entityId: SITE_SETTINGS_ENTITY_ID,
        fieldKey: SITE_SETTINGS_FAVICON_FIELD_KEY,
      });

    const bindings = await getSiteSettingsMediaBindings();
    expect(bindings.siteLogoLight?.assetId).toBe(logo.id);
    expect(bindings.siteLogoLight?.url).toBe("https://cdn/logo.png");
    expect(bindings.favicon?.assetId).toBe(favicon.id);
    expect(bindings.favicon?.version).toMatch(/\d{4}-\d{2}-\d{2}T/); // updatedAt ISO string
    expect(bindings.siteLogoDark).toBeNull();
  });
});
