/**
 * User Links API Tests
 * Tests for /api/staff/users/[id]/links endpoints
 *
 * Note: Tests are separated into:
 * 1. Unit tests - test business logic without server
 * 2. Integration tests - test actual API endpoints (require running server)
 */

import { describe, it, expect } from "@jest/globals";

// Test data
const TEST_USER_ID = "test-user-links-001";

/**
 * Unit Tests - Business Logic Validation
 * These tests run without a server and test pure functions/logic
 */
describe("User Links Data Validation (Unit Tests)", () => {
  const validLinkTypes = [
    "KNOWLEDGE_BASE",
    "AI_AGENT",
    "AI_VOICE_AGENT",
    "WHATSAPP_INTEGRATION",
    "APPOINTMENTS",
    "CUSTOMERS",
    "WAITLISTS",
    "CALENDAR",
    "ANALYTICS",
    "REPORTS",
    "BILLING",
    "DASHBOARD",
    "DOCUMENTATION",
    "SETTINGS",
    "SUPPORT",
    "CUSTOM",
  ];

  it("should have all valid link types defined", () => {
    expect(validLinkTypes.length).toBeGreaterThan(0);
    expect(validLinkTypes).toContain("KNOWLEDGE_BASE");
    expect(validLinkTypes).toContain("AI_AGENT");
    expect(validLinkTypes).toContain("AI_VOICE_AGENT");
    expect(validLinkTypes).toContain("WHATSAPP_INTEGRATION");
    expect(validLinkTypes).toContain("CUSTOM");
  });

  it("should have unique link type values", () => {
    const uniqueTypes = new Set(validLinkTypes);
    expect(uniqueTypes.size).toBe(validLinkTypes.length);
  });

  it("should validate URL formats correctly", () => {
    const validUrls = [
      "https://example.com",
      "https://kb.mawidi.com/user/123",
      "https://agent.example.com/dashboard?id=abc",
      "http://localhost:3000/test",
      "https://sub.domain.example.com/path/to/resource",
    ];

    const invalidUrls = [
      "not-a-url",
      "ftp://invalid",
      "",
      "javascript:alert(1)",
      "file:///etc/passwd",
    ];

    validUrls.forEach((url) => {
      expect(() => new URL(url)).not.toThrow();
    });

    invalidUrls.forEach((url) => {
      let isValidHttpUrl = false;
      try {
        const parsed = new URL(url);
        isValidHttpUrl =
          parsed.protocol === "https:" || parsed.protocol === "http:";
      } catch {
        isValidHttpUrl = false;
      }
      expect(isValidHttpUrl).toBe(false);
    });
  });
});

describe("User Links Business Logic (Unit Tests)", () => {
  it("should auto-increment sortOrder for new links", () => {
    const existingLinks = [
      { sortOrder: 1 },
      { sortOrder: 2 },
      { sortOrder: 3 },
    ];

    const maxSortOrder = Math.max(...existingLinks.map((l) => l.sortOrder), 0);
    const newSortOrder = maxSortOrder + 1;

    expect(newSortOrder).toBe(4);
  });

  it("should handle empty links array for sortOrder", () => {
    const existingLinks: { sortOrder: number }[] = [];
    const maxSortOrder = Math.max(...existingLinks.map((l) => l.sortOrder), 0);
    const newSortOrder = maxSortOrder + 1;

    expect(newSortOrder).toBe(1);
  });

  it("should truncate long URLs in display", () => {
    const longUrl =
      "https://example.com/very/long/path/that/exceeds/fifty/characters/in/length";
    const displayUrl =
      longUrl.length > 50 ? longUrl.substring(0, 50) + "..." : longUrl;

    expect(displayUrl.length).toBeLessThanOrEqual(53); // 50 + '...'
    expect(displayUrl.endsWith("...")).toBe(true);
  });

  it("should not truncate short URLs", () => {
    const shortUrl = "https://example.com";
    const displayUrl =
      shortUrl.length > 50 ? shortUrl.substring(0, 50) + "..." : shortUrl;

    expect(displayUrl).toBe(shortUrl);
    expect(displayUrl.endsWith("...")).toBe(false);
  });
});

describe("User Links Form Validation (Unit Tests)", () => {
  it("should require title field", () => {
    const formData = {
      linkType: "CUSTOM",
      title: "",
      url: "https://example.com",
      description: "",
    };

    const isValid = formData.title.trim() !== "" && formData.url.trim() !== "";
    expect(isValid).toBe(false);
  });

  it("should require URL field", () => {
    const formData = {
      linkType: "CUSTOM",
      title: "Test Link",
      url: "",
      description: "",
    };

    const isValid = formData.title.trim() !== "" && formData.url.trim() !== "";
    expect(isValid).toBe(false);
  });

  it("should allow empty description", () => {
    const formData = {
      linkType: "CUSTOM",
      title: "Test Link",
      url: "https://example.com",
      description: "",
    };

    const isValid = formData.title.trim() !== "" && formData.url.trim() !== "";
    expect(isValid).toBe(true);
  });

  it("should validate all fields are present for valid form", () => {
    const formData = {
      linkType: "AI_AGENT",
      title: "My AI Agent",
      url: "https://agent.example.com",
      description: "Customer AI agent dashboard",
    };

    const isValid =
      formData.linkType !== "" &&
      formData.title.trim() !== "" &&
      formData.url.trim() !== "";

    expect(isValid).toBe(true);
  });
});

describe("User Links Payload Preparation (Unit Tests)", () => {
  it("should prepare correct payload for creating a link", () => {
    const formData = {
      linkType: "AI_AGENT",
      title: "Test Agent",
      url: "https://agent.example.com",
      description: "Test description",
    };

    const payload = {
      linkType: formData.linkType,
      title: formData.title,
      url: formData.url,
      description: formData.description || null,
    };

    expect(payload.linkType).toBe("AI_AGENT");
    expect(payload.title).toBe("Test Agent");
    expect(payload.url).toBe("https://agent.example.com");
    expect(payload.description).toBe("Test description");
  });

  it("should handle null description correctly", () => {
    const formData = {
      linkType: "CUSTOM",
      title: "Test",
      url: "https://example.com",
      description: "",
    };

    const payload = {
      ...formData,
      description: formData.description || null,
    };

    expect(payload.description).toBeNull();
  });

  it("should prepare correct payload for updating a link", () => {
    const updates = {
      title: "Updated Title",
      url: "https://new-url.example.com",
    };

    expect(updates.title).toBe("Updated Title");
    expect(updates.url).toBe("https://new-url.example.com");
  });
});

/**
 * Integration Tests - API Endpoint Tests
 * These tests require a running server on localhost:9000
 * They are skipped by default when server is not available
 */
describe("User Links API Integration Tests", () => {
  const API_BASE = "http://localhost:9000/api/staff/users";
  let serverAvailable = false;

  beforeAll(async () => {
    // Check if server is running
    try {
      const response = await fetch("http://localhost:9000/api/health", {
        signal: AbortSignal.timeout(2000),
      });
      serverAvailable = response.ok;
    } catch {
      serverAvailable = false;
    }
  });

  describe("Authentication Tests", () => {
    it("should return 401 for unauthenticated GET request", async () => {
      if (!serverAvailable) {
        console.log("Skipping: Server not available");
        return;
      }

      const response = await fetch(`${API_BASE}/${TEST_USER_ID}/links`);
      expect(response.status).toBe(401);
    });

    it("should return 401 for unauthenticated POST request", async () => {
      if (!serverAvailable) {
        console.log("Skipping: Server not available");
        return;
      }

      const response = await fetch(`${API_BASE}/${TEST_USER_ID}/links`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          linkType: "KNOWLEDGE_BASE",
          title: "Test KB",
          url: "https://kb.example.com",
        }),
      });

      expect(response.status).toBe(401);
    });

    it("should return 401 for unauthenticated PATCH request", async () => {
      if (!serverAvailable) {
        console.log("Skipping: Server not available");
        return;
      }

      const response = await fetch(
        `${API_BASE}/${TEST_USER_ID}/links/test-link-id`,
        {
          method: "PATCH",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ title: "Updated Title" }),
        },
      );

      expect(response.status).toBe(401);
    });

    it("should return 401 for unauthenticated DELETE request", async () => {
      if (!serverAvailable) {
        console.log("Skipping: Server not available");
        return;
      }

      const response = await fetch(
        `${API_BASE}/${TEST_USER_ID}/links/test-link-id`,
        {
          method: "DELETE",
        },
      );

      expect(response.status).toBe(401);
    });
  });
});
