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

function IncludeSelector({selectedEntity, selectedBundle, includes, onIncludeChange, baseUrl}) {
  const [availableRelationships, setAvailableRelationships] = useState([]);
  const [relationshipMetadata, setRelationshipMetadata] = useState({});
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

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

  useEffect(() => {
    if (selectedEntity && selectedBundle) {
      fetchRelationships();
    } else {
      setAvailableRelationships([]);
      setRelationshipMetadata({});
    }
  }, [selectedEntity, selectedBundle]);

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

    setLoading(true);
    setError(null);

    try {
      console.log(`Fetching relationships for ${selectedEntity}/${selectedBundle}`);

      // Use the OpenAPI endpoint instead of resource/schema
      const openApiUrl = drupalSettings.path.baseUrl + "openapi/jsonapi"
      console.log('Using OpenAPI endpoint for relationships:', openApiUrl);

      const response = await fetch(openApiUrl);

      if (response.ok) {
        const data = await response.json();
        console.log('Schema data for relationships received:', data);

        // Extract relationships from the schema
        let relationshipNames = [];
        let metadata = {};

        // Function to extract metadata from a relationship definition
        const extractRelationshipMetadata = (relName, relDef) => {
          if (!metadata[relName]) {
            // Try to determine the target entity type
            let targetType = 'unknown';
            let isCollection = false;

            // Look for 'data' property which usually has the target type info
            if (relDef.properties && relDef.properties.data) {
              const dataProps = relDef.properties.data;

              // Check if it's a collection (array of items) or single item
              if (dataProps.type === 'array' && dataProps.items && dataProps.items.properties && dataProps.items.properties.type) {
                isCollection = true;
                // For collections, type info is in items.properties.type
                if (dataProps.items.properties.type.enum && dataProps.items.properties.type.enum.length > 0) {
                  targetType = dataProps.items.properties.type.enum[0];
                }
              } else if (dataProps.properties && dataProps.properties.type) {
                // For single items, type info is in properties.type
                if (dataProps.properties.type.enum && dataProps.properties.type.enum.length > 0) {
                  targetType = dataProps.properties.type.enum[0];
                }
              }
            }

            // Create the metadata object - extract directly from schema
            metadata[relName] = {
              name: relName,
              // Use the title from the schema if available
              title: relDef.title || relName,
              description: relDef.description || '',
              targetType: targetType,
              isCollection: isCollection,
              readOnly: relDef.readOnly === true,
              // Add more relationship metadata as needed
            };
          }
        };

        // Find the schema for this entity type and bundle in OpenAPI definitions
        const resourceType = `${selectedEntity}--${selectedBundle}`;
        if (data && data.definitions && data.definitions[resourceType]) {
          const resourceSchema = data.definitions[resourceType];
          console.log(`Found schema for ${resourceType} in OpenAPI 2.0 definitions`);

          // In OpenAPI 2.0, relationships are in data.relationships.properties
          if (resourceSchema.properties?.data?.properties?.relationships?.properties) {
            const relationships = resourceSchema.properties.data.properties.relationships.properties;
            console.log(`Found ${Object.keys(relationships).length} relationships in OpenAPI schema`);

            Object.entries(relationships).forEach(([rel, relDef]) => {
              relationshipNames.push(rel);
              extractRelationshipMetadata(rel, relDef);
            });
          }
        }

        // If no relationships found yet, try other entity types as reference
        if (relationshipNames.length === 0) {
          console.log(`Schema for ${resourceType} not found or has no relationships. Checking other schemas...`);

          // Look for any entity type that might have relationships
          Object.keys(data.definitions).forEach(defKey => {
            // Only check entity-like definitions (skip utility schemas)
            if (defKey.includes('--') && data.definitions[defKey].properties?.data?.properties?.relationships?.properties) {
              const relationships = data.definitions[defKey].properties.data.properties.relationships.properties;

              console.log(`Using relationships from ${defKey} as reference`);
              Object.entries(relationships).forEach(([rel, relDef]) => {
                if (!relationshipNames.includes(rel)) {
                  relationshipNames.push(rel);
                  extractRelationshipMetadata(rel, relDef);
                }
              });

              // If we've found some relationships, stop searching
              if (relationshipNames.length > 0) {
                return;
              }
            }
          });
        }

        // Still no relationships? Check if there's a properties.relationships path
        if (relationshipNames.length === 0 && data.properties && data.properties.relationships &&
          data.properties.relationships.properties) {
          console.log('Found relationships in root properties.relationships.properties');
          Object.entries(data.properties.relationships.properties).forEach(([rel, relDef]) => {
            if (!relationshipNames.includes(rel)) {
              relationshipNames.push(rel);
              extractRelationshipMetadata(rel, relDef);
            }
          });
        }

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

            // Check if this is a relationships object with properties
            if (currentPath.includes('relationships') && obj.properties) {
              console.log(`Found potential relationships at: ${currentPath}`, obj.properties);
              Object.entries(obj.properties).forEach(([rel, relDef]) => {
                if (!relationshipNames.includes(rel)) {
                  relationshipNames.push(rel);
                  extractRelationshipMetadata(rel, relDef);
                }
              });
            }

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

          findRelationshipProperties(data);
        }

        // We found some relationships
        if (relationshipNames.length > 0) {
          console.log('Final relationship names extracted:', relationshipNames);
          console.log('Relationship metadata extracted:', metadata);

          // Fill in any missing metadata with basic information
          relationshipNames.forEach(rel => {
            if (!metadata[rel]) {
              // Basic fallback if somehow we got a relationship name without metadata
              metadata[rel] = {
                name: rel,
                title: rel.startsWith('field_') ?
                  rel.replace('field_', '').replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase()) :
                  rel.charAt(0).toUpperCase() + rel.slice(1),
              };
            }
          });

          setAvailableRelationships(relationshipNames);
          setRelationshipMetadata(metadata);
        } else {
          console.log('No relationships found in schema, setting empty list');
          setAvailableRelationships([]);
          setRelationshipMetadata({});
        }
      } else {
        console.log('Schema endpoint failed with status:', response.status);
        setError(`Schema endpoint failed with status: ${response.status}`);
      }
    } catch (err) {
      console.error('Error fetching relationships:', err);
      setError(`Unable to get relationships: ${err.message}`);
    } finally {
      setLoading(false);
    }
  };

  // Fallback relationships for when API requests fail
  const getCommonRelationships = (entityType, bundle) => {
    // Entity-type specific relationships
    switch (entityType) {
      case 'node':
        const baseRelationships = ['uid', 'revision_uid', 'type'];

        // Add bundle-specific relationships for common content types
        if (bundle === 'article') {
          return [...baseRelationships, 'field_tags', 'field_image'];
        } else if (bundle === 'page') {
          return [...baseRelationships, 'field_meta_tags'];
        } else if (bundle === 'song') {
          return [
            ...baseRelationships,
            'field_song_genre',
            'field_song_image',
            'field_song_audio',
            'field_song_channel_1_author',
            'field_song_channel_2_author',
            'field_song_channel_3_author',
            'field_song_channel_4_author'
          ];
        } else if (bundle === 'course') {
          return [
            ...baseRelationships,
            'field_resources',
            'field_tags',
            'field_video'
          ];
        } else if (bundle === 'lesson') {
          return [
            ...baseRelationships,
            'field_course',
            'field_attachment',
            'field_video',
            'field_image'
          ];
        } else if (bundle === 'video') {
          return [
            ...baseRelationships,
            'field_video',
            'field_tags'
          ];
        }
        return baseRelationships;

      case 'user':
        return ['roles', 'user_picture'];

      case 'taxonomy_term':
        if (bundle === 'tags') {
          return ['parent', 'vid'];
        } else if (bundle === 'genres') {
          return ['parent', 'vid', 'field_genre_image'];
        }
        return ['parent', 'vid'];

      case 'media':
        const mediaBase = ['thumbnail', 'uid'];

        if (bundle === 'image') {
          return [...mediaBase, 'field_media_image'];
        } else if (bundle === 'video') {
          return [...mediaBase, 'field_media_video_embed_field'];
        } else if (bundle === 'document') {
          return [...mediaBase, 'field_document'];
        }
        return mediaBase;

      case 'comment':
        const commentBase = ['uid', 'entity_id', 'pid'];

        if (bundle === 'song_comment') {
          return commentBase;
        } else if (bundle === 'video_comment') {
          return [...commentBase, 'field_video'];
        }
        return commentBase;

      default:
        return [];
    }
  };

  const handleIncludeToggle = (relationshipName) => {
    console.log(`Include toggle: ${relationshipName}`);
    if (includes.includes(relationshipName)) {
      // Removing an include
      onIncludeChange(includes.filter(inc => inc !== relationshipName));
    } else {
      // Adding an include
      onIncludeChange([...includes, relationshipName]);
    }
  };

  const handleClearAll = () => {
    console.log('Clearing all includes');
    onIncludeChange([]);
  };

  // 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();
      }
    };
  }, []);

  // Generate tooltip text for relationships based on schema info
  const generateRelationshipTooltip = (rel) => {
    const meta = relationshipMetadata[rel];
    if (!meta) return rel;

    // Use title from schema if available, otherwise use relationship name
    let tooltip = meta.title || rel;

    // Add target type info if available
    if (meta.targetType && meta.targetType !== 'unknown') {
      tooltip += `\n${meta.isCollection ? 'Collection of ' : ''}${meta.targetType}`;
    }

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

    // Add select status
    if (includes.includes(rel)) {
      tooltip += '\n\nIncluded in response';
    }

    return tooltip;
  };

  availableRelationships.sort();

  return (
    <div className="include-selector form-item" data-testid="include-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}}>Includes (relationships)</h4>
          <div
            className="field-tooltip-wrapper js-tooltip"
            data-tooltip="Adding includes acts like a JOIN, allowing fields, filters, and sorts on related entity data."
            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>
        <button
          className="button button--small"
          onClick={handleClearAll}
          disabled={includes.length === 0}
        >
          Clear
        </button>
      </div>

      {(selectedEntity && selectedBundle) ? (
        <>
          <div className="claro-details">
            <div className="claro-details__wrapper">
              {loading ? (
                <div className="form-item__description">
                  <div className="spinner" style={{display: 'inline-block', marginRight: '8px'}}></div>
                  Loading relationships…
                </div>
              ) : error ? (
                <div className="messages messages--error">
                  {error}
                </div>
              ) : (
                <>
                  <div className="available-relationships">
                    <h5 className="fields-group-title" style={{borderBottom: 'none'}}>Includes</h5>
                    <div className="relationship-list" style={{margin: 0, position: 'relative'}}>
                      {availableRelationships.length === 0 ? (
                        <div className="form-item__description">
                          No includes available for this entity type
                        </div>
                      ) : (
                        <div className="relationship-chips"
                             style={{display: 'flex', flexWrap: 'wrap', gap: '8px', position: 'relative'}}>
                          {availableRelationships.map(rel => (
                            <div
                              key={rel}
                              className="field-tooltip-wrapper js-tooltip"
                              data-tooltip={generateRelationshipTooltip(rel)}
                              style={{position: 'relative'}}
                            >
                              <span
                                className={`gin-chip ${includes.includes(rel) ? 'gin-chip--primary' : ''}`}
                                onClick={() => handleIncludeToggle(rel)}
                                aria-label={generateRelationshipTooltip(rel).replace(/\n/g, ', ')}
                              >
                                {rel}
                              </span>
                            </div>
                          ))}
                        </div>
                      )}
                    </div>
                  </div>
                </>
              )}
            </div>
          </div>
        </>
      ) : (
        <div className="form-item__description">
          Select an entity type and **bundle** to see available includes
        </div>
      )}
    </div>
  );
}

export default IncludeSelector;
