/**
 * Schema Validation Test: Prisma Relations
 * Validates that all relation names in code match the Prisma schema
 *
 * This test prevents the billing tab issue from recurring by:
 * 1. Checking subscription model has correct relation names
 * 2. Validating relation names are snake_case (not camelCase)
 * 3. Ensuring code uses exact names from schema
 */

import { readFileSync } from "fs";
import path from "path";

describe("Prisma Schema - Relation Names Validation", () => {
  let schemaContent: string;

  beforeAll(() => {
    const schemaPath = path.join(process.cwd(), "prisma/schema.prisma");
    schemaContent = readFileSync(schemaPath, "utf-8");
  });

  describe("Subscriptions Model Relations", () => {
    it("should have billing_history relation (snake_case)", () => {
      const subscriptionsModel = extractModel(schemaContent, "subscriptions");

      expect(subscriptionsModel).toContain("billing_history");
      expect(subscriptionsModel).toContain("billing_history[]");

      // Should NOT have camelCase version
      expect(subscriptionsModel).not.toContain(
        "billingHistory billing_history",
      );
    });

    it("should have users relation (not user)", () => {
      const subscriptionsModel = extractModel(schemaContent, "subscriptions");

      expect(subscriptionsModel).toContain("users                users");

      // Should NOT have singular "user" as relation name
      const lines = subscriptionsModel.split("\n");
      const userRelationLine = lines.find((line) => line.includes("@relation"));
      expect(userRelationLine).toBeDefined();
      expect(userRelationLine).toContain("users");
    });

    it("should have all expected relations", () => {
      const subscriptionsModel = extractModel(schemaContent, "subscriptions");

      const expectedRelations = [
        "billing_history      billing_history[]",
        "users                users",
      ];

      expectedRelations.forEach((relation) => {
        expect(subscriptionsModel).toContain(relation);
      });
    });
  });

  describe("Common Relation Name Mistakes (Regression Prevention)", () => {
    it("should NOT use camelCase for billing_history", () => {
      // Check all TypeScript files in app/api for wrong usage
      const apiFiles = [
        "app/api/subscription/details/route.ts",
        "app/api/user/package-status/route.ts",
      ];

      apiFiles.forEach((filePath) => {
        const fullPath = path.join(process.cwd(), filePath);
        const content = readFileSync(fullPath, "utf-8");

        // Should use billing_history (snake_case)
        if (
          content.includes("billing_history") ||
          content.includes("subscriptions")
        ) {
          // Check that we're not using the wrong camelCase version in Prisma queries
          const wrongUsageRegex = /include:\s*\{[^}]*billingHistory\s*:/g;
          const wrongMatches = content.match(wrongUsageRegex);

          expect(wrongMatches).toBeNull();
        }
      });
    });

    it('should NOT use "user" relation in WHERE clause', () => {
      const apiFiles = ["app/api/subscription/details/route.ts"];

      apiFiles.forEach((filePath) => {
        const fullPath = path.join(process.cwd(), filePath);
        const content = readFileSync(fullPath, "utf-8");

        // Check WHERE clauses use "users" not "user"
        const wrongWhereRegex = /where:\s*\{[^}]*\buser:\s*\{/g;
        const wrongMatches = content.match(wrongWhereRegex);

        // Should NOT have "user: {" in where clause (should be "users: {")
        if (wrongMatches) {
          // Allow "user:" in other contexts, but not in Prisma where for subscriptions
          const inSubscriptionQuery = content.includes(
            "prisma.subscriptions.findFirst",
          );
          if (inSubscriptionQuery) {
            expect(wrongMatches).toBeNull();
          }
        }
      });
    });
  });

  describe("NextAuth Version Compatibility", () => {
    it("should use NextAuth v5 syntax (not v4)", () => {
      const apiFiles = [
        "app/api/subscription/details/route.ts",
        "app/api/user/package-status/route.ts",
      ];

      apiFiles.forEach((filePath) => {
        const fullPath = path.join(process.cwd(), filePath);
        const content = readFileSync(fullPath, "utf-8");

        // Should NOT import getServerSession (v4 syntax)
        expect(content).not.toContain("import { getServerSession }");
        expect(content).not.toContain("from 'next-auth'");
        expect(content).not.toContain("getServerSession(authOptions)");

        // Should import auth (v5 syntax)
        if (content.includes("const session =")) {
          expect(content).toContain("import { auth }");
          expect(content).toContain("from '@/lib/auth'");
          expect(content).toContain("await auth()");
        }
      });
    });
  });
});

// Helper function to extract model definition from schema
function extractModel(schema: string, modelName: string): string {
  const modelRegex = new RegExp(
    `model ${modelName}\\s*\\{([^}]+(?:\\{[^}]*\\}[^}]*)*)\\}`,
    "s",
  );
  const match = schema.match(modelRegex);

  if (!match) {
    throw new Error(`Model ${modelName} not found in schema`);
  }

  return match[1];
}
