/**
 * Regression Tests for User Management Feature
 *
 * Ensures that future code changes don't break existing functionality
 * These tests should ALWAYS pass to prevent regressions
 */

import { prisma } from "@/lib/db";
import { getLocationFromIP, getIPFromRequest } from "@/lib/geolocation";
import bcrypt from "bcryptjs";

// Requires live database - skip in unit test environment
describe.skip("Critical Path Regression Tests", () => {
  test("CRITICAL: User login MUST create login history record", async () => {
    const user = await prisma.users.create({
      data: {
        email: "regression-login@example.com",
        name: "Regression Login Test",
        password: await bcrypt.hash("Pass123!", 12),
        role: "CUSTOMER",
      },
    });

    const beforeCount = await prisma.login_history.count({
      where: { userId: user.id },
    });

    // Simulate login
    await prisma.login_history.create({
      data: {
        userId: user.id,
        ipAddress: "203.0.113.1",
        provider: "credentials",
        success: true,
      },
    });

    const afterCount = await prisma.login_history.count({
      where: { userId: user.id },
    });

    expect(afterCount).toBe(beforeCount + 1);

    // Cleanup
    await prisma.login_history.deleteMany({ where: { userId: user.id } });
    await prisma.users.delete({ where: { id: user.id } });
  });

  test("CRITICAL: Suspended users MUST be blocked from login", async () => {
    const user = await prisma.users.create({
      data: {
        email: "regression-suspended@example.com",
        name: "Regression Suspended Test",
        role: "CUSTOMER",
        isSuspended: true,
        isActive: false,
      },
    });

    // Check suspension flag
    const checkUser = await prisma.users.findUnique({
      where: { id: user.id },
      select: { isSuspended: true },
    });

    expect(checkUser?.isSuspended).toBe(true);

    // In auth callback, this would return false
    const shouldAllowLogin = !checkUser?.isSuspended;
    expect(shouldAllowLogin).toBe(false);

    // Cleanup
    await prisma.users.delete({ where: { id: user.id } });
  });

  test("CRITICAL: Admin users MUST NOT be suspendable", async () => {
    const admin = await prisma.users.create({
      data: {
        email: "regression-admin@mawidi.com",
        name: "Regression Admin Test",
        username: "regression-admin",
        role: "ADMIN",
        password: await bcrypt.hash("Admin123!", 12),
      },
    });

    // Check if should allow suspension
    const isAdmin = admin.role === "ADMIN" || admin.role === "SUPER_ADMIN";
    const shouldBlockSuspension = isAdmin;

    expect(shouldBlockSuspension).toBe(true);

    // Cleanup
    await prisma.users.delete({ where: { id: admin.id } });
  });

  test("CRITICAL: Password MUST NEVER appear in API responses", async () => {
    const user = await prisma.users.create({
      data: {
        email: "regression-password@example.com",
        name: "Regression Password Test",
        password: await bcrypt.hash("Secret123!", 12),
        role: "CUSTOMER",
      },
    });

    const retrieved = await prisma.users.findUnique({
      where: { id: user.id },
    });

    // Remove password before sending to client
    const { password, ...safeUser } = retrieved!;

    expect(safeUser.password).toBeUndefined();
    expect(safeUser.email).toBe(user.email);
    expect(password).toBeDefined(); // Original has it

    // Cleanup
    await prisma.users.delete({ where: { id: user.id } });
  });

  test("CRITICAL: IP address MUST be captured on every login", async () => {
    const mockRequest = {
      headers: new Map([["x-forwarded-for", "203.0.113.50"]]),
    } as any;

    mockRequest.headers.get = (key: string) => mockRequest.headers.get(key);

    const ip = getIPFromRequest(mockRequest);

    expect(ip).toBeDefined();
    expect(ip).not.toBe("");
    expect(ip).toBe("203.0.113.50");
  });

  test("CRITICAL: Login count MUST increment on each login", async () => {
    const user = await prisma.users.create({
      data: {
        email: "regression-count@example.com",
        name: "Regression Count Test",
        role: "CUSTOMER",
        loginCount: 0,
      },
    });

    // Simulate 3 logins
    for (let i = 0; i < 3; i++) {
      await prisma.users.update({
        where: { id: user.id },
        data: { loginCount: { increment: 1 } },
      });
    }

    const updated = await prisma.users.findUnique({
      where: { id: user.id },
      select: { loginCount: true },
    });

    expect(updated?.loginCount).toBe(3);

    // Cleanup
    await prisma.users.delete({ where: { id: user.id } });
  });

  test("CRITICAL: Geographic data MUST be stored with login history", async () => {
    const user = await prisma.users.create({
      data: {
        email: "regression-geo@example.com",
        name: "Regression Geo Test",
        role: "CUSTOMER",
      },
    });

    const loginRecord = await prisma.login_history.create({
      data: {
        userId: user.id,
        ipAddress: "203.0.113.1",
        country: "Qatar",
        countryCode: "QA",
        city: "Doha",
        latitude: 25.2854,
        longitude: 51.531,
        timezone: "Asia/Qatar",
        provider: "credentials",
        success: true,
      },
    });

    expect(loginRecord.country).toBe("Qatar");
    expect(loginRecord.city).toBe("Doha");
    expect(loginRecord.latitude).toBeDefined();
    expect(loginRecord.longitude).toBeDefined();

    // Cleanup
    await prisma.login_history.delete({ where: { id: loginRecord.id } });
    await prisma.users.delete({ where: { id: user.id } });
  });
});

describe.skip("API Response Format Regression Tests", () => {
  test("GET /api/staff/dashboard/users MUST return expected structure", async () => {
    // This ensures the API response structure never changes unexpectedly
    const expectedStructure = {
      users: expect.arrayContaining([
        expect.objectContaining({
          id: expect.any(String),
          email: expect.any(String),
          name: expect.any(String),
          role: expect.any(String),
          lastLoginIp: expect.anything(),
          lastLoginCountry: expect.anything(),
          loginCount: expect.any(Number),
          accountStatus: expect.any(String),
        }),
      ]),
      analytics: expect.objectContaining({
        total: expect.any(Number),
        active: expect.any(Number),
        suspended: expect.any(Number),
        locked: expect.any(Number),
      }),
      pagination: expect.objectContaining({
        page: expect.any(Number),
        limit: expect.any(Number),
        total: expect.any(Number),
        totalPages: expect.any(Number),
      }),
    };

    // This structure MUST NOT change without updating tests
    expect(expectedStructure).toBeDefined();
  });

  test("GET /api/staff/users/[id] MUST return expected structure", () => {
    const expectedStructure = {
      user: expect.objectContaining({
        id: expect.any(String),
        email: expect.any(String),
        name: expect.any(String),
        loginHistory: expect.any(Array),
        adminNotes: expect.any(Array),
        billingEmails: expect.any(Array),
      }),
      analytics: expect.objectContaining({
        loginStats: expect.objectContaining({
          total: expect.any(Number),
          uniqueIps: expect.any(Number),
          uniqueCountries: expect.any(Number),
          successRate: expect.any(Number),
        }),
      }),
    };

    expect(expectedStructure).toBeDefined();
  });
});

describe.skip("Database Schema Regression Tests", () => {
  test("User model MUST have all required fields", async () => {
    const user = await prisma.users.create({
      data: {
        email: "schema-check@example.com",
        name: "Schema Check",
        role: "CUSTOMER",
      },
    });

    const retrieved = await prisma.users.findUnique({
      where: { id: user.id },
    });

    // Essential fields that MUST exist
    expect(retrieved).toHaveProperty("id");
    expect(retrieved).toHaveProperty("email");
    expect(retrieved).toHaveProperty("name");
    expect(retrieved).toHaveProperty("role");
    expect(retrieved).toHaveProperty("isActive");
    expect(retrieved).toHaveProperty("isSuspended");
    expect(retrieved).toHaveProperty("lastLoginIp");
    expect(retrieved).toHaveProperty("lastLoginCountry");
    expect(retrieved).toHaveProperty("lastLoginCity");
    expect(retrieved).toHaveProperty("loginCount");
    expect(retrieved).toHaveProperty("createdAt");
    expect(retrieved).toHaveProperty("updatedAt");

    await prisma.users.delete({ where: { id: user.id } });
  });

  test("AdminNote model MUST have all required fields", async () => {
    const user = await prisma.users.create({
      data: {
        email: "note-schema@example.com",
        name: "Note Schema Test",
        role: "CUSTOMER",
      },
    });

    const note = await prisma.admin_notes.create({
      data: {
        userId: user.id,
        staffId: "staff-1",
        content: "Schema check note",
        category: "GENERAL",
      },
    });

    expect(note).toHaveProperty("id");
    expect(note).toHaveProperty("userId");
    expect(note).toHaveProperty("staffId");
    expect(note).toHaveProperty("content");
    expect(note).toHaveProperty("category");
    expect(note).toHaveProperty("isPrivate");
    expect(note).toHaveProperty("createdAt");
    expect(note).toHaveProperty("updatedAt");

    await prisma.admin_notes.delete({ where: { id: note.id } });
    await prisma.users.delete({ where: { id: user.id } });
  });

  test("LoginHistory model MUST have all required fields", async () => {
    const user = await prisma.users.create({
      data: {
        email: "login-schema@example.com",
        name: "Login Schema Test",
        role: "CUSTOMER",
      },
    });

    const login = await prisma.login_history.create({
      data: {
        userId: user.id,
        ipAddress: "203.0.113.1",
        provider: "credentials",
        success: true,
      },
    });

    expect(login).toHaveProperty("id");
    expect(login).toHaveProperty("userId");
    expect(login).toHaveProperty("ipAddress");
    expect(login).toHaveProperty("userAgent");
    expect(login).toHaveProperty("country");
    expect(login).toHaveProperty("countryCode");
    expect(login).toHaveProperty("city");
    expect(login).toHaveProperty("region");
    expect(login).toHaveProperty("latitude");
    expect(login).toHaveProperty("longitude");
    expect(login).toHaveProperty("timezone");
    expect(login).toHaveProperty("provider");
    expect(login).toHaveProperty("success");
    expect(login).toHaveProperty("failReason");
    expect(login).toHaveProperty("createdAt");

    await prisma.login_history.delete({ where: { id: login.id } });
    await prisma.users.delete({ where: { id: user.id } });
  });
});

describe.skip("Feature Flag Regression Tests", () => {
  test("isActive flag MUST default to true", async () => {
    const user = await prisma.users.create({
      data: {
        email: "default-active@example.com",
        name: "Default Active Test",
        role: "CUSTOMER",
      },
    });

    expect(user.isActive).toBe(true);

    await prisma.users.delete({ where: { id: user.id } });
  });

  test("isSuspended flag MUST default to false", async () => {
    const user = await prisma.users.create({
      data: {
        email: "default-suspended@example.com",
        name: "Default Suspended Test",
        role: "CUSTOMER",
      },
    });

    expect(user.isSuspended).toBe(false);

    await prisma.users.delete({ where: { id: user.id } });
  });

  test("loginCount MUST default to 0", async () => {
    const user = await prisma.users.create({
      data: {
        email: "default-count@example.com",
        name: "Default Count Test",
        role: "CUSTOMER",
      },
    });

    expect(user.loginCount).toBe(0);

    await prisma.users.delete({ where: { id: user.id } });
  });

  test("isPrivate flag MUST default to true for admin notes", async () => {
    const user = await prisma.users.create({
      data: {
        email: "note-privacy@example.com",
        name: "Note Privacy Test",
        role: "CUSTOMER",
      },
    });

    const note = await prisma.admin_notes.create({
      data: {
        userId: user.id,
        staffId: "staff-1",
        content: "Privacy test note",
        category: "GENERAL",
        // isPrivate not specified, should default to true
      },
    });

    expect(note.isPrivate).toBe(true);

    await prisma.admin_notes.delete({ where: { id: note.id } });
    await prisma.users.delete({ where: { id: user.id } });
  });
});

describe.skip("Backward Compatibility Tests", () => {
  test("Existing user queries MUST still work with new fields", async () => {
    // Old-style query (without new fields)
    const users = await prisma.users.findMany({
      where: { role: "CUSTOMER" },
      select: {
        id: true,
        email: true,
        name: true,
        createdAt: true,
      },
    });

    expect(Array.isArray(users)).toBe(true);
    users.forEach((user) => {
      expect(user).toHaveProperty("id");
      expect(user).toHaveProperty("email");
      expect(user).toHaveProperty("name");
      expect(user).toHaveProperty("createdAt");
    });
  });

  test("Existing user updates MUST still work", async () => {
    const user = await prisma.users.create({
      data: {
        email: "backward-compat@example.com",
        name: "Backward Compat Test",
        role: "CUSTOMER",
      },
    });

    // Old-style update (without new fields)
    await prisma.users.update({
      where: { id: user.id },
      data: {
        name: "Updated Name",
        lastLoginAt: new Date(),
      },
    });

    const updated = await prisma.users.findUnique({
      where: { id: user.id },
    });

    expect(updated?.name).toBe("Updated Name");
    expect(updated?.lastLoginAt).toBeDefined();

    await prisma.users.delete({ where: { id: user.id } });
  });
});

describe.skip("Data Consistency Regression Tests", () => {
  test("suspendedAt MUST be set when isSuspended is true", async () => {
    const user = await prisma.users.create({
      data: {
        email: "consistency-suspend@example.com",
        name: "Consistency Test",
        role: "CUSTOMER",
        isSuspended: true,
        suspendedAt: new Date(),
        suspendedReason: "Test",
      },
    });

    expect(user.isSuspended).toBe(true);
    expect(user.suspendedAt).toBeDefined();
    expect(user.suspendedReason).toBeDefined();

    await prisma.users.delete({ where: { id: user.id } });
  });

  test("lastLoginCountry and lastLoginCity MUST update together", async () => {
    const user = await prisma.users.create({
      data: {
        email: "consistency-location@example.com",
        name: "Location Consistency Test",
        role: "CUSTOMER",
      },
    });

    await prisma.users.update({
      where: { id: user.id },
      data: {
        lastLoginCountry: "Qatar",
        lastLoginCity: "Doha",
        lastLoginIp: "203.0.113.1",
      },
    });

    const updated = await prisma.users.findUnique({
      where: { id: user.id },
    });

    if (updated?.lastLoginCountry) {
      expect(updated.lastLoginCity).toBeDefined();
    }

    if (updated?.lastLoginCity) {
      expect(updated.lastLoginCountry).toBeDefined();
    }

    await prisma.users.delete({ where: { id: user.id } });
  });

  test("Billing email status MUST be SENT by default", async () => {
    const user = await prisma.users.create({
      data: {
        email: "billing-default@example.com",
        name: "Billing Default Test",
        role: "CUSTOMER",
      },
    });

    const billing = await prisma.billing_emails.create({
      data: {
        userId: user.id,
        staffId: "staff-1",
        subject: "Test",
        body: "Test",
        // status not specified, should default to SENT
      },
    });

    expect(billing.status).toBe("SENT");

    await prisma.billing_emails.delete({ where: { id: billing.id } });
    await prisma.users.delete({ where: { id: user.id } });
  });
});

describe.skip("Index Performance Regression Tests", () => {
  test("Querying by (isActive, isSuspended) MUST use index", async () => {
    const startTime = Date.now();

    await prisma.users.findMany({
      where: {
        isActive: true,
        isSuspended: false,
      },
      take: 100,
    });

    const duration = Date.now() - startTime;

    // With index, should be under 50ms even with thousands of users
    expect(duration).toBeLessThan(100);
  });

  test("Querying by lastLoginCountry MUST use index", async () => {
    const startTime = Date.now();

    await prisma.users.findMany({
      where: {
        lastLoginCountry: "Qatar",
      },
      take: 100,
    });

    const duration = Date.now() - startTime;

    expect(duration).toBeLessThan(100);
  });

  test("Querying login history by userId MUST use index", async () => {
    const startTime = Date.now();

    await prisma.login_history.findMany({
      where: {
        userId: "any-user-id",
      },
      orderBy: { createdAt: "desc" },
      take: 50,
    });

    const duration = Date.now() - startTime;

    expect(duration).toBeLessThan(50);
  });
});

describe.skip("Error Handling Regression Tests", () => {
  test("Geolocation failure MUST NOT prevent login", async () => {
    // Mock geolocation failure
    jest.spyOn(console, "error").mockImplementation(() => {});

    const mockGetLocation = async (ip: string) => {
      throw new Error("Geolocation service unavailable");
    };

    let caughtError = false;
    let location = null;

    try {
      location = await mockGetLocation("203.0.113.1");
    } catch (error) {
      caughtError = true;
      location = null; // Allow login to proceed
    }

    expect(caughtError).toBe(true);
    expect(location).toBeNull();

    // Login should still be allowed
    const shouldAllowLogin = true; // Even if geolocation fails

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

  test("Database error MUST be caught and handled", async () => {
    let errorHandled = false;

    try {
      await prisma.users.findUnique({
        where: { id: null as any }, // Invalid query
      });
    } catch (error) {
      errorHandled = true;
      // Error should be logged but not crash the app
    }

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