/**
 * API Integration Tests for Dashboard Workflows Endpoints
 *
 * Tests:
 * - GET /api/dashboard/workflows returns workflows with tier info
 * - Returns 401 for unauthenticated requests
 * - POST creates workflow with valid data
 * - CSRF validation works
 * - Rate limiting enforcement
 */

import { NextRequest } from "next/server";
import { GET, POST } from "@/app/api/dashboard/workflows/route";
import { auth } from "@/lib/auth";
import { prisma } from "@/lib/db";
import { validateCSRFToken } from "@/lib/csrf";
import { applyRateLimit } from "@/lib/rate-limiter";
import { getAuthenticatedUser } from "@/lib/utils/auth-helpers.util";
import { WorkflowManagementService } from "@/lib/services/workflow-management.service";

// Mock cuid2 module
jest.mock("@paralleldrive/cuid2", () => ({
  createId: jest.fn(
    () => "mock-cuid-" + Math.random().toString(36).substr(2, 9),
  ),
}));

// Mock next-auth before importing anything
jest.mock("next-auth", () => ({
  __esModule: true,
  default: jest.fn(),
}));

// Mock next-auth/next
jest.mock("next-auth/next", () => ({
  __esModule: true,
  default: jest.fn(),
  getServerSession: jest.fn(),
}));

const { createId } = require("@paralleldrive/cuid2");

// Mock dependencies
jest.mock("@/lib/auth", () => ({
  auth: jest.fn(),
}));
jest.mock("@/lib/utils/auth-helpers.util");
jest.mock("@/lib/db");
jest.mock("@/lib/csrf");
jest.mock("@/lib/rate-limiter");
jest.mock("@/lib/dual-database", () => ({
  saveToBothDatabases: jest.fn(),
  saveUserToBoth: jest.fn(),
  saveAuditLogToBoth: jest.fn(),
}), { virtual: true });
jest.mock("@/lib/services/workflow-management.service", () => ({
  WorkflowManagementService: {
    getUserWorkflows: jest.fn(),
    getAllowedWorkflowsByTier: jest.fn(),
    createWorkflow: jest.fn(),
  },
}));
jest.mock("@/lib/logger", () => ({
  logger: {
    scope: jest.fn().mockReturnValue({
      info: jest.fn(),
      warn: jest.fn(),
      error: jest.fn(),
    }),
  },
}));
jest.mock("@/lib/data-source", () => ({
  getDataSource: jest.fn(() => "prisma"),
}));

describe("Workflows API Integration Tests", () => {
  const mockUserId = `user_${createId()}`;
  const mockEmail = "test@mawidi.com";

  beforeEach(() => {
    jest.clearAllMocks();
  });

  describe("GET /api/dashboard/workflows", () => {
    it("should return workflows with tier information for authenticated user", async () => {
      // Mock authenticated user
      (getAuthenticatedUser as jest.Mock).mockResolvedValue({
        userId: mockUserId,
        email: mockEmail,
      });

      // Mock user with tier2 subscription (route reads subscriptions array)
      const mockUser = {
        id: mockUserId,
        email: mockEmail,
        name: "Test User",
        selectedPackage: null,
        subscriptions: [{ tierId: "tier2" }],
      };

      (prisma.users.findUnique as jest.Mock).mockResolvedValue(mockUser);

      // Mock workflows from WorkflowManagementService
      const mockWorkflows = [
        {
          id: createId(),
          userId: mockUserId,
          workflowType: "ai_agent",
          status: "active",
          config: {},
          canActivate: true,
          createdAt: new Date(),
          updatedAt: new Date(),
        },
        {
          id: createId(),
          userId: mockUserId,
          workflowType: "whatsapp",
          status: "inactive",
          config: {},
          canActivate: true,
          createdAt: new Date(),
          updatedAt: new Date(),
        },
      ];

      (
        WorkflowManagementService.getUserWorkflows as jest.Mock
      ).mockResolvedValue(mockWorkflows);
      (
        WorkflowManagementService.getAllowedWorkflowsByTier as jest.Mock
      ).mockReturnValue(["ai_agent", "whatsapp", "quotations"]);

      // Create request
      const request = new NextRequest(
        "http://localhost:9000/api/dashboard/workflows",
      );

      // Execute
      const response = await GET(request);
      const data = await response.json();

      // Assertions
      expect(response.status).toBe(200);
      expect(data.success).toBe(true);
      expect(data.currentTier).toBe("tier2");
      expect(data.workflows).toHaveLength(2);
      expect(data.allowedFeatures).toContain("ai_agent");
      expect(data.allowedFeatures).toContain("whatsapp");
      expect(data.allowedFeatures).toContain("quotations");
      expect(data.totalCount).toBe(2);
    });

    it("should return 401 for unauthenticated request", async () => {
      (getAuthenticatedUser as jest.Mock).mockResolvedValue(null);

      const request = new NextRequest(
        "http://localhost:9000/api/dashboard/workflows",
      );
      const response = await GET(request);
      const data = await response.json();

      expect(response.status).toBe(401);
      expect(data.success).toBe(false);
      expect(data.error).toBe("Unauthorized");
    });

    it("should return 404 when user not found in database", async () => {
      (getAuthenticatedUser as jest.Mock).mockResolvedValue({
        userId: mockUserId,
        email: mockEmail,
      });

      (prisma.users.findUnique as jest.Mock).mockResolvedValue(null);

      const request = new NextRequest(
        "http://localhost:9000/api/dashboard/workflows",
      );
      const response = await GET(request);
      const data = await response.json();

      expect(response.status).toBe(404);
      expect(data.success).toBe(false);
      expect(data.error).toBe("User not found");
    });

    it("should default to tier1 when user has no subscription", async () => {
      (getAuthenticatedUser as jest.Mock).mockResolvedValue({
        userId: mockUserId,
        email: mockEmail,
      });

      const mockUser = {
        id: mockUserId,
        email: mockEmail,
        name: "Test User",
        selectedPackage: null,
        subscriptions: [],
      };

      (prisma.users.findUnique as jest.Mock).mockResolvedValue(mockUser);
      (
        WorkflowManagementService.getUserWorkflows as jest.Mock
      ).mockResolvedValue([]);
      (
        WorkflowManagementService.getAllowedWorkflowsByTier as jest.Mock
      ).mockReturnValue(["ai_agent", "whatsapp", "quotations"]);

      const request = new NextRequest(
        "http://localhost:9000/api/dashboard/workflows",
      );
      const response = await GET(request);
      const data = await response.json();

      expect(response.status).toBe(200);
      expect(data.currentTier).toBe("tier1");
      expect(data.allowedFeatures).toHaveLength(3); // tier1 has 3 features
    });

    it("should handle database errors gracefully", async () => {
      (getAuthenticatedUser as jest.Mock).mockResolvedValue({
        userId: mockUserId,
        email: mockEmail,
      });

      (prisma.users.findUnique as jest.Mock).mockRejectedValue(
        new Error("Database connection error"),
      );

      const request = new NextRequest(
        "http://localhost:9000/api/dashboard/workflows",
      );
      const response = await GET(request);
      const data = await response.json();

      expect(response.status).toBe(500);
      expect(data.success).toBe(false);
      expect(data.error).toBe("Internal server error");
    });
  });

  describe("POST /api/dashboard/workflows", () => {
    it("should create workflow with valid data and CSRF token", async () => {
      // Mock rate limiting (pass)
      (applyRateLimit as jest.Mock).mockResolvedValue(null);

      // Mock authenticated user
      (getAuthenticatedUser as jest.Mock).mockResolvedValue({
        userId: mockUserId,
        email: mockEmail,
      });

      // Mock CSRF validation (pass)
      (validateCSRFToken as jest.Mock).mockReturnValue(true);

      // Mock no existing workflow (checked by WorkflowManagementService internally)
      (prisma.userWorkflow.findFirst as jest.Mock).mockResolvedValue(null);

      // Mock workflow creation via service
      const mockCreatedWorkflow = {
        id: createId(),
        userId: mockUserId,
        workflowType: "ai_agent",
        n8nWorkflowId: "n8n_123",
        status: "inactive",
        config: { greeting: "Hello!" },
        lastRunAt: null,
        lastRunStatus: null,
        createdAt: new Date(),
        updatedAt: new Date(),
      };

      (WorkflowManagementService.createWorkflow as jest.Mock).mockResolvedValue(
        mockCreatedWorkflow,
      );

      // Create request with body
      const requestBody = {
        workflowType: "ai_agent",
        n8nWorkflowId: "n8n_123",
        config: { greeting: "Hello!" },
      };

      const request = new NextRequest(
        "http://localhost:9000/api/dashboard/workflows",
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            "x-csrf-token": "valid-token",
          },
          body: JSON.stringify(requestBody),
        },
      );

      // Execute
      const response = await POST(request);
      const data = await response.json();

      // Assertions
      expect(response.status).toBe(201);
      expect(data.success).toBe(true);
      expect(data.workflow.workflowType).toBe("ai_agent");
      expect(data.workflow.status).toBe("inactive");
      expect(data.message).toBe("Workflow created successfully");
    });

    it("should return 401 for unauthenticated request", async () => {
      (applyRateLimit as jest.Mock).mockResolvedValue(null);
      (getAuthenticatedUser as jest.Mock).mockResolvedValue(null);

      const request = new NextRequest(
        "http://localhost:9000/api/dashboard/workflows",
        {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            workflowType: "ai_agent",
            n8nWorkflowId: "n8n_123",
          }),
        },
      );

      const response = await POST(request);
      const data = await response.json();

      expect(response.status).toBe(401);
      expect(data.success).toBe(false);
      expect(data.error).toBe("Unauthorized");
    });

    it("should return 403 when CSRF token is invalid", async () => {
      (applyRateLimit as jest.Mock).mockResolvedValue(null);
      (getAuthenticatedUser as jest.Mock).mockResolvedValue({
        userId: mockUserId,
        email: mockEmail,
      });
      (validateCSRFToken as jest.Mock).mockReturnValue(false);

      const request = new NextRequest(
        "http://localhost:9000/api/dashboard/workflows",
        {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            workflowType: "ai_agent",
            n8nWorkflowId: "n8n_123",
          }),
        },
      );

      const response = await POST(request);
      const data = await response.json();

      expect(response.status).toBe(403);
      expect(data.success).toBe(false);
      expect(data.error).toBe("Invalid CSRF token");
    });

    it("should enforce rate limiting", async () => {
      const rateLimitResponse = new Response(
        JSON.stringify({ error: "Too many requests" }),
        { status: 429 },
      );

      (applyRateLimit as jest.Mock).mockResolvedValue(rateLimitResponse);

      const request = new NextRequest(
        "http://localhost:9000/api/dashboard/workflows",
        {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            workflowType: "ai_agent",
            n8nWorkflowId: "n8n_123",
          }),
        },
      );

      const response = await POST(request);

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

    it("should return 400 when workflowType is missing", async () => {
      (applyRateLimit as jest.Mock).mockResolvedValue(null);
      (getAuthenticatedUser as jest.Mock).mockResolvedValue({
        userId: mockUserId,
        email: mockEmail,
      });
      (validateCSRFToken as jest.Mock).mockReturnValue(true);

      const request = new NextRequest(
        "http://localhost:9000/api/dashboard/workflows",
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            "x-csrf-token": "valid-token",
          },
          body: JSON.stringify({ n8nWorkflowId: "n8n_123" }), // Missing workflowType
        },
      );

      const response = await POST(request);
      const data = await response.json();

      expect(response.status).toBe(400);
      expect(data.success).toBe(false);
      expect(data.error).toBe("Workflow type is required");
    });

    it("should return 400 when n8nWorkflowId is missing", async () => {
      (applyRateLimit as jest.Mock).mockResolvedValue(null);
      (getAuthenticatedUser as jest.Mock).mockResolvedValue({
        userId: mockUserId,
        email: mockEmail,
      });
      (validateCSRFToken as jest.Mock).mockReturnValue(true);

      const request = new NextRequest(
        "http://localhost:9000/api/dashboard/workflows",
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            "x-csrf-token": "valid-token",
          },
          body: JSON.stringify({ workflowType: "ai_agent" }), // Missing n8nWorkflowId
        },
      );

      const response = await POST(request);
      const data = await response.json();

      expect(response.status).toBe(400);
      expect(data.success).toBe(false);
      expect(data.error).toBe("n8n workflow ID is required");
    });

    it("should return 409 when duplicate workflow exists", async () => {
      (applyRateLimit as jest.Mock).mockResolvedValue(null);
      (getAuthenticatedUser as jest.Mock).mockResolvedValue({
        userId: mockUserId,
        email: mockEmail,
      });
      (validateCSRFToken as jest.Mock).mockReturnValue(true);

      // Service throws when workflow already exists
      (WorkflowManagementService.createWorkflow as jest.Mock).mockRejectedValue(
        new Error("Workflow of type ai_agent already exists for this user"),
      );

      const request = new NextRequest(
        "http://localhost:9000/api/dashboard/workflows",
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            "x-csrf-token": "valid-token",
          },
          body: JSON.stringify({
            workflowType: "ai_agent",
            n8nWorkflowId: "n8n_123",
          }),
        },
      );

      const response = await POST(request);
      const data = await response.json();

      expect(response.status).toBe(409);
      expect(data.success).toBe(false);
      expect(data.error).toContain("already exists");
    });

    it("should handle server errors during workflow creation", async () => {
      (applyRateLimit as jest.Mock).mockResolvedValue(null);
      (getAuthenticatedUser as jest.Mock).mockResolvedValue({
        userId: mockUserId,
        email: mockEmail,
      });
      (validateCSRFToken as jest.Mock).mockReturnValue(true);
      (prisma.userWorkflow.findFirst as jest.Mock).mockResolvedValue(null);
      (WorkflowManagementService.createWorkflow as jest.Mock).mockRejectedValue(
        new Error("Database write error"),
      );

      const request = new NextRequest(
        "http://localhost:9000/api/dashboard/workflows",
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            "x-csrf-token": "valid-token",
          },
          body: JSON.stringify({
            workflowType: "ai_agent",
            n8nWorkflowId: "n8n_123",
          }),
        },
      );

      const response = await POST(request);
      const data = await response.json();

      expect(response.status).toBe(500);
      expect(data.success).toBe(false);
      expect(data.error).toBe("Failed to create workflow");
    });

    it("should create workflow with optional config", async () => {
      (applyRateLimit as jest.Mock).mockResolvedValue(null);
      (getAuthenticatedUser as jest.Mock).mockResolvedValue({
        userId: mockUserId,
        email: mockEmail,
      });
      (validateCSRFToken as jest.Mock).mockReturnValue(true);
      (prisma.userWorkflow.findFirst as jest.Mock).mockResolvedValue(null);

      const mockCreatedWorkflow = {
        id: createId(),
        userId: mockUserId,
        workflowType: "whatsapp",
        n8nWorkflowId: "n8n_whatsapp",
        status: "inactive",
        config: {}, // Empty config
        lastRunAt: null,
        lastRunStatus: null,
        createdAt: new Date(),
        updatedAt: new Date(),
      };

      (WorkflowManagementService.createWorkflow as jest.Mock).mockResolvedValue(
        mockCreatedWorkflow,
      );

      const request = new NextRequest(
        "http://localhost:9000/api/dashboard/workflows",
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            "x-csrf-token": "valid-token",
          },
          body: JSON.stringify({
            workflowType: "whatsapp",
            n8nWorkflowId: "n8n_whatsapp",
            // No config provided
          }),
        },
      );

      const response = await POST(request);
      const data = await response.json();

      expect(response.status).toBe(201);
      expect(data.success).toBe(true);
      expect(data.workflow.config).toEqual({});
    });
  });

  describe("Cross-tier workflow visibility", () => {
    it("should show workflow permission flags for tier1 user", async () => {
      (getAuthenticatedUser as jest.Mock).mockResolvedValue({
        userId: mockUserId,
        email: mockEmail,
      });

      const mockUser = {
        id: mockUserId,
        email: mockEmail,
        selectedPackage: null,
        subscriptions: [{ tierId: "tier1" }],
      };

      (prisma.users.findUnique as jest.Mock).mockResolvedValue(mockUser);

      const mockWorkflows = [
        {
          id: createId(),
          userId: mockUserId,
          workflowType: "ai_agent", // Allowed in tier1
          status: "active",
          config: {},
          canActivate: true,
          createdAt: new Date(),
          updatedAt: new Date(),
        },
        {
          id: createId(),
          userId: mockUserId,
          workflowType: "lead_generation", // Requires tier5
          status: "inactive",
          config: {},
          canActivate: false,
          requiresUpgrade: true,
          createdAt: new Date(),
          updatedAt: new Date(),
        },
      ];

      (
        WorkflowManagementService.getUserWorkflows as jest.Mock
      ).mockResolvedValue(mockWorkflows);
      (
        WorkflowManagementService.getAllowedWorkflowsByTier as jest.Mock
      ).mockReturnValue(["ai_agent", "whatsapp", "quotations"]);

      const request = new NextRequest(
        "http://localhost:9000/api/dashboard/workflows",
      );
      const response = await GET(request);
      const data = await response.json();

      expect(response.status).toBe(200);
      expect(data.workflows).toHaveLength(2);
      expect(data.workflows[0].canActivate).toBe(true);
      expect(data.workflows[1].canActivate).toBe(false);
      expect(data.workflows[1].requiresUpgrade).toBe(true);
    });
  });
});
