/**
 * Unit Tests for Social Media Validators
 * File: lib/validators/social-media.validator.ts
 *
 * Tests Zod validation schemas for OAuth, content, and scheduling.
 */

import {
  socialPlatformSchema,
  socialIntegrationStatusSchema,
  oauthCallbackSchema,
  oauthStateSchema,
  inboxReplySchema,
  inboxMarkReadSchema,
  socialPostSchema,
  queueItemCreateSchema,
  schedulePostSchema,
  calendarQuerySchema,
  aiGenerateSchema,
  blogGenerationInputSchema,
  createPlatformContentSchema,
} from "@/lib/validators/social-media.validator";

describe("social-media.validator", () => {
  // ═════════════════════════════════════════════════════════════════════
  // Platform Schema
  // ═════════════════════════════════════════════════════════════════════

  describe("socialPlatformSchema", () => {
    it.each(["INSTAGRAM", "FACEBOOK", "TIKTOK", "TWITTER"])(
      "accepts valid platform: %s",
      (platform) => {
        expect(socialPlatformSchema.parse(platform)).toBe(platform);
      },
    );

    it("rejects invalid platform", () => {
      expect(() => socialPlatformSchema.parse("LINKEDIN")).toThrow();
      expect(() => socialPlatformSchema.parse("facebook")).toThrow(); // case sensitive
      expect(() => socialPlatformSchema.parse("")).toThrow();
    });
  });

  // ═════════════════════════════════════════════════════════════════════
  // Integration Status Schema
  // ═════════════════════════════════════════════════════════════════════

  describe("socialIntegrationStatusSchema", () => {
    it.each(["CONNECTED", "DISCONNECTED", "TOKEN_EXPIRED", "ERROR"])(
      "accepts valid status: %s",
      (status) => {
        expect(socialIntegrationStatusSchema.parse(status)).toBe(status);
      },
    );

    it("rejects invalid status", () => {
      expect(() => socialIntegrationStatusSchema.parse("PENDING")).toThrow();
    });
  });

  // ═════════════════════════════════════════════════════════════════════
  // OAuth Callback Schema
  // ═════════════════════════════════════════════════════════════════════

  describe("oauthCallbackSchema", () => {
    it("accepts valid code and state", () => {
      const result = oauthCallbackSchema.parse({
        code: "auth-code-123",
        state: "encoded-state-456",
      });
      expect(result.code).toBe("auth-code-123");
      expect(result.state).toBe("encoded-state-456");
    });

    it("rejects missing code", () => {
      expect(() => oauthCallbackSchema.parse({ state: "state" })).toThrow();
    });

    it("rejects empty code", () => {
      expect(() =>
        oauthCallbackSchema.parse({ code: "", state: "state" }),
      ).toThrow();
    });

    it("rejects missing state", () => {
      expect(() => oauthCallbackSchema.parse({ code: "code" })).toThrow();
    });
  });

  // ═════════════════════════════════════════════════════════════════════
  // OAuth State Schema
  // ═════════════════════════════════════════════════════════════════════

  describe("oauthStateSchema", () => {
    const validState = {
      userId: "user-1",
      platform: "FACEBOOK",
      csrfToken: "a".repeat(64),
      redirectUrl: "http://localhost:9000/callback",
      timestamp: Date.now(),
    };

    it("accepts valid state", () => {
      const result = oauthStateSchema.parse(validState);
      expect(result.userId).toBe("user-1");
      expect(result.platform).toBe("FACEBOOK");
    });

    it("rejects state with short CSRF token", () => {
      expect(() =>
        oauthStateSchema.parse({ ...validState, csrfToken: "short" }),
      ).toThrow();
    });

    it("rejects state with invalid platform", () => {
      expect(() =>
        oauthStateSchema.parse({ ...validState, platform: "SNAPCHAT" }),
      ).toThrow();
    });

    it("rejects state with invalid redirect URL", () => {
      expect(() =>
        oauthStateSchema.parse({ ...validState, redirectUrl: "not-a-url" }),
      ).toThrow();
    });
  });

  // ═════════════════════════════════════════════════════════════════════
  // Inbox Reply Schema
  // ═════════════════════════════════════════════════════════════════════

  describe("inboxReplySchema", () => {
    it("accepts valid reply with content", () => {
      const result = inboxReplySchema.parse({ content: "Hello!" });
      expect(result.content).toBe("Hello!");
      expect(result.mediaUrls).toEqual([]);
    });

    it("accepts reply with media URLs", () => {
      const result = inboxReplySchema.parse({
        content: "Check this out",
        mediaUrls: ["https://example.com/image.jpg"],
      });
      expect(result.mediaUrls).toHaveLength(1);
    });

    it("rejects empty content", () => {
      expect(() => inboxReplySchema.parse({ content: "" })).toThrow();
    });

    it("rejects content over 10000 chars", () => {
      expect(() =>
        inboxReplySchema.parse({ content: "x".repeat(10001) }),
      ).toThrow();
    });

    it("rejects more than 10 media URLs", () => {
      const urls = Array.from(
        { length: 11 },
        (_, i) => `https://example.com/${i}.jpg`,
      );
      expect(() =>
        inboxReplySchema.parse({ content: "test", mediaUrls: urls }),
      ).toThrow();
    });
  });

  // ═════════════════════════════════════════════════════════════════════
  // Inbox Mark Read Schema
  // ═════════════════════════════════════════════════════════════════════

  describe("inboxMarkReadSchema", () => {
    it("accepts messageIds", () => {
      const result = inboxMarkReadSchema.parse({ messageIds: ["msg-1"] });
      expect(result.messageIds).toEqual(["msg-1"]);
    });

    it("accepts conversationId", () => {
      const result = inboxMarkReadSchema.parse({ conversationId: "conv-1" });
      expect(result.conversationId).toBe("conv-1");
    });

    it("rejects when both are missing", () => {
      expect(() => inboxMarkReadSchema.parse({})).toThrow();
    });
  });

  // ═════════════════════════════════════════════════════════════════════
  // Social Post Schema (platform-aware)
  // ═════════════════════════════════════════════════════════════════════

  describe("socialPostSchema", () => {
    it("accepts valid Facebook post", () => {
      const result = socialPostSchema.parse({
        content: "Hello world!",
        hashtags: ["#test"],
        mediaUrls: [],
        platform: "FACEBOOK",
      });
      expect(result.content).toBe("Hello world!");
    });

    it("rejects Instagram post without media", () => {
      expect(() =>
        socialPostSchema.parse({
          content: "No media",
          hashtags: [],
          mediaUrls: [],
          platform: "INSTAGRAM",
        }),
      ).toThrow("requires at least one media");
    });

    it("rejects content exceeding Twitter limit (280 chars)", () => {
      expect(() =>
        socialPostSchema.parse({
          content: "x".repeat(281),
          hashtags: [],
          mediaUrls: [],
          platform: "TWITTER",
        }),
      ).toThrow("character limit");
    });

    it("accepts long Facebook post (up to 63206 chars)", () => {
      const result = socialPostSchema.parse({
        content: "x".repeat(5000),
        hashtags: [],
        mediaUrls: [],
        platform: "FACEBOOK",
      });
      expect(result.content).toHaveLength(5000);
    });
  });

  // ═════════════════════════════════════════════════════════════════════
  // Platform-Specific Content Schema
  // ═════════════════════════════════════════════════════════════════════

  describe("createPlatformContentSchema", () => {
    it("creates schema that validates Instagram posts", () => {
      const schema = createPlatformContentSchema("INSTAGRAM");

      expect(() =>
        schema.parse({
          content: "Test",
          hashtags: ["#beauty"],
          mediaUrls: ["https://example.com/photo.jpg"],
          platform: "INSTAGRAM",
        }),
      ).not.toThrow();
    });

    it("enforces Instagram max hashtags (30)", () => {
      const schema = createPlatformContentSchema("INSTAGRAM");
      const hashtags = Array.from({ length: 31 }, (_, i) => `#tag${i}`);

      expect(() =>
        schema.parse({
          content: "Test",
          hashtags,
          mediaUrls: ["https://example.com/photo.jpg"],
          platform: "INSTAGRAM",
        }),
      ).toThrow("30 hashtags");
    });
  });

  // ═════════════════════════════════════════════════════════════════════
  // Schedule Post Schema
  // ═════════════════════════════════════════════════════════════════════

  describe("schedulePostSchema", () => {
    const validSchedule = {
      socialAccountId: "acc-1",
      platform: "FACEBOOK",
      content: "Scheduled post",
      scheduledAt: new Date().toISOString(),
    };

    it("accepts valid schedule input", () => {
      const result = schedulePostSchema.parse(validSchedule);
      expect(result.content).toBe("Scheduled post");
      expect(result.scheduledAt).toBeInstanceOf(Date);
    });

    it("accepts optional calendarColor (hex)", () => {
      const result = schedulePostSchema.parse({
        ...validSchedule,
        calendarColor: "#FF5733",
      });
      expect(result.calendarColor).toBe("#FF5733");
    });

    it("rejects invalid hex color", () => {
      expect(() =>
        schedulePostSchema.parse({
          ...validSchedule,
          calendarColor: "red",
        }),
      ).toThrow();
    });
  });

  // ═════════════════════════════════════════════════════════════════════
  // Calendar Query Schema
  // ═════════════════════════════════════════════════════════════════════

  describe("calendarQuerySchema", () => {
    it("accepts valid month and year", () => {
      const result = calendarQuerySchema.parse({ month: 3, year: 2026 });
      expect(result.month).toBe(3);
      expect(result.year).toBe(2026);
    });

    it("rejects month outside 1-12", () => {
      expect(() => calendarQuerySchema.parse({ month: 13 })).toThrow();
      expect(() => calendarQuerySchema.parse({ month: 0 })).toThrow();
    });

    it("accepts empty object (all optional)", () => {
      const result = calendarQuerySchema.parse({});
      expect(result.month).toBeUndefined();
    });
  });

  // ═════════════════════════════════════════════════════════════════════
  // AI Generate Schema
  // ═════════════════════════════════════════════════════════════════════

  describe("aiGenerateSchema", () => {
    it("accepts valid caption generation request", () => {
      const result = aiGenerateSchema.parse({
        type: "caption",
        topic: "New product launch",
        tone: "professional",
        language: "en",
      });
      expect(result.type).toBe("caption");
      expect(result.tone).toBe("professional");
    });

    it("defaults tone to professional", () => {
      const result = aiGenerateSchema.parse({ type: "hashtags" });
      expect(result.tone).toBe("professional");
    });

    it("defaults language to en", () => {
      const result = aiGenerateSchema.parse({ type: "reply" });
      expect(result.language).toBe("en");
    });

    it("accepts Arabic language", () => {
      const result = aiGenerateSchema.parse({
        type: "caption",
        language: "ar",
      });
      expect(result.language).toBe("ar");
    });

    it("rejects invalid type", () => {
      expect(() => aiGenerateSchema.parse({ type: "summarize" })).toThrow();
    });
  });

  // ═════════════════════════════════════════════════════════════════════
  // Blog Generation Schema
  // ═════════════════════════════════════════════════════════════════════

  describe("blogGenerationInputSchema", () => {
    it("accepts valid blog generation input", () => {
      const result = blogGenerationInputSchema.parse({
        topic: "AI in Healthcare",
        tone: "professional",
        language: "en",
      });
      expect(result.topic).toBe("AI in Healthcare");
      expect(result.wordCount).toBe(1000); // default
    });

    it("rejects topic shorter than 3 chars", () => {
      expect(() =>
        blogGenerationInputSchema.parse({
          topic: "AI",
          tone: "casual",
          language: "ar",
        }),
      ).toThrow("at least 3");
    });

    it("accepts Arabic language for blog generation", () => {
      const result = blogGenerationInputSchema.parse({
        topic: "الذكاء الاصطناعي في الرعاية الصحية",
        tone: "informative",
        language: "ar",
        wordCount: 2000,
      });
      expect(result.language).toBe("ar");
      expect(result.wordCount).toBe(2000);
    });
  });
});
