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

// Mock Payload CMS
const { mockCreate, mockSendEmail } = vi.hoisted(() => ({
  mockCreate: vi.fn(),
  mockSendEmail: vi.fn(),
}));

// Mock Nodemailer
const { mockSendMail } = vi.hoisted(() => ({
  mockSendMail: vi.fn().mockResolvedValue({ messageId: "mock-message-id" }),
}));

vi.mock("nodemailer", () => ({
  default: {
    createTransport: vi.fn().mockReturnValue({
      sendMail: mockSendMail,
    }),
  },
}));

vi.mock("payload", () => ({
  getPayload: vi.fn().mockResolvedValue({
    create: mockCreate,
    sendEmail: mockSendEmail,
  }),
}));

// Mock Email Template renders
vi.mock("@mintel/mail", () => ({
  render: vi.fn().mockResolvedValue("<html>Mocked Email HTML</html>"),
  ContactFormNotification: () => "ContactFormNotification",
  ConfirmationMessage: () => "ConfirmationMessage",
}));

// Mock Notifications and Analytics
const { mockNotify, mockTrack, mockCaptureException } = vi.hoisted(() => ({
  mockNotify: vi.fn(),
  mockTrack: vi.fn(),
  mockCaptureException: vi.fn(),
}));

vi.mock("@/lib/services/create-services.server", () => ({
  getServerAppServices: () => ({
    logger: {
      child: () => ({
        info: vi.fn(),
        warn: vi.fn(),
        error: vi.fn(),
      }),
    },
    analytics: {
      setServerContext: vi.fn(),
      track: mockTrack,
    },
    notifications: {
      notify: mockNotify,
    },
    errors: {
      captureException: mockCaptureException,
    },
  }),
}));

// Import the route handler we want to test
import { POST } from "../app/api/contact/route";
import { NextResponse } from "next/server";
import type { Mock } from "vitest";

describe("Contact API Integration", () => {
  beforeEach(() => {
    vi.clearAllMocks();
    (NextResponse.json as Mock).mockImplementation((body: any, init?: any) => ({
      status: init?.status || 200,
      json: async () => body,
    }));
  });

  it("should validate and decline empty or short messages", async () => {
    const req = new Request("http://localhost/api/contact", {
      method: "POST",
      body: JSON.stringify({
        name: "Test User",
        email: "test@example.com",
        message: "too short",
      }),
    });

    const response = await POST(req);
    expect(response.status).toBe(400);

    const data = await response.json();
    expect(data.error).toBe("message_too_short");

    // Ensure payload and email were NOT called
    expect(mockCreate).not.toHaveBeenCalled();
    expect(mockSendEmail).not.toHaveBeenCalled();
  });

  it("should catch honeypot submissions", async () => {
    const req = new Request("http://localhost/api/contact", {
      method: "POST",
      body: JSON.stringify({
        name: "Spam Bot",
        email: "spam@example.com",
        message: "This is a very long spam message that passes length checks.",
        website: "http://spam.com", // Honeypot filled
      }),
    });

    const response = await POST(req);
    // Honeypot returns 200 OK so the bot thinks it succeeded
    expect(response.status).toBe(200);

    // But it actually does NOTHING internally
    expect(mockCreate).not.toHaveBeenCalled();
    expect(mockSendMail).not.toHaveBeenCalled();
  });

  it("should successfully save to Payload and send emails", async () => {
    const req = new Request("http://localhost/api/contact", {
      method: "POST",
      headers: {
        "user-agent": "vitest",
        "x-forwarded-for": "127.0.0.1",
      },
      body: JSON.stringify({
        name: "Jane Doe",
        email: "jane@example.com",
        company: "Jane Tech",
        message:
          "Hello, I am interested in exploring your high-voltage grid solutions.",
      }),
    });

    const response = await POST(req);
    expect(response.status).toBe(200);

    const data = await response.json();
    expect(data.message).toBe("Ok");

    // 1. Verify Payload creation
    expect(mockCreate).toHaveBeenCalledTimes(1);
    expect(mockCreate).toHaveBeenCalledWith({
      collection: "form-submissions",
      data: {
        name: "Jane Doe",
        email: "jane@example.com",
        company: "Jane Tech",
        message:
          "Hello, I am interested in exploring your high-voltage grid solutions.",
      },
    });

    // 2. Verify Email Sending
    // Note: sendMail is called twice (Notification + User Confirmation)
    expect(mockSendMail).toHaveBeenCalledTimes(2);

    expect(mockSendMail).toHaveBeenNthCalledWith(
      1,
      expect.objectContaining({
        subject: "Kontaktanfrage von Jane Doe",
        replyTo: "jane@example.com",
      }),
    );

    expect(mockSendMail).toHaveBeenNthCalledWith(
      2,
      expect.objectContaining({
        to: "jane@example.com",
        subject: "Ihre Kontaktanfrage bei MB Grid Solutions",
      }),
    );

    // 3. Verify notification and analytics
    expect(mockNotify).toHaveBeenCalledTimes(1);
    expect(mockTrack).toHaveBeenCalledWith("contact-form-success", {
      has_company: true,
    });
  });
});
