/**
 * ArchitectureDebugPage - Debug page for testing refactored architecture
 * 
 * Tests:
 * A - Level2 recursion: referencedObject with attributes is stored
 * B - Disabled type: NOT full sync, but reference-only caching works
 * C - Attribute wipe rule: shallow referencedObject doesn't delete existing values
 * D - QueryService reconstruction: DB → TS object is correct
 * E - Write-through: update to Jira + immediate DB update
 */

import { useState, useEffect } from 'react';
import { getConfiguredObjectTypes } from '../services/api';
import PageHeader from './PageHeader';

interface TestResult {
  test: string;
  status: 'pending' | 'running' | 'success' | 'error';
  message?: string;
  data?: any;
  sqlQueries?: Array<{ sql: string; result: any }>;
  timestamp?: string;
}

export default function ArchitectureDebugPage() {
  const [testResults, setTestResults] = useState<Record<string, TestResult>>({});
  const [loading, setLoading] = useState<Record<string, boolean>>({});
  const [enabledTypes, setEnabledTypes] = useState<string[]>([]);
  const [loadingEnabledTypes, setLoadingEnabledTypes] = useState(true);
  const [inputs, setInputs] = useState({
    typeName: 'ApplicationComponent',
    objectKey: '',
    referencedObjectKey: '',
    disabledTypeName: 'HostingType',
    updateField: 'description',
    updateValue: 'Updated via Debug Page',
  });

  // Load enabled object types on mount
  useEffect(() => {
    const loadEnabledTypes = async () => {
      try {
        setLoadingEnabledTypes(true);
        const config = await getConfiguredObjectTypes();
        const enabled = config.schemas.flatMap(s => 
          s.objectTypes.filter(ot => ot.enabled).map(ot => ot.objectTypeName)
        );
        setEnabledTypes(enabled);
      } catch (error) {
        console.error('Failed to load enabled types:', error);
      } finally {
        setLoadingEnabledTypes(false);
      }
    };
    loadEnabledTypes();
  }, []);

  const updateTestResult = (testId: string, updates: Partial<TestResult>) => {
    setTestResults(prev => ({
      ...prev,
      [testId]: {
        ...prev[testId],
        ...updates,
        timestamp: new Date().toISOString(),
      } as TestResult,
    }));
  };

  const executeSqlQuery = async (sql: string, params: any[] = []): Promise<any> => {
    try {
      const response = await fetch('/api/v2/debug/query', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        credentials: 'include',
        body: JSON.stringify({ sql, params }),
      });
      if (!response.ok) {
        const errorData = await response.json().catch(() => ({ error: 'Unknown error' }));
        throw new Error(errorData.error || `HTTP ${response.status}`);
      }
      const data = await response.json();
      return data.result || [];
    } catch (error) {
      console.error('SQL query failed:', error);
      throw error;
    }
  };

  // Test A: Level2 recursion
  const runTestA = async () => {
    const testId = 'testA';
    setLoading(prev => ({ ...prev, [testId]: true }));
    updateTestResult(testId, { test: 'Test A: Level2 Recursion', status: 'running' });

    try {
      // Step 1: Sync object type
      updateTestResult(testId, { message: `Syncing object type "${inputs.typeName}"...` });
      const syncResponse = await fetch(`/api/v2/sync/objects/${inputs.typeName}`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'include',
      });
      if (!syncResponse.ok) {
        const errorData = await syncResponse.json().catch(() => ({ error: `HTTP ${syncResponse.status}: Sync failed` }));
        const errorMessage = errorData.error || `HTTP ${syncResponse.status}: Sync failed`;
        
        // Extract enabled types from error details if available
        let enabledTypesHint = '';
        if (errorData.details?.enabledTypeNames && errorData.details.enabledTypeNames.length > 0) {
          enabledTypesHint = ` Currently enabled: ${errorData.details.enabledTypeNames.join(', ')}.`;
        }
        
        // Provide helpful hints for common errors
        let hint = '';
        if (errorMessage.includes('not enabled')) {
          hint = ` Tip: Go to Schema Configuration settings and enable "${inputs.typeName}".${enabledTypesHint}`;
        } else if (errorMessage.includes('token')) {
          hint = ' Tip: Check if JIRA_SERVICE_ACCOUNT_TOKEN is configured in .env or if you have a Personal Access Token configured.';
        } else if (errorMessage.includes('404') || errorMessage.includes('not found')) {
          hint = ' Tip: The object type may not exist in your Jira Assets instance. Check the type name spelling.';
        }
        
        throw new Error(errorMessage + hint);
      }
      const syncResult = await syncResponse.json();
      
      // Check for errors in sync result
      if (syncResult.hasErrors && syncResult.errors && syncResult.errors.length > 0) {
        const errorMessages = syncResult.errors.map((e: any) => `${e.objectId}: ${e.error}`).join('; ');
        console.warn(`Sync completed with errors: ${errorMessages}`);
      }
      // Check if sync had errors (even if not marked as hasErrors)
      if (syncResult.errors && syncResult.errors.length > 0) {
        const errorMessages = syncResult.errors.map((e: any) => e.error || e.message || 'Unknown error').join('; ');
        
        // Check if it's a network/Jira API error
        if (errorMessages.includes('Failed to fetch') || errorMessages.includes('fetch failed') || errorMessages.includes('network')) {
          throw new Error(`Network error while syncing: ${errorMessages}. This usually means: - Jira host URL is incorrect or unreachable - Network connectivity issues - Jira API authentication failed. Check your Jira PAT token in Profile Settings and verify the JIRA_HOST environment variable.`);
        }
        
        throw new Error(`Sync failed: ${errorMessages}. Check backend logs for details.`);
      }
      
      if (syncResult.objectsCached === 0 && syncResult.objectsProcessed === 0) {
        throw new Error('Sync completed but no objects were processed. This could mean:\n- The object type has no objects in Jira Assets\n- The IQL search returned no results\n- Check if the object type name is correct');
      }

      // Step 2: Get a sample object to check
      updateTestResult(testId, { message: 'Fetching sample objects...' });
      const objectsResponse = await fetch(`/api/v2/objects/${inputs.typeName}?limit=10`, {
        credentials: 'include',
      });
      if (!objectsResponse.ok) {
        const errorData = await objectsResponse.json().catch(() => ({ error: `HTTP ${objectsResponse.status}: Failed to fetch objects` }));
        const errorMessage = errorData.error || `HTTP ${objectsResponse.status}: Failed to fetch objects`;
        throw new Error(`${errorMessage}. Sync processed ${syncResult.objectsProcessed || 0} objects. If objects were synced, they may not be queryable yet.`);
      }
      const objectsData = await objectsResponse.json();
      const sampleObject = objectsData.objects?.[0];
      if (!sampleObject) {
        throw new Error(`No objects found after sync. Sync processed ${syncResult.objectsProcessed || 0} objects, cached ${syncResult.objectsCached || 0}. The objects may not be queryable yet or the object type has no objects in Jira Assets.`);
      }

      // Step 3: Find a referenced object from the sample
      updateTestResult(testId, { message: 'Looking for referenced objects in sample...' });
      const referencedObjectKey = inputs.referencedObjectKey || (() => {
        // Try to find a reference in the object
        const references: string[] = [];
        for (const [, value] of Object.entries(sampleObject)) {
          if (value && typeof value === 'object' && ('objectKey' in value || 'key' in value)) {
            const objKey = (value as any).objectKey || (value as any).key;
            if (objKey) references.push(objKey);
          }
          if (Array.isArray(value) && value.length > 0) {
            for (const item of value) {
              if (item && typeof item === 'object' && ('objectKey' in item || 'key' in item)) {
                const objKey = item.objectKey || item.key;
                if (objKey) references.push(objKey);
              }
            }
          }
        }
        return references.length > 0 ? references[0] : null;
      })();

      if (!referencedObjectKey) {
        const sampleObjectKeys = Object.keys(sampleObject).join(', ');
        throw new Error(`No referenced object found in sample object. Object fields: ${sampleObjectKeys}. Please provide a referencedObjectKey manually if the object has references.`);
      }
      
      updateTestResult(testId, { message: `Found referenced object: ${referencedObjectKey}` });

      // Step 4: Run SQL checks
      updateTestResult(testId, { message: 'Running database checks...' });
      
      const sqlQueries: Array<{ sql: string; result: any }> = [];

      // Check 1: Both objects exist
      const sampleObjectKey = sampleObject.objectKey || sampleObject.key || sampleObject.id;
      if (!sampleObjectKey) {
        throw new Error(`Sample object has no objectKey. Object structure: ${JSON.stringify(sampleObject)}`);
      }
      
      const check1Sql = `SELECT id, object_key, object_type_name, label FROM objects WHERE object_key IN (?, ?)`;
      const check1Result = await executeSqlQuery(check1Sql, [sampleObjectKey, referencedObjectKey]);
      sqlQueries.push({ sql: check1Sql, result: check1Result });

      // Check 2: Referenced object has attribute values
      // Handle both snake_case and camelCase column names
      const refObj = check1Result.find((o: any) => 
        (o.object_key || o.objectKey) === referencedObjectKey
      );
      
      if (!refObj) {
        const foundKeys = check1Result.map((o: any) => (o.object_key || o.objectKey)).filter(Boolean);
        throw new Error(`Referenced object "${referencedObjectKey}" not found in database. Found objects: ${foundKeys.join(', ') || 'none'}. The referenced object may not have been cached during sync.`);
      }
      
      const check2Sql = `SELECT COUNT(*) as count FROM attribute_values WHERE object_id = ?`;
      const check2Result = await executeSqlQuery(check2Sql, [refObj.id]);
      sqlQueries.push({ sql: check2Sql, result: check2Result });
      
      const attrCount = check2Result[0]?.count || (check2Result[0]?.count === 0 ? 0 : null);
      
      // Check 3: Get sample attribute values to verify they exist
      const check3Sql = `SELECT av.*, a.field_name, a.attr_type 
                         FROM attribute_values av 
                         JOIN attributes a ON a.id = av.attribute_id 
                         WHERE av.object_id = ? 
                         LIMIT 5`;
      const check3Result = await executeSqlQuery(check3Sql, [refObj.id]);
      sqlQueries.push({ sql: check3Sql, result: check3Result });

      updateTestResult(testId, {
        status: 'success',
        message: `✅ Sync completed successfully. Found ${syncResult.objectsCached || 0} objects. Referenced object "${referencedObjectKey}" exists with ${attrCount || 0} attribute values.`,
        data: {
          syncResult: {
            objectsProcessed: syncResult.objectsProcessed,
            objectsCached: syncResult.objectsCached,
            relationsExtracted: syncResult.relationsExtracted,
          },
          sampleObject: { objectKey: sampleObjectKey, label: sampleObject.label || sampleObject.name },
          referencedObject: {
            objectKey: referencedObjectKey,
            id: refObj.id,
            typeName: refObj.object_type_name || refObj.objectTypeName,
            label: refObj.label,
            attributeValueCount: attrCount,
          },
        },
        sqlQueries,
      });
    } catch (error) {
      updateTestResult(testId, {
        status: 'error',
        message: error instanceof Error ? error.message : 'Test failed',
      });
    } finally {
      setLoading(prev => ({ ...prev, [testId]: false }));
    }
  };

  // Test B: Disabled type reference-only caching
  const runTestB = async () => {
    const testId = 'testB';
    setLoading(prev => ({ ...prev, [testId]: true }));
    updateTestResult(testId, { test: 'Test B: Disabled Type Reference-Only', status: 'running' });

    try {
      const disabledType = inputs.disabledTypeName;

      // Step 1: Check initial count
      updateTestResult(testId, { message: 'Checking initial object count...' });
      const initialCountResult = await executeSqlQuery(
        `SELECT COUNT(*) as count FROM objects WHERE object_type_name = ?`,
        [disabledType]
      );
      const initialCount = initialCountResult[0]?.count || 0;

      // Step 2: Sync an enabled type that references the disabled type
      updateTestResult(testId, { message: `Syncing ${inputs.typeName} (should cache ${disabledType} references)...` });
      const syncResponse = await fetch(`/api/v2/sync/objects/${inputs.typeName}`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'include',
      });
      if (!syncResponse.ok) throw new Error('Sync failed');
      await syncResponse.json();

      // Step 3: Check final count (should not have increased much)
      updateTestResult(testId, { message: 'Checking final object count...' });
      const finalCountResult = await executeSqlQuery(
        `SELECT COUNT(*) as count FROM objects WHERE object_type_name = ?`,
        [disabledType]
      );
      const finalCount = finalCountResult[0]?.count || 0;

      // Step 4: Check relations
      const relationsResult = await executeSqlQuery(
        `SELECT COUNT(*) as count 
         FROM object_relations r
         JOIN objects t ON t.id = r.target_id
         WHERE t.object_type_name = ?`,
        [disabledType]
      );
      const relationCount = relationsResult[0]?.count || 0;

      const sqlQueries = [
        { sql: 'Initial count query', result: initialCountResult },
        { sql: 'Final count query', result: finalCountResult },
        { sql: 'Relations query', result: relationsResult },
      ];

      updateTestResult(testId, {
        status: 'success',
        message: `Disabled type ${disabledType}: ${initialCount} → ${finalCount} objects. ${relationCount} relations found.`,
        data: {
          initialCount,
          finalCount,
          relationCount,
          delta: finalCount - initialCount,
        },
        sqlQueries,
      });
    } catch (error) {
      updateTestResult(testId, {
        status: 'error',
        message: error instanceof Error ? error.message : 'Test failed',
      });
    } finally {
      setLoading(prev => ({ ...prev, [testId]: false }));
    }
  };

  // Test C: Attribute wipe rule
  const runTestC = async () => {
    const testId = 'testC';
    setLoading(prev => ({ ...prev, [testId]: true }));
    updateTestResult(testId, { test: 'Test C: Attribute Wipe Rule', status: 'running' });

    try {
      if (!inputs.referencedObjectKey) {
        throw new Error('Please provide a referencedObjectKey to test');
      }

      // Step 1: Get initial attribute count
      updateTestResult(testId, { message: 'Checking initial attribute values...' });
      const objInfoResponse = await fetch(`/api/v2/debug/objects?objectKey=${inputs.referencedObjectKey}`, {
        credentials: 'include',
      });
      if (!objInfoResponse.ok) throw new Error('Failed to get object info');
      const objInfo = await objInfoResponse.json();
      const initialAttrCount = objInfo.attributeValueCount || 0;

      if (initialAttrCount === 0) {
        throw new Error('Object has no attributes - sync it first with level2 expansion');
      }

      // Step 2: Sync a parent object that references this one (should come as shallow)
      updateTestResult(testId, { message: 'Syncing parent object (referenced object may come as shallow)...' });
      const syncResponse = await fetch(`/api/v2/sync/objects/${inputs.typeName}`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'include',
      });
      if (!syncResponse.ok) throw new Error('Sync failed');

      // Step 3: Check final attribute count (should be same or greater)
      updateTestResult(testId, { message: 'Checking final attribute values...' });
      const finalObjInfoResponse = await fetch(`/api/v2/debug/objects?objectKey=${inputs.referencedObjectKey}`, {
        credentials: 'include',
      });
      if (!finalObjInfoResponse.ok) throw new Error('Failed to get final object info');
      const finalObjInfo = await finalObjInfoResponse.json();
      const finalAttrCount = finalObjInfo.attributeValueCount || 0;

      const sqlQueries = [
        { sql: 'Initial attribute count', result: [{ count: initialAttrCount }] },
        { sql: 'Final attribute count', result: [{ count: finalAttrCount }] },
      ];

      const success = finalAttrCount >= initialAttrCount;
      
      updateTestResult(testId, {
        status: success ? 'success' : 'error',
        message: success 
          ? `✅ Attributes preserved: ${initialAttrCount} → ${finalAttrCount}`
          : `❌ Attributes were wiped: ${initialAttrCount} → ${finalAttrCount}`,
        data: {
          initialAttrCount,
          finalAttrCount,
          preserved: success,
        },
        sqlQueries,
      });
    } catch (error) {
      updateTestResult(testId, {
        status: 'error',
        message: error instanceof Error ? error.message : 'Test failed',
      });
    } finally {
      setLoading(prev => ({ ...prev, [testId]: false }));
    }
  };

  // Test D: QueryService reconstruction
  const runTestD = async () => {
    const testId = 'testD';
    setLoading(prev => ({ ...prev, [testId]: true }));
    updateTestResult(testId, { test: 'Test D: QueryService Reconstruction', status: 'running' });

    try {
      if (!inputs.objectKey) {
        throw new Error('Please provide an objectKey to test');
      }

      // Step 1: Get object from DB via QueryService
      updateTestResult(testId, { message: 'Fetching object via QueryService...' });
      const objectResponse = await fetch(`/api/v2/objects/${inputs.typeName}/${inputs.objectKey}`, {
        credentials: 'include',
      });
      if (!objectResponse.ok) throw new Error('Failed to fetch object');
      const object = await objectResponse.json();

      // Step 2: Get raw DB data for comparison
      updateTestResult(testId, { message: 'Fetching raw DB data...' });
      const objInfoResponse = await fetch(`/api/v2/debug/objects?objectKey=${inputs.objectKey}`, {
        credentials: 'include',
      });
      if (!objInfoResponse.ok) throw new Error('Failed to get object info');
      const objInfo = await objInfoResponse.json();

      // Step 3: Get attribute values from DB
      const attrValuesResult = await executeSqlQuery(
        `SELECT av.*, a.field_name, a.attr_type, a.is_multiple
         FROM attribute_values av
         JOIN attributes a ON a.id = av.attribute_id
         WHERE av.object_id = ?
         ORDER BY a.field_name, av.array_index`,
        [objInfo.object.id]
      );

      // Step 4: Verify reconstruction
      const fieldCount = new Set(attrValuesResult.map((av: any) => av.field_name)).size;
      const objectFieldCount = Object.keys(object).filter(k => !k.startsWith('_') && k !== 'id' && k !== 'objectKey' && k !== 'label').length;

      const sqlQueries = [
        { sql: 'Attribute values query', result: attrValuesResult },
      ];

      updateTestResult(testId, {
        status: 'success',
        message: `Object reconstructed: ${fieldCount} fields from DB, ${objectFieldCount} fields in object`,
        data: {
          object,
          dbFields: fieldCount,
          objectFields: objectFieldCount,
          attributeValues: attrValuesResult.length,
        },
        sqlQueries,
      });
    } catch (error) {
      updateTestResult(testId, {
        status: 'error',
        message: error instanceof Error ? error.message : 'Test failed',
      });
    } finally {
      setLoading(prev => ({ ...prev, [testId]: false }));
    }
  };

  // Test E: Write-through
  const runTestE = async () => {
    const testId = 'testE';
    setLoading(prev => ({ ...prev, [testId]: true }));
    updateTestResult(testId, { test: 'Test E: Write-Through Update', status: 'running' });

    try {
      if (!inputs.objectKey) {
        throw new Error('Please provide an objectKey to test');
      }

      // Step 1: Get initial object state
      updateTestResult(testId, { message: 'Fetching initial object state...' });
      const initialResponse = await fetch(`/api/v2/objects/${inputs.typeName}/${inputs.objectKey}`, {
        credentials: 'include',
      });
      if (!initialResponse.ok) throw new Error('Failed to fetch initial object');
      const initialObject = await initialResponse.json();

      // Step 2: Update via write-through
      updateTestResult(testId, { message: 'Updating object via write-through...' });
      const updatePayload: Record<string, any> = {};
      updatePayload[inputs.updateField] = inputs.updateValue;
      
      const updateResponse = await fetch(`/api/v2/objects/${inputs.typeName}/${inputs.objectKey}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'include',
        body: JSON.stringify(updatePayload),
      });
      if (!updateResponse.ok) {
        const error = await updateResponse.json();
        throw new Error(error.error || 'Update failed');
      }
      await updateResponse.json();

      // Step 3: Immediately check DB (without refresh)
      updateTestResult(testId, { message: 'Checking DB state immediately...' });
      const dbCheckResponse = await fetch(`/api/v2/objects/${inputs.typeName}/${inputs.objectKey}`, {
        credentials: 'include',
      });
      if (!dbCheckResponse.ok) throw new Error('Failed to fetch updated object');
      const dbObject = await dbCheckResponse.json();

      // Step 4: Check attribute value in DB
      const attrCheckResult = await executeSqlQuery(
        `SELECT av.*, a.field_name
         FROM attribute_values av
         JOIN attributes a ON a.id = av.attribute_id
         JOIN objects o ON o.id = av.object_id
         WHERE o.object_key = ? AND a.field_name = ?`,
        [inputs.objectKey, inputs.updateField]
      );

      const sqlQueries = [
        { sql: 'Attribute value check', result: attrCheckResult },
      ];

      const dbValue = dbObject[inputs.updateField];
      const updated = dbValue === inputs.updateValue || (typeof dbValue === 'object' && dbValue?.label === inputs.updateValue);

      updateTestResult(testId, {
        status: updated ? 'success' : 'error',
        message: updated
          ? `✅ Write-through successful: DB updated immediately`
          : `❌ Write-through failed: DB value doesn't match`,
        data: {
          initialValue: initialObject[inputs.updateField],
          expectedValue: inputs.updateValue,
          dbValue,
          updated,
        },
        sqlQueries,
      });
    } catch (error) {
      updateTestResult(testId, {
        status: 'error',
        message: error instanceof Error ? error.message : 'Test failed',
      });
    } finally {
      setLoading(prev => ({ ...prev, [testId]: false }));
    }
  };

  return (
    <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
      <PageHeader
        title="Architecture Debug & Test Page"
        description="Test the refactored V2 API architecture. All tests require admin permissions."
        icon={
          <svg className="w-8 h-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
          </svg>
        }
      />

      {/* Input Form */}
      <div className="bg-white shadow rounded-lg p-6 mb-8">
        <h2 className="text-xl font-semibold mb-4">Test Parameters</h2>
        <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-1">
              Object Type Name
            </label>
            <div className="flex gap-2">
              <input
                type="text"
                value={inputs.typeName}
                onChange={(e) => setInputs({ ...inputs, typeName: e.target.value })}
                className="flex-1 border border-gray-300 rounded-md px-3 py-2"
                placeholder="ApplicationComponent"
                list="enabled-types-list"
              />
              <datalist id="enabled-types-list">
                {enabledTypes.map(type => (
                  <option key={type} value={type} />
                ))}
              </datalist>
            </div>
            {!loadingEnabledTypes && enabledTypes.length > 0 && (
              <p className="mt-1 text-xs text-gray-500">
                Enabled types: {enabledTypes.join(', ')}
                {!enabledTypes.includes(inputs.typeName) && inputs.typeName && (
                  <span className="ml-2 text-orange-600">
                    ⚠ "{inputs.typeName}" is not enabled
                  </span>
                )}
              </p>
            )}
            {!loadingEnabledTypes && enabledTypes.length === 0 && (
              <p className="mt-1 text-xs text-orange-600">
                ⚠ No object types are currently enabled. Please enable at least one in Schema Configuration.
              </p>
            )}
          </div>
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-1">
              Object Key (for Tests C, D, E)
            </label>
            <input
              type="text"
              value={inputs.objectKey}
              onChange={(e) => setInputs({ ...inputs, objectKey: e.target.value })}
              className="w-full border border-gray-300 rounded-md px-3 py-2"
              placeholder="APP-123"
            />
          </div>
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-1">
              Referenced Object Key (for Tests A, C)
            </label>
            <input
              type="text"
              value={inputs.referencedObjectKey}
              onChange={(e) => setInputs({ ...inputs, referencedObjectKey: e.target.value })}
              className="w-full border border-gray-300 rounded-md px-3 py-2"
              placeholder="HOST-123"
            />
          </div>
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-1">
              Disabled Type Name (for Test B)
            </label>
            <input
              type="text"
              value={inputs.disabledTypeName}
              onChange={(e) => setInputs({ ...inputs, disabledTypeName: e.target.value })}
              className="w-full border border-gray-300 rounded-md px-3 py-2"
              placeholder="HostingType"
            />
          </div>
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-1">
              Update Field (for Test E)
            </label>
            <input
              type="text"
              value={inputs.updateField}
              onChange={(e) => setInputs({ ...inputs, updateField: e.target.value })}
              className="w-full border border-gray-300 rounded-md px-3 py-2"
              placeholder="description"
            />
          </div>
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-1">
              Update Value (for Test E)
            </label>
            <input
              type="text"
              value={inputs.updateValue}
              onChange={(e) => setInputs({ ...inputs, updateValue: e.target.value })}
              className="w-full border border-gray-300 rounded-md px-3 py-2"
              placeholder="Updated value"
            />
          </div>
        </div>
      </div>

      {/* Utility Actions */}
      <div className="bg-yellow-50 border border-yellow-200 rounded-lg p-4 mb-8">
        <h2 className="text-lg font-semibold mb-2 text-yellow-900">Utility Actions</h2>
        <div className="flex gap-2">
          <button
            onClick={async () => {
              try {
                const response = await fetch('/api/v2/debug/fix-missing-type-names', {
                  method: 'POST',
                  headers: { 'Content-Type': 'application/json' },
                  credentials: 'include',
                });
                const result = await response.json();
                if (result.success) {
                  alert(`Fixed ${result.fixed} object types with missing type_name. Errors: ${result.errors || 0}`);
                  // Reload enabled types
                  const config = await getConfiguredObjectTypes();
                  const enabled = config.schemas.flatMap(s => 
                    s.objectTypes.filter(ot => ot.enabled).map(ot => ot.objectTypeName)
                  );
                  setEnabledTypes(enabled);
                } else {
                  alert(`Error: ${result.error || 'Failed to fix'}`);
                }
              } catch (error) {
                alert(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
              }
            }}
            className="bg-yellow-600 text-white px-4 py-2 rounded-md hover:bg-yellow-700"
          >
            Fix Missing type_name
          </button>
          <button
            onClick={async () => {
              const testId = 'debug-all-types';
              setLoading(prev => ({ ...prev, [testId]: true }));
              updateTestResult(testId, { test: 'Debug: All Object Types', status: 'running', message: 'Fetching all object types...' });
              
              try {
                const response = await fetch('/api/v2/debug/all-object-types', {
                  credentials: 'include',
                });
                
                if (!response.ok) {
                  // Check if it's a 404 - likely means V2 API is not enabled
                  if (response.status === 404) {
                    throw new Error('V2 API routes are not enabled. Please set USE_V2_API=true in backend environment variables and restart the server.');
                  }
                  
                  const errorData = await response.json().catch(() => ({ error: `HTTP ${response.status}: Failed to fetch` }));
                  const errorMessage = errorData.error || errorData.details || `HTTP ${response.status}: Failed to fetch`;
                  
                  // Provide more context for common errors
                  if (response.status === 403) {
                    throw new Error(`${errorMessage} (Admin permission required)`);
                  }
                  
                  throw new Error(errorMessage);
                }
                
                const result = await response.json();
                
                // Format the data for display
                const enabledWithNullTypeName = result.allTypes.filter((t: any) => t.enabled && !t.hasTypeName);
                const enabledWithTypeName = result.allTypes.filter((t: any) => t.enabled && t.hasTypeName);
                
                updateTestResult(testId, {
                  test: 'Debug: All Object Types',
                  status: 'success',
                  message: `Found ${result.summary.total} total types. ${result.summary.enabled} enabled in DB (${result.summary.enabledWithTypeName} with type_name, ${enabledWithNullTypeName.length} missing type_name). ${result.summary.missingTypeName} total missing type_name.`,
                  data: {
                    summary: result.summary,
                    enabledWithNullTypeName: enabledWithNullTypeName.map((t: any) => ({
                      id: t.id,
                      displayName: t.displayName,
                      enabled: t.enabled,
                    })),
                    enabledWithTypeName: enabledWithTypeName.map((t: any) => ({
                      id: t.id,
                      typeName: t.typeName,
                      displayName: t.displayName,
                    })),
                    allTypes: result.allTypes,
                    enabledTypesFromService: result.enabledTypes,
                  },
                });
              } catch (error) {
                updateTestResult(testId, {
                  test: 'Debug: All Object Types',
                  status: 'error',
                  message: error instanceof Error ? error.message : 'Failed to fetch',
                });
              } finally {
                setLoading(prev => ({ ...prev, [testId]: false }));
              }
            }}
            disabled={loading.debugAllTypes}
            className="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 disabled:bg-gray-400"
          >
            {loading.debugAllTypes ? 'Loading...' : 'Show All Object Types (Debug)'}
          </button>
        </div>
      </div>

      {/* Test Buttons */}
      <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mb-8">
        <button
          onClick={runTestA}
          disabled={loading.testA}
          className="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 disabled:bg-gray-400"
        >
          {loading.testA ? 'Running...' : 'Test A: Level2 Recursion'}
        </button>
        <button
          onClick={runTestB}
          disabled={loading.testB}
          className="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 disabled:bg-gray-400"
        >
          {loading.testB ? 'Running...' : 'Test B: Disabled Type'}
        </button>
        <button
          onClick={runTestC}
          disabled={loading.testC}
          className="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 disabled:bg-gray-400"
        >
          {loading.testC ? 'Running...' : 'Test C: Attribute Wipe Rule'}
        </button>
        <button
          onClick={runTestD}
          disabled={loading.testD}
          className="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 disabled:bg-gray-400"
        >
          {loading.testD ? 'Running...' : 'Test D: QueryService Reconstruction'}
        </button>
        <button
          onClick={runTestE}
          disabled={loading.testE}
          className="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 disabled:bg-gray-400"
        >
          {loading.testE ? 'Running...' : 'Test E: Write-Through'}
        </button>
      </div>

      {/* Test Results */}
      <div className="space-y-6">
        {Object.entries(testResults).map(([testId, result]) => (
          <div key={testId} className="bg-white shadow rounded-lg p-6">
            <div className="flex items-center justify-between mb-4">
              <h3 className="text-lg font-semibold">{result.test}</h3>
              <span className={`px-3 py-1 rounded-full text-sm ${
                result.status === 'success' ? 'bg-green-100 text-green-800' :
                result.status === 'error' ? 'bg-red-100 text-red-800' :
                result.status === 'running' ? 'bg-yellow-100 text-yellow-800' :
                'bg-gray-100 text-gray-800'
              }`}>
                {result.status}
              </span>
            </div>
            
            {result.message && (
              <p className="text-gray-700 mb-4">{result.message}</p>
            )}

            {result.data && (
              <div className="mb-4">
                <h4 className="font-medium mb-2">Data:</h4>
                <pre className="bg-gray-50 p-4 rounded-md overflow-auto text-sm">
                  {JSON.stringify(result.data, null, 2)}
                </pre>
              </div>
            )}

            {result.sqlQueries && result.sqlQueries.length > 0 && (
              <div className="mb-4">
                <h4 className="font-medium mb-2">SQL Queries & Results:</h4>
                {result.sqlQueries.map((query, idx) => (
                  <div key={idx} className="mb-4 border-l-4 border-blue-500 pl-4">
                    <div className="font-mono text-sm bg-gray-50 p-2 rounded mb-2">
                      {query.sql}
                    </div>
                    <pre className="bg-gray-50 p-4 rounded-md overflow-auto text-xs max-h-64">
                      {JSON.stringify(query.result, null, 2)}
                    </pre>
                  </div>
                ))}
              </div>
            )}

            {result.timestamp && (
              <p className="text-xs text-gray-500">Ran at: {new Date(result.timestamp).toLocaleString()}</p>
            )}
          </div>
        ))}
      </div>

      {Object.keys(testResults).length === 0 && (
        <div className="bg-gray-50 rounded-lg p-8 text-center text-gray-500">
          No tests run yet. Use the buttons above to start testing.
        </div>
      )}
    </div>
  );
}
