import React, { useState, useEffect, useRef } from 'react';

function FieldsSelector({ selectedEntity, selectedBundle, selectedFields, onFieldsChange, relatedEntityFields = {}, loadingRelatedFields = false, baseUrl }) {
  const [availableFields, setAvailableFields] = useState([]);
  const [fieldMetadata, setFieldMetadata] = useState({});
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);
  const [searchQuery, setSearchQuery] = useState('');

  // Local loading state that will be cleared more aggressively
  const [localLoadingState, setLocalLoadingState] = useState(false);

  // For JS-based tooltips
  const tooltipRef = useRef(null);

  // Process all fields - direct and from related entities
  useEffect(() => {
    if (selectedEntity && selectedBundle) {
      fetchFields();
    } else {
      setAvailableFields([]);
      setFieldMetadata({});
    }
  }, [selectedEntity, selectedBundle]);

  // Enhanced loading state management with longer persistence
  useEffect(() => {
    // When loadingRelatedFields becomes true, update local state immediately
    if (loadingRelatedFields) {
      setLocalLoadingState(true);
    }
    // When loadingRelatedFields becomes false, clear local state after a longer delay
    // to ensure fields have time to render
    else if (localLoadingState) {
      const timer = setTimeout(() => {
        // Check if we have any relationship fields before clearing the loading state
        const hasRelatedFields = Object.keys(relatedEntityFields).length > 0;

        if (hasRelatedFields) {
          setLocalLoadingState(false);
        } else {
          // If we still don't have relationship fields, wait a bit longer
          const extendedTimer = setTimeout(() => {
            setLocalLoadingState(false);
          }, 500);

          return () => clearTimeout(extendedTimer);
        }
      }, 500); // Use a longer delay to account for async loading

      return () => clearTimeout(timer);
    }
  }, [loadingRelatedFields, localLoadingState, relatedEntityFields]);

  // Reset loading state when entity or bundle changes
  useEffect(() => {
    setLocalLoadingState(false);
    // Reset loading state when entity/bundle changes
  }, [selectedEntity, selectedBundle]);

  // Process related entity fields when they change - improved version
  useEffect(() => {
    // Process related entity fields when they change

    // Define a function to process the fields to better handle the async nature
    const processRelatedFields = () => {
      // Prevent excessive logging
      if (Object.keys(relatedEntityFields).length > 0) {
        // Track if we're adding any new fields
        let addedNewFields = false;
        let newFieldCount = 0;
        // Get a copy of the current metadata
        const updatedMetadata = { ...fieldMetadata };
        const updatedFields = [...availableFields];

        // Process each relationship's fields
        Object.entries(relatedEntityFields).forEach(([relationship, fields]) => {

          fields.forEach(field => {
            const { name, fieldDef } = field;

            // Add field to metadata if not already there
            if (!updatedMetadata[name]) {
              addedNewFields = true;
              newFieldCount++;
              updatedMetadata[name] = {
                name: name,
                // Use title directly from schema and add relationship context
                title: fieldDef.title ? `${fieldDef.title} (${relationship})` : name,
                type: fieldDef.type || 'unknown',
                description: fieldDef.description || '',
                format: fieldDef.format || '',
                required: fieldDef.required === true,
                pattern: fieldDef.pattern || '',
                readOnly: fieldDef.readOnly === true,
                writeOnly: fieldDef.writeOnly === true,
                enum: fieldDef.enum || (fieldDef.oneOf ? fieldDef.oneOf.map(item => item.const) : null),
                enumTitles: fieldDef.oneOf ? fieldDef.oneOf.map(item => item.title) : null,
                maxLength: fieldDef.maxLength || null,
                default: fieldDef.default !== undefined ? fieldDef.default : null,
                // Flag as a relationship field for styling
                isRelatedField: true,
                relationshipName: relationship
              };
            }

            // Add to available fields if not already there
            if (!updatedFields.includes(name)) {
              addedNewFields = true;
              updatedFields.push(name);
            }
          });
        });

        // Only update state if we actually added new fields
        // This prevents infinite re-rendering
        if (addedNewFields) {

          // Force an update to the state, even if the fields might be the same
          // Using a callback to ensure we get the latest state
          setFieldMetadata(current => ({...updatedMetadata}));
          setAvailableFields(current => [...updatedFields]);

          // Fields updated, clear loading state
          setLocalLoadingState(false);
        } else {
          // No new fields to add
        }
      } else {
        // No related entity fields to process
      }
    };

    // Process fields immediately
    processRelatedFields();

    // Then process again after a delay to catch any async updates
    const timer = setTimeout(() => {
      // Process fields again after delay
      processRelatedFields();
    }, 500);

    return () => clearTimeout(timer);

  // Only depend on relatedEntityFields to avoid infinite loops
  }, [relatedEntityFields, fieldMetadata, availableFields]);

  // Add an effect specifically to handle loading state changes
  useEffect(() => {
    // Track loading state changes
  }, [loadingRelatedFields]);

  const fetchFields = async () => {
    if (!selectedEntity || !selectedBundle) return;

    setLoading(true);
    setError(null);

    try {
      // Use the baseUrl prop passed from the parent component
      const jsonApiBase = baseUrl;


      const schemaUrl = `${jsonApiBase}/${selectedEntity}/${selectedBundle}/resource/schema`;

      const response = await fetch(schemaUrl, {
        headers: { 'Accept': 'application/vnd.api+json' }
      });

      if (response.ok) {
        const data = await response.json();

        // Extract fields from the schema
        let fieldNames = [];
        // Object to store detailed metadata for each field
        let metadata = {};

        // Function to extract metadata directly from field definition in schema
        const extractFieldMetadata = (fieldName, fieldDef) => {
          if (!metadata[fieldName]) {
            // Extract all available properties from the schema definition
            metadata[fieldName] = {
              name: fieldName,
              // Use title directly from schema
              title: fieldDef.title || null,
              type: fieldDef.type || 'unknown',
              description: fieldDef.description || '',
              format: fieldDef.format || '',
              required: fieldDef.required === true,
              pattern: fieldDef.pattern || '',
              readOnly: fieldDef.readOnly === true,
              writeOnly: fieldDef.writeOnly === true,
              example: fieldDef.example || '',
              enum: fieldDef.enum || (fieldDef.oneOf ? fieldDef.oneOf.map(item => item.const) : null),
              enumTitles: fieldDef.oneOf ? fieldDef.oneOf.map(item => item.title) : null,
              maxLength: fieldDef.maxLength || null,
              default: fieldDef.default !== undefined ? fieldDef.default : null,
              // Add any other schema properties we find useful
            };
          }
        };

        // Direct access to attributes in the definitions
        if (data && data.definitions && data.definitions.attributes && data.definitions.attributes.properties) {
          console.log('Found attributes directly in definitions.attributes.properties');
          Object.entries(data.definitions.attributes.properties).forEach(([field, def]) => {
            fieldNames.push(field);
            extractFieldMetadata(field, def);
          });
        }

        // If no fields found yet, try more approaches
        if (fieldNames.length === 0) {
          // Try all possible paths for attributes
          if (data && data.definitions) {
            console.log('Searching definitions for attributes');

            // Find any property named "attributes" with a "properties" child in definitions
            Object.keys(data.definitions).forEach(defKey => {
              const def = data.definitions[defKey];

              // Check if this is an attributes definition with properties
              if (defKey === 'attributes' && def.properties) {
                console.log('Found attributes definition with properties');
                Object.entries(def.properties).forEach(([field, fieldDef]) => {
                  if (!fieldNames.includes(field)) {
                    fieldNames.push(field);
                    extractFieldMetadata(field, fieldDef);
                  }
                });
              }

              // Check for nested attributes in properties
              if (def.properties && def.properties.attributes && def.properties.attributes.properties) {
                console.log(`Found attributes in ${defKey}.properties.attributes.properties`);
                Object.entries(def.properties.attributes.properties).forEach(([field, fieldDef]) => {
                  if (!fieldNames.includes(field)) {
                    fieldNames.push(field);
                    extractFieldMetadata(field, fieldDef);
                  }
                });
              }

              // Direct attributes with properties
              if (def.attributes && def.attributes.properties) {
                console.log(`Found attributes in ${defKey}.attributes.properties`);
                Object.entries(def.attributes.properties).forEach(([field, fieldDef]) => {
                  if (!fieldNames.includes(field)) {
                    fieldNames.push(field);
                    extractFieldMetadata(field, fieldDef);
                  }
                });
              }
            });
          }
        }

        // Still no fields? Check if there's a properties.attributes path
        if (fieldNames.length === 0 && data.properties && data.properties.attributes &&
            data.properties.attributes.properties) {
          console.log('Found attributes in root properties.attributes.properties');
          Object.entries(data.properties.attributes.properties).forEach(([field, fieldDef]) => {
            if (!fieldNames.includes(field)) {
              fieldNames.push(field);
              extractFieldMetadata(field, fieldDef);
            }
          });
        }

        // Last resort - deep scan the schema
        if (fieldNames.length === 0) {
          console.log('Deep scanning schema for attribute properties');
          const findAttributeProperties = (obj, currentPath = '') => {
            if (!obj || typeof obj !== 'object') return;

            // Check if this is an attributes object with properties
            if (currentPath.includes('attributes') && obj.properties) {
              console.log(`Found potential attributes at: ${currentPath}`, obj.properties);
              Object.entries(obj.properties).forEach(([field, fieldDef]) => {
                if (!fieldNames.includes(field)) {
                  fieldNames.push(field);
                  extractFieldMetadata(field, fieldDef);
                }
              });
            }

            // Continue traversing
            Object.keys(obj).forEach(key => {
              const newPath = currentPath ? `${currentPath}.${key}` : key;
              if (obj[key] && typeof obj[key] === 'object') {
                findAttributeProperties(obj[key], newPath);
              }
            });
          };

          findAttributeProperties(data);
        }

        // Add basic fields if we've found some attributes but want to ensure common fields are present
        if (fieldNames.length > 0) {
          const basicFields = ['id', 'uuid'];
          basicFields.forEach(field => {
            if (!fieldNames.includes(field)) {
              fieldNames.push(field);
              // Minimal metadata for basic fields if not found in schema
              metadata[field] = {
                name: field,
                type: 'string'
              };
            }
          });
        }

        if (fieldNames.length > 0) {
          console.log('Final field names extracted:', fieldNames);
          console.log('Field metadata extracted:', metadata);
          setAvailableFields(fieldNames);
          setFieldMetadata(metadata);
        } else {
          console.warn('Could not extract fields from schema, falling back to basic fields');
          const fallbackFields = ['id', 'uuid', 'title', 'name', 'created', 'changed'];
          setAvailableFields(fallbackFields);

          // Create minimal fallback metadata
          const fallbackMetadata = {};
          fallbackFields.forEach(field => {
            fallbackMetadata[field] = {
              name: field,
              // Minimal fields for fallback
              type: field === 'created' || field === 'changed' ? 'datetime' : 'string'
            };
          });
          setFieldMetadata(fallbackMetadata);
        }
      } else {
          setError(`Schema endpoint failed with status: ${response.status}`);
      }
    } catch (err) {
      // Handle error
      setError(`Unable to get fields: ${err.message}`);
    } finally {
      setLoading(false);
    }
  };

  // Fallback fields for when API requests fail
  const getCommonFields = (entityType, bundle) => {
    // Only use essential core fields that are nearly universal
    const baseFields = ['id', 'uuid', 'created', 'changed', 'status'];

    // Add some commonly used entity type specific core fields
    let typeFields = [];

    // Only include known core fields, not custom fields
    if (entityType === 'node') {
      typeFields = ['title', 'uid', 'promote', 'sticky'];
    } else if (entityType === 'user') {
      typeFields = ['name', 'mail', 'roles'];
    } else if (entityType === 'taxonomy_term') {
      typeFields = ['name', 'description', 'weight', 'parent', 'vid'];
    } else if (entityType === 'file') {
      typeFields = ['filename', 'uri', 'filemime', 'filesize'];
    } else if (entityType === 'media') {
      typeFields = ['name', 'thumbnail', 'uid'];
    } else if (entityType === 'comment') {
      typeFields = ['subject', 'entity_id', 'pid', 'uid'];
    }

    // Combine and deduplicate fields
    return [...new Set([...baseFields, ...typeFields])];
  };

  const handleFieldToggle = (field) => {
    if (selectedFields.includes(field)) {
      // If removing a field, check if it's a relationship field
      if (field.includes('.')) {
        // Don't automatically remove the parent relationship field when removing a specific relationship field
        onFieldsChange(selectedFields.filter(f => f !== field));
      } else {
        // Check if this is a base relationship field (like "uid")
        const isBaseRelationship = Object.keys(relatedEntityFields).some(rel => rel === field);

        if (isBaseRelationship) {
          // If removing a relationship parent field (like "uid"), also remove all its child fields
          // This is the inverse of what we do when adding a relationship field
          const fieldsToKeep = selectedFields.filter(f =>
            f !== field && !f.startsWith(`${field}.`)
          );
          onFieldsChange(fieldsToKeep);

          // Base relationship field and all its child fields removed
        } else {
          // Just a regular field, just remove it
          onFieldsChange(selectedFields.filter(f => f !== field));
        }
      }
    } else {
      // If adding a field
      if (field.includes('.')) {
        // It's a relationship field (like "uid.display_name")
        const [relationshipName, fieldName] = field.split('.');

        // If the main relationship field isn't already selected, add it too
        if (!selectedFields.includes(relationshipName)) {
          // Auto-select parent relationship field
          onFieldsChange([...selectedFields, relationshipName, field]);
        } else {
          // Just add the relationship field if the parent is already selected
          onFieldsChange([...selectedFields, field]);
        }
      } else {
        // Check if this is a base relationship field being added directly
        const isBaseRelationship = Object.keys(relatedEntityFields).some(rel => rel === field);

        // Check if this is a base relationship field

        // Regular field, just add it
        onFieldsChange([...selectedFields, field]);
      }
    }
  };

  const handleSelectAll = () => {
    onFieldsChange([...availableFields]);
  };

  const handleClearAll = () => {
    onFieldsChange([]);
  };

  // Add JS-based tooltip handling
  useEffect(() => {
    // Function to create and position a tooltip
    const createTooltip = (event) => {
      // Remove any existing tooltips
      const existingTooltip = document.getElementById('js-tooltip');
      if (existingTooltip) {
        existingTooltip.remove();
      }

      // Get the tooltip text from the element
      const tooltipText = event.currentTarget.getAttribute('data-tooltip');
      if (!tooltipText) return;

      // Create tooltip element
      const tooltip = document.createElement('div');
      tooltip.id = 'js-tooltip';
      tooltip.textContent = tooltipText;
      tooltip.style.position = 'fixed';
      tooltip.style.zIndex = '10000';
      tooltip.style.backgroundColor = 'var(--explorer-background-tertiary, #333)';
      tooltip.style.color = 'var(--explorer-text, #fff)';
      tooltip.style.padding = '10px 14px';
      tooltip.style.borderRadius = '4px';
      tooltip.style.fontSize = '13px';
      tooltip.style.lineHeight = '1.5';
      tooltip.style.maxWidth = '500px';
      tooltip.style.minWidth = '200px';
      tooltip.style.width = 'max-content';
      tooltip.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.2)';
      tooltip.style.pointerEvents = 'none';
      tooltip.style.whiteSpace = 'pre-wrap';
      tooltip.style.textAlign = 'left';

      // Add to the DOM
      document.body.appendChild(tooltip);

      // Get element position
      const rect = event.currentTarget.getBoundingClientRect();

      // Calculate tooltip position based on available space
      const tooltipRect = tooltip.getBoundingClientRect();

      // Default position above the element
      let top = rect.top - tooltipRect.height - 10;
      let left = rect.left;

      // Check if tooltip goes beyond top of viewport
      if (top < 10) {
        // Position below the element
        top = rect.bottom + 10;
      }

      // Check if tooltip goes beyond right edge of viewport
      if (left + tooltipRect.width > window.innerWidth - 10) {
        // Align to right edge with some margin
        left = window.innerWidth - tooltipRect.width - 10;
      }

      // Set final position
      tooltip.style.top = `${top}px`;
      tooltip.style.left = `${left}px`;

      tooltipRef.current = tooltip;
    };

    // Function to remove tooltip
    const removeTooltip = () => {
      if (tooltipRef.current) {
        tooltipRef.current.remove();
        tooltipRef.current = null;
      }
    };

    // Add event listeners
    const handleWrappers = () => {
      const tooltipWrappers = document.querySelectorAll('.field-tooltip-wrapper.js-tooltip');
      tooltipWrappers.forEach(wrapper => {
        wrapper.addEventListener('mouseenter', createTooltip);
        wrapper.addEventListener('mouseleave', removeTooltip);
      });
    };

    // Initial setup
    handleWrappers();

    // Setup observer to watch for DOM changes and add listeners to new elements
    const observer = new MutationObserver(handleWrappers);
    observer.observe(document.body, { childList: true, subtree: true });

    // Clean up
    return () => {
      observer.disconnect();
      if (tooltipRef.current) {
        tooltipRef.current.remove();
      }
    };
  }, []);

  const filteredFields = [...availableFields].sort().filter(field =>
    field.toLowerCase().includes(searchQuery.toLowerCase())
  );

  // Generate tooltip text directly from schema metadata
  const generateTooltipText = (field) => {
    const meta = fieldMetadata[field];
    if (!meta) return field;

    // Check if this is a relationship field (contains a dot)
    const isRelationshipField = field.includes('.');

    // Start with field title from schema if available
    let tooltip = meta.title || field;

    // For relationship fields, add info about relationship
    if (isRelationshipField) {
      const [relationship, fieldName] = field.split('.');
      tooltip = `${tooltip}\nInclude Field`;
      tooltip += `\nFrom: ${relationship}`;
    }

    // Add type information (directly from schema)
    if (meta.type) {
      tooltip += `\n${meta.type}`;

      if (meta.format) {
        tooltip += ` (${meta.format})`;
      }

      if (meta.maxLength) {
        tooltip += `, max length: ${meta.maxLength}`;
      }
    }

    // If the field has an enum or oneOf with const/title pairs
    if (meta.enum && meta.enumTitles && meta.enum.length > 0) {
      tooltip += '\n\nAllowed values:';
      for (let i = 0; i < Math.min(meta.enum.length, meta.enumTitles.length); i++) {
        tooltip += `\n• ${meta.enumTitles[i]} (${meta.enum[i]})`;
      }
    }

    // Add description from schema
    if (meta.description) {
      tooltip += `\n\n${meta.description}`;
    }

    // Show default value if present in schema
    if (meta.default !== null && meta.default !== undefined) {
      tooltip += `\n\nDefault: ${meta.default}`;
    }

    // Add constraints directly from schema
    const constraints = [];
    if (meta.required) constraints.push('Required');
    if (meta.readOnly) constraints.push('Read only');
    if (meta.writeOnly) constraints.push('Write only');

    if (constraints.length > 0) {
      tooltip += `\n\n${constraints.join(', ')}`;
    }

    // For include fields, add note about include requirements
    if (isRelationshipField) {
      const relationship = field.split('.')[0];
      tooltip += `\n\nNote: Requires including the "${relationship}" include`;
    }

    return tooltip;
  };

  return (
    <div className="field-selector form-item" data-testid="fields-selector">
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '8px' }}>
        <div style={{ display: 'flex', alignItems: 'center' }}>
          <h4 className="form-item__label" style={{ margin: 0 }}>Fields</h4>
          <div
            className="field-tooltip-wrapper js-tooltip"
            data-tooltip="If no fields are selected, all fields will be included in the response. Select specific fields to optimize response size."
            style={{ marginLeft: '8px', cursor: 'help' }}
            data-testid="tooltip"
          >
            <span style={{
              display: 'inline-flex',
              alignItems: 'center',
              justifyContent: 'center',
              width: '20px',
              height: '20px',
              borderRadius: '50%',
              background: 'var(--gin-color-primary-light)',
              color: 'var(--gin-color-primary)',
              fontSize: '14px',
              fontWeight: 'bold'
            }}>?</span>
          </div>
        </div>
        <div>
          <button
            className="button button--small"
            onClick={handleSelectAll}
            style={{ marginRight: '4px' }}
            data-testid="select-all-fields"
          >
            Select all
          </button>
          <button
            className="button button--small"
            onClick={handleClearAll}
            disabled={selectedFields.length === 0}
          >
            Clear
          </button>
        </div>
      </div>

      {(selectedEntity && selectedBundle) ? (
        <>
          <div className="claro-details">
            <div className="claro-details__wrapper">
              <div className="form-items-inline">
                <div className="form-item search-field-container" style={{ flexGrow: 1, position: 'relative', marginBottom: '16px' }}>
                  <input
                    type="text"
                    className="form-element"
                    placeholder="Search fields"
                    value={searchQuery}
                    onChange={(e) => setSearchQuery(e.target.value)}
                  />
                  {searchQuery && (
                    <button
                      type="button"
                      aria-label="Clear search"
                      onClick={() => setSearchQuery('')}
                      style={{
                        position: 'absolute',
                        right: '8px',
                        top: '50%',
                        transform: 'translateY(-50%)',
                        background: 'none',
                        border: 'none',
                        cursor: 'pointer',
                        padding: '4px',
                        fontSize: '16px',
                        color: '#666',
                        zIndex: 2
                      }}
                    >
                      ✕
                    </button>
                  )}
                </div>
              </div>

              {loading ? (
                <div className="form-item__description">
                  <div className="spinner" style={{ display: 'inline-block', marginRight: '8px' }}></div>
                  Loading fields…
                </div>
              ) : error ? (
                <div className="messages messages--error">
                  {error}
                </div>
              ) : (
                <>
                  <div className="available-fields" style={{ display: 'flex', flexDirection: 'column', flexGrow: 1, height: '100%' }}>
                    {/*<h5 className="fields-group-title">Fields</h5>*/}
                    <div className="claro-details__wrapper fields-list" style={{ margin: 0, display: 'flex', flexDirection: 'column', flexGrow: 1 }}>
                      {filteredFields.length === 0 ? (
                        <div className="form-item__description">No fields match your search</div>
                      ) : (
                        <div className="field-chips">
                          {/* Direct fields (without dots in name) */}
                          <div className="field-chips__direct">
                            <div style={{ display: 'flex', alignItems: 'center', marginBottom: '8px' }}>
                              <h5 className="fields-group-title" style={{ margin: 0, display: 'inline' }}>Direct fields</h5>
                              <div
                                className="field-tooltip-wrapper js-tooltip"
                                data-tooltip={`These are fields that belong directly to the **${selectedBundle}** entity`}
                                style={{ marginLeft: '4px', cursor: 'help' }}
                              >
                                <span style={{
                                  display: 'inline-flex',
                                  alignItems: 'center',
                                  justifyContent: 'center',
                                  width: '20px',
                                  height: '20px',
                                  borderRadius: '50%',
                                  background: 'var(--gin-color-primary-light)',
                                  color: 'var(--gin-color-primary)',
                                  fontSize: '14px',
                                  fontWeight: 'bold'
                                }}>?</span>
                              </div>
                            </div>
                            <div style={{ display: 'flex', flexWrap: 'wrap', gap: '8px' }}>
                            {filteredFields
                              .filter(field => {
                                // Direct fields don't have dots AND include base relationship fields
                                const isDirectField = !field.includes('.');

                                // Also include base relationship fields (e.g., "uid")
                                // We can determine this by checking if the field exists in related entity fields
                                // AND it doesn't have a dot in it (meaning it's a base relationship, not a field of a relationship)
                                const isBaseRelationship = Object.keys(relatedEntityFields).some(rel => {
                                  return relatedEntityFields[rel].some(f =>
                                    f.name === field && f.isBaseRelationship === true
                                  );
                                });

                                return isDirectField || isBaseRelationship;
                              })
                              .map(field => {
                                // Determine if this is a base relationship field
                                // There are two ways this could happen:
                                // 1. This field is specifically marked as a base relationship
                                // 2. This field name exactly matches a relationship name in our relationshipFields object
                                const isBaseRelationship = Object.keys(relatedEntityFields).some(rel => {
                                  return (
                                    // Either the field is marked as a base relationship
                                    relatedEntityFields[rel].some(f =>
                                      f.name === field && f.isBaseRelationship === true
                                    ) ||
                                    // Or the field name matches the relationship name exactly
                                    field === rel
                                  );
                                });

                                return (
                                  <div
                                    key={field}
                                    className="field-tooltip-wrapper js-tooltip"
                                    data-tooltip={generateTooltipText(field)}
                                  >
                                    <span
                                      className={`gin-chip ${isBaseRelationship ? 'gin-chip--base-relationship' : ''} ${selectedFields.includes(field) ? 'gin-chip--primary' : ''}`}
                                      onClick={() => handleFieldToggle(field)}
                                      aria-label={generateTooltipText(field).replace(/\n/g, ', ')}
                                      style={isBaseRelationship ? { borderStyle: 'dashed' } : {}}
                                    >
                                      {field}{isBaseRelationship ? ' (relationship)' : ''}
                                    </span>
                                  </div>
                                );
                              })}
                            </div>
                            </div>

                            {/* Show loading indicator for related fields based on locally tracked state */}
                            {(localLoadingState || loadingRelatedFields) && selectedEntity && selectedBundle && (
                              <div className="loading-related-fields" data-testid="loading-indicator" style={{ padding: '12px', marginTop: '16px', marginBottom: '16px', backgroundColor: 'rgba(99, 102, 241, 0.05)', borderRadius: '6px', borderLeft: '3px solid #6366f1' }}>
                                <div className="spinner" style={{ display: 'inline-block', marginRight: '8px' }}></div>
                                <span><strong>Loading relationship fields…</strong> The Fields tab will show newly available fields from included relationships.</span>
                              </div>
                            )}

                            {/* Display related fields grouped by relationship */}
                            {Object.keys(relatedEntityFields).length > 0 &&
                              Object.keys(relatedEntityFields).map(relationship => {
                                // Get fields for this relationship that match the filter
                                // Exclude the base relationship field itself
                                const relationshipFields = filteredFields.filter(
                                  field => field.startsWith(`${relationship}.`)
                                );

                                // Only show if we have matching fields
                                if (relationshipFields.length === 0) return null;

                                return (
                                  <div key={relationship} className="field-chips__relationship">
                                    <div style={{ display: 'flex', alignItems: 'center', marginBottom: '8px', width: '100%' }}>
                                      <h5 className="include-fields-title" style={{ margin: 0, display: 'flex', alignItems: 'center' }}>
                                        {relationship} Fields
                                        {!selectedFields.includes(relationship) && (
                                          <div
                                            className="field-tooltip-wrapper js-tooltip"
                                            data-tooltip={`These fields come from the **${relationship}** include. Selecting any field here will also add the **${relationship}** field to your request.`}
                                            style={{ marginLeft: '8px', cursor: 'help' }}
                                          >
                                            <span style={{
                                              display: 'inline-flex',
                                              alignItems: 'center',
                                              justifyContent: 'center',
                                              width: '20px',
                                              height: '20px',
                                              borderRadius: '50%',
                                              background: 'var(--gin-color-primary-light)',
                                              color: 'var(--gin-color-primary)',
                                              fontSize: '14px',
                                              fontWeight: 'bold'
                                            }}>?</span>
                                          </div>
                                        )}
                                      </h5>
                                    </div>
                                    <div style={{ display: 'flex', flexWrap: 'wrap', gap: '8px' }}>
                                    {relationshipFields.map(field => (
                                      <div
                                        key={field}
                                        className="field-tooltip-wrapper js-tooltip"
                                        data-tooltip={generateTooltipText(field)}
                                      >
                                        <span
                                          className={`gin-chip gin-chip--relationship ${selectedFields.includes(field) ? 'gin-chip--primary' : ''}`}
                                          onClick={() => handleFieldToggle(field)}
                                          aria-label={generateTooltipText(field).replace(/\n/g, ', ')}
                                        >
                                          {field.split('.')[1]} {/* Just show the field name after the dot */}
                                        </span>
                                      </div>
                                    ))}
                                    </div>
                                  </div>
                                );
                              })
                            }
                          </div>
                      )}
                    </div>
                  </div>
                </>
              )}
            </div>
          </div>
        </>
      ) : (
        <div className="form-item__description">
          Select an entity type and **bundle** to see available fields
        </div>
      )}
    </div>
  );
}

export default FieldsSelector;
