/**
 * Comprehensive tests for the file examples system
 */

import {
  FileExampleManager,
  sampleFileExamples,
  type FileExample as _FileExample,
} from "../data/fileExamples";

// Test helper to run all tests
export async function runFileExamplesTests() {
  console.log("🧪 Running File Examples System Tests...\n");

  let passed = 0;
  let failed = 0;

  const test = (name: string, fn: () => void | Promise<void>) => {
    try {
      const result = fn();
      if (result instanceof Promise) {
        return result
          .then(() => {
            console.log(`✅ ${name}`);
            passed++;
          })
          .catch((err) => {
            console.log(`❌ ${name}`);
            console.error(`   Error: ${err.message}`);
            failed++;
          });
      } else {
        console.log(`✅ ${name}`);
        passed++;
      }
    } catch (err: any) {
      console.log(`❌ ${name}`);
      console.error(`   Error: ${err.message}`);
      failed++;
    }
  };

  // Test 1: Data structure exists
  test("File examples data is loaded", () => {
    if (!sampleFileExamples || sampleFileExamples.length === 0) {
      throw new Error("No file examples found");
    }
    console.log(`   Found ${sampleFileExamples.length} groups`);
  });

  // Test 2: FileExampleManager exists
  test("FileExampleManager class is available", () => {
    if (!FileExampleManager) {
      throw new Error("FileExampleManager not found");
    }
  });

  // Test 3: Sample data has correct structure
  test("Sample data has correct structure", () => {
    const group = sampleFileExamples[0];
    if (!group.groupId || !group.title || !Array.isArray(group.files)) {
      throw new Error("Invalid group structure");
    }

    const file = group.files[0];
    if (!file.id || !file.filename || !file.content || !file.language) {
      throw new Error("Invalid file structure");
    }

    // Check for postSlug
    if (!file.postSlug) {
      throw new Error("Files missing postSlug property");
    }
  });

  // Test 4: Get all groups
  test("FileExampleManager.getAllGroups() works", async () => {
    const groups = await FileExampleManager.getAllGroups();
    if (!Array.isArray(groups) || groups.length === 0) {
      throw new Error("getAllGroups returned invalid result");
    }
  });

  // Test 5: Get specific group
  test("FileExampleManager.getGroup() works", async () => {
    const group = await FileExampleManager.getGroup("python-data-processing");
    if (!group) {
      throw new Error("Group not found");
    }
    if (group.groupId !== "python-data-processing") {
      throw new Error("Wrong group returned");
    }
  });

  // Test 6: Search files
  test("FileExampleManager.searchFiles() works", async () => {
    const results = await FileExampleManager.searchFiles("python");
    if (!Array.isArray(results)) {
      throw new Error("searchFiles returned invalid result");
    }
    if (results.length === 0) {
      throw new Error('No results found for "python"');
    }
  });

  // Test 7: Get file by ID
  test("FileExampleManager.getFileExample() works", async () => {
    const file = await FileExampleManager.getFileExample(
      "python-data-processor",
    );
    if (!file) {
      throw new Error("File not found");
    }
    if (file.id !== "python-data-processor") {
      throw new Error("Wrong file returned");
    }
  });

  // Test 8: Filter by postSlug
  test("Filter files by postSlug", async () => {
    const groups = await FileExampleManager.getAllGroups();
    const debuggingFiles = groups
      .flatMap((g) => g.files)
      .filter((f) => f.postSlug === "debugging-tips");

    if (debuggingFiles.length === 0) {
      throw new Error("No files found for debugging-tips");
    }

    console.log(`   Found ${debuggingFiles.length} files for debugging-tips`);
  });

  // Test 9: Filter by postSlug and groupId
  test("Filter files by postSlug and groupId", async () => {
    const groups = await FileExampleManager.getAllGroups();
    const filtered = groups
      .filter((g) => g.groupId === "python-data-processing")
      .map((g) => ({
        ...g,
        files: g.files.filter((f) => f.postSlug === "debugging-tips"),
      }))
      .filter((g) => g.files.length > 0);

    if (filtered.length === 0) {
      throw new Error(
        "No files found for debugging-tips in python-data-processing",
      );
    }

    console.log(`   Found ${filtered[0].files.length} files`);
  });

  // Test 10: Filter by postSlug and tags
  test("Filter files by postSlug and tags", async () => {
    const groups = await FileExampleManager.getAllGroups();
    const tags = ["architecture", "design-patterns"];

    const filtered = groups
      .map((g) => ({
        ...g,
        files: g.files.filter(
          (f) =>
            f.postSlug === "architecture-patterns" &&
            f.tags?.some((tag) => tags.includes(tag)),
        ),
      }))
      .filter((g) => g.files.length > 0);

    if (filtered.length === 0) {
      throw new Error("No files found for architecture-patterns with tags");
    }

    console.log(`   Found ${filtered[0].files.length} files`);
  });

  // Test 11: Download single file
  test("Download single file", async () => {
    const result = await FileExampleManager.downloadFile(
      "python-data-processor",
    );
    if (!result) {
      throw new Error("Download failed");
    }
    if (!result.filename || !result.content || !result.mimeType) {
      throw new Error("Invalid download result");
    }
  });

  // Test 12: Download multiple files
  test("Download multiple files", async () => {
    const files = await FileExampleManager.downloadMultiple([
      "python-data-processor",
      "python-config-example",
    ]);
    if (!Array.isArray(files) || files.length !== 2) {
      throw new Error("Invalid multiple download result");
    }
  });

  // Test 13: Get available tags
  test("Get available tags", async () => {
    const tags = await FileExampleManager.getAvailableTags();
    if (!Array.isArray(tags) || tags.length === 0) {
      throw new Error("No tags found");
    }
    if (!tags.includes("python") || !tags.includes("architecture")) {
      throw new Error("Expected tags not found");
    }
  });

  // Test 14: Create new file example
  test("Create new file example", async () => {
    const newExample = await FileExampleManager.createFileExample({
      filename: "test.py",
      content: 'print("test")',
      language: "python",
      description: "Test file",
      tags: ["test"],
      postSlug: "test-post",
    });

    if (!newExample.id) {
      throw new Error("New example has no ID");
    }

    // Verify it was added
    const retrieved = await FileExampleManager.getFileExample(newExample.id);
    if (!retrieved || retrieved.filename !== "test.py") {
      throw new Error("New example not found");
    }
  });

  // Test 15: Update file example
  test("Update file example", async () => {
    const updated = await FileExampleManager.updateFileExample(
      "python-data-processor",
      {
        description: "Updated description",
      },
    );

    if (!updated || updated.description !== "Updated description") {
      throw new Error("Update failed");
    }
  });

  // Test 16: Delete file example
  test("Delete file example", async () => {
    // First create one
    const created = await FileExampleManager.createFileExample({
      filename: "delete-test.py",
      content: "test",
      language: "python",
      postSlug: "test",
    });

    // Then delete it
    const deleted = await FileExampleManager.deleteFileExample(created.id);
    if (!deleted) {
      throw new Error("Delete failed");
    }

    // Verify it's gone
    const retrieved = await FileExampleManager.getFileExample(created.id);
    if (retrieved) {
      throw new Error("File still exists after deletion");
    }
  });

  // Wait for all async tests to complete
  await new Promise((resolve) => setTimeout(resolve, 100));

  console.log(`\n📊 Test Results: ${passed} passed, ${failed} failed`);

  if (failed === 0) {
    console.log("🎉 All tests passed!");
  } else {
    console.log("❌ Some tests failed");
    process.exit(1);
  }
}

// Export for use in other test files
