import React, { useState, useEffect } from 'react';
import OpenApiSchemaUtil from '../utils/openApiSchema';

/**
 * Modified FieldsSelector that uses OpenAPI schema instead of JSON:API Schema
 *
 * @param {string} selectedEntity - The selected entity type
 * @param {string} selectedBundle - The selected bundle
 * @param {array} selectedFields - The currently selected fields
 * @param {function} onFieldsChange - Callback for field changes
 * @param {object} relatedEntityFields - Fields from related entities
 * @param {boolean} loadingRelatedFields - Whether related fields are loading
 * @param {string} baseUrl - The base URL for the JSON:API
 * @param {array} includes - Currently selected includes
 * @param {function} onIncludeChange - Callback for include changes
 */
function OpenApiFieldsSelector({ selectedEntity, selectedBundle, selectedFields, onFieldsChange, relatedEntityFields = {}, loadingRelatedFields = false, baseUrl, includes = [], onIncludeChange }) {
  const [availableFields, setAvailableFields] = useState([]);
  const [fieldMetadata, setFieldMetadata] = useState({});
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);
  const [searchQuery, setSearchQuery] = useState('');
  const [openApiSchema, setOpenApiSchema] = useState(null);

  // Load the OpenAPI schema on component mount
  useEffect(() => {
    const loadSchema = async () => {
      try {
        const schema = await OpenApiSchemaUtil.fetchSchema(baseUrl);
        setOpenApiSchema(schema);
      } catch (err) {
        setError(`Error loading OpenAPI schema: ${err.message}`);
      }
    };

    loadSchema();
  }, [baseUrl]);

  // Load fields when entity, bundle, or schema changes
  useEffect(() => {
    if (selectedEntity && selectedBundle && openApiSchema) {
      fetchFields();
    } else {
      setAvailableFields([]);
      setFieldMetadata({});
    }
  }, [selectedEntity, selectedBundle, openApiSchema]);

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

    setLoading(true);
    setError(null);

    try {
      // Extract fields from the OpenAPI schema
      const { attributes, relationships } = OpenApiSchemaUtil.getEntityFields(openApiSchema, selectedEntity, selectedBundle);

      // Process attributes (regular fields)
      const fieldNames = [];
      const metadata = {};

      attributes.forEach(attr => {
        fieldNames.push(attr.name);
        metadata[attr.name] = {
          name: attr.name,
          title: attr.title || attr.name,
          type: attr.type || 'string',
          description: attr.description || '',
          format: attr.format || '',
          required: attr.required === true,
          readOnly: attr.readOnly === true
        };
      });

      // Add relationship fields directly
      relationships.forEach(rel => {
        fieldNames.push(rel.name);
        metadata[rel.name] = {
          name: rel.name,
          title: rel.title || rel.name,
          type: 'relationship',
          description: rel.description || '',
          targetType: rel.targetType || 'unknown',
          isCollection: rel.isCollection === true
        };
      });

      setAvailableFields(fieldNames);
      setFieldMetadata(metadata);
    } catch (err) {
      setError(`Unable to get fields: ${err.message}`);
    } finally {
      setLoading(false);
    }
  };

  // Filter fields based on search query
  const filteredFields = [...availableFields].sort().filter(field =>
    field.toLowerCase().includes(searchQuery.toLowerCase())
  );

  // Toggle field selection
  const handleFieldToggle = (field) => {
    // Check if this is a relationship field (contains a dot)
    const parts = field.split('.');
    if (parts.length > 1) {
      const relationship = parts[0];

      // Ensure the relationship is included
      if (!includes.includes(relationship) && onIncludeChange) {
        console.log(`Auto-including relationship "${relationship}" for field "${field}"`);
        onIncludeChange([...includes, relationship]);
      }
    }

    if (selectedFields.includes(field)) {
      // If removing a field
      onFieldsChange(selectedFields.filter(f => f !== field));
    } else {
      // If adding a field
      onFieldsChange([...selectedFields, field]);
    }
  };

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

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

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

    let tooltip = meta.title || field;

    if (meta.type) {
      tooltip += `\n${meta.type}`;

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

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

    const constraints = [];
    if (meta.required) constraints.push('Required');
    if (meta.readOnly) constraints.push('Read only');

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

    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">
              {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="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>

                  <div className="available-fields" style={{ display: 'flex', flexDirection: 'column', flexGrow: 1, height: '100%' }}>
                    <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">
                          <div className="field-chips__direct">
                            <div style={{ display: 'flex', alignItems: 'center', marginBottom: '8px' }}>
                              <h5 className="fields-group-title" style={{ margin: 0, display: 'inline' }}>Fields</h5>
                            </div>
                            <div style={{ display: 'flex', flexWrap: 'wrap', gap: '8px' }}>
                              {filteredFields.map(field => {
                                const isRelationship = fieldMetadata[field]?.type === 'relationship';

                                // If this is a relationship field, make it selected if the corresponding
                                // relationship is included
                                const isForceSelected = isRelationship && includes.includes(field);
                                const isSelected = selectedFields.includes(field) || isForceSelected;

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

                          {/* Display relationship fields from includes */}
                          {Object.keys(relatedEntityFields).length > 0 && (
                            <div>
                              {/* Show loading indicator for related fields */}
                              {loadingRelatedFields && (
                                <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).map(relationship => {
                                // Get fields for this relationship
                                const relationshipFields = relatedEntityFields[relationship];

                                // Skip if no fields found
                                if (!relationshipFields || relationshipFields.length === 0) return null;

                                return (
                                  <div key={relationship} className="field-chips__relationship" style={{ marginTop: '20px' }}>
                                    <div style={{ display: 'flex', alignItems: 'center', marginBottom: '8px', width: '100%' }}>
                                      <h5 className="include-fields-title" style={{ margin: 0, display: 'flex', alignItems: 'center' }}>
                                        {relationship} Fields
                                      </h5>
                                    </div>
                                    <div style={{ display: 'flex', flexWrap: 'wrap', gap: '8px' }}>
                                      {relationshipFields.map((field) => {
                                        // Skip the main relationship field (e.g., skip "uid" in "uid" section)
                                        // This avoids showing "uid" again in the uid fields section
                                        if (field.name === relationship) {
                                          return null;
                                        }

                                        return (
                                          <div
                                            key={field.name}
                                            className="field-tooltip-wrapper js-tooltip"
                                            data-tooltip={field.name}
                                          >
                                            <span
                                              className={`gin-chip gin-chip--relationship ${selectedFields.includes(field.name) ? 'gin-chip--primary' : ''}`}
                                              onClick={() => handleFieldToggle(field.name)}
                                            >
                                              {field.name.split('.')[1] || field.name}
                                            </span>
                                          </div>
                                        );
                                      })}
                                    </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 OpenApiFieldsSelector;
