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

vi.mock("next/cache", async () => ({ revalidatePath: (await import("@/tests/helpers/next-mocks")).revalidatePath }));
vi.mock("next/navigation", async () => ({ redirect: (await import("@/tests/helpers/next-mocks")).redirect }));
vi.mock("next/dist/client/components/redirect-error", async () => ({
  isRedirectError: (await import("@/tests/helpers/next-mocks")).isRedirectError,
}));
vi.mock("@/lib/admin-auth", async () => {
  const m = await import("@/tests/helpers/next-mocks");
  return { isAdminAuthenticated: m.isAdminAuthenticated, clearAdminSessionCookie: m.clearAdminSessionCookie };
});

const { sendTestEmail } = vi.hoisted(() => ({ sendTestEmail: vi.fn(async () => {}) }));
vi.mock("@/lib/mail", () => ({ sendTestEmail }));

import { saveMailSettingsAction, sendTestEmailAction } from "@/app/_admin/smtp/actions";
import { getMailSettings } from "@/lib/app-config";
import { adminAuth, captureRedirect, formDataFrom, resetNextMocks } from "@/tests/helpers/next-mocks";

beforeEach(() => {
  resetNextMocks();
  sendTestEmail.mockClear();
});

const validForm = {
  smtpHost: "smtp.example.com",
  smtpPort: "465",
  smtpUsername: "mailer",
  smtpPassword: "secret",
  smtpSecure: "on",
  mailFromEmail: "from@example.com",
  mailFromName: "Studio",
  mailContactRecipient: "contact@example.com",
  mailTestRecipient: "test@example.com",
};

describe("saveMailSettingsAction", () => {
  it("persists valid settings and redirects with success", async () => {
    const url = await captureRedirect(() => saveMailSettingsAction(formDataFrom(validForm)));
    expect(url).toContain("success=");

    const settings = await getMailSettings();
    expect(settings.smtp.host).toBe("smtp.example.com");
    expect(settings.smtp.port).toBe(465);
    expect(settings.smtp.secure).toBe(true);
    expect(settings.recipients.contact).toBe("contact@example.com");
  });

  it("rejects an invalid port with an error flash", async () => {
    const url = await captureRedirect(() =>
      saveMailSettingsAction(formDataFrom({ ...validForm, smtpPort: "not-a-number" })),
    );
    expect(url).toContain("error=");
  });

  it("retains the existing password when the field is left blank", async () => {
    await captureRedirect(() => saveMailSettingsAction(formDataFrom(validForm)));
    await captureRedirect(() =>
      saveMailSettingsAction(formDataFrom({ ...validForm, smtpPassword: "" })),
    );
    const settings = await getMailSettings();
    expect(settings.smtp.password).toBe("secret");
  });

  it("redirects unauthenticated callers to the admin root", async () => {
    adminAuth.authenticated = false;
    const url = await captureRedirect(() => saveMailSettingsAction(formDataFrom(validForm)));
    expect(url).toBe("/");
  });
});

describe("sendTestEmailAction", () => {
  it("sends a test email and redirects with success", async () => {
    const url = await captureRedirect(() => sendTestEmailAction());
    expect(sendTestEmail).toHaveBeenCalledTimes(1);
    expect(url).toContain("success=");
  });

  it("redirects with an error when sending fails", async () => {
    sendTestEmail.mockRejectedValueOnce(new Error("SMTP host is required."));
    const url = await captureRedirect(() => sendTestEmailAction());
    expect(url).toContain("error=");
  });

  it("redirects unauthenticated callers to the admin root", async () => {
    adminAuth.authenticated = false;
    const url = await captureRedirect(() => sendTestEmailAction());
    expect(url).toBe("/");
    expect(sendTestEmail).not.toHaveBeenCalled();
  });
});
