import axios from 'axios';

/**
 * Utility service for working with OpenAPI schema
 */
const OpenApiSchemaUtil = {
  // Cache for the OpenAPI schema to avoid repeated fetching
  schemaCache: null,

  /**
   * Fetch the complete OpenAPI schema
   *
   * @param {string} baseUrl - The JSON:API base URL
   * @returns {Promise<object>} - The OpenAPI schema
   */
  fetchSchema: async (baseUrl) => {
    if (OpenApiSchemaUtil.schemaCache) {
      return OpenApiSchemaUtil.schemaCache;
    }

    try {
      const openApiUrl = drupalSettings.path.baseUrl + "openapi/jsonapi"
      const response = await axios.get(openApiUrl);
      if (response.data && response.data.paths) {
        OpenApiSchemaUtil.schemaCache = response.data;
        return response.data;
      }
      throw new Error('Invalid OpenAPI schema format');
    } catch (err) {
      throw new Error(`Error fetching OpenAPI schema: ${err.message}`);
    }
  },


  /**
   * Extract field information for a specific entity type and bundle
   *
   * @param {object} schema - The OpenAPI schema
   * @param {string} entityType - The entity type (e.g., 'node')
   * @param {string} bundle - The bundle (e.g., 'article')
   * @returns {object} - Object with attributes and relationships arrays
   */
  getEntityFields: (schema, entityType, bundle) => {
    console.log(`Getting fields for ${entityType}/${bundle}`);

    // Direct extraction from OpenAPI schema using standard patterns
    const attributes = [];
    const relationships = [];

    // Check if we have a valid schema
    if (!schema) {
      console.error('No schema provided');
      return { attributes, relationships };
    }

    // Handle OpenAPI 2.0 (Swagger) vs OpenAPI 3.0
    // OpenAPI 2.0 uses 'definitions', OpenAPI 3.0 uses 'components.schemas'
    let schemaSection = null;
    let schemaVersion = "unknown";

    if (schema.swagger && schema.swagger.startsWith('2')) {
      schemaSection = schema.definitions;
      schemaVersion = "2.0 (Swagger)";
    } else if (schema.openapi && schema.openapi.startsWith('3')) {
      schemaSection = schema.components?.schemas;
      schemaVersion = "3.0";
    }

    console.log(`Detected OpenAPI version: ${schemaVersion}`);

    if (!schemaSection) {
      console.error('No schema definitions or components found');
      return { attributes, relationships };
    }

    // The entity schema name in Drupal is typically in the format "entityType--bundle"
    const expectedSchemaName = `${entityType}--${bundle}`;
    const resourceSchema = schemaSection[expectedSchemaName];

    if (!resourceSchema) {
      console.error(`No schema found for ${expectedSchemaName}`);
      return { attributes, relationships };
    }

    console.log(`Found schema for ${expectedSchemaName}`);


    // If we found a schema, extract field information
    if (resourceSchema && resourceSchema.properties) {
      console.log('Found schema with properties:', Object.keys(resourceSchema.properties));

      // In Drupal's OpenAPI 2.0 format, the fields are nested under data.attributes and data.relationships
      const dataProperties = resourceSchema.properties.data?.properties;

      if (!dataProperties) {
        console.error('Schema does not have data.properties structure');
        return { attributes, relationships };
      }

      // Extract attributes - these are in data.attributes.properties
      const attributesSchema = dataProperties.attributes?.properties;
      if (attributesSchema) {
        console.log(`Found ${Object.keys(attributesSchema).length} attribute fields`);

        Object.entries(attributesSchema).forEach(([name, def]) => {
          attributes.push({
            name,
            title: def.title || name,
            type: def.type || 'string',
            description: def.description || '',
            required: resourceSchema.required?.includes(`data.attributes.${name}`) || false,
            readOnly: def.readOnly === true,
            format: def.format || undefined,
            enum: def.enum || undefined
          });
        });
      } else {
        console.error('No attributes found in schema');
      }

      // Process relationships - these are in data.relationships.properties
      const relationshipsSchema = dataProperties.relationships?.properties;
      if (relationshipsSchema) {
        console.log(`Found ${Object.keys(relationshipsSchema).length} relationship fields`);

        Object.entries(relationshipsSchema).forEach(([name, def]) => {
          // For OpenAPI 2.0, determine if this is a to-many relationship
          let isCollection = false;
          let targetType = name;  // Default to the relationship name if type can't be determined

          // Process the relationship structure to find type and collection status
          if (def.properties?.data) {
            if (def.properties.data.type === 'array') {
              isCollection = true;

              // Try to find target type for to-many relationship
              if (def.properties.data.items?.properties?.type?.enum?.[0]) {
                targetType = def.properties.data.items.properties.type.enum[0];
              }
            } else {
              // For to-one relationship
              if (def.properties.data.properties?.type?.enum?.[0]) {
                targetType = def.properties.data.properties.type.enum[0];
              }
            }
          }

          relationships.push({
            name,
            title: def.title || name,
            description: def.description || '',
            targetType,
            isCollection,
            required: resourceSchema.required?.includes(`data.relationships.${name}`) || false
          });
        });
      } else {
        console.error('No relationships found in schema');
      }
    }

    console.log(`Total fields extracted: ${attributes.length} attributes, ${relationships.length} relationships`);
    return { attributes, relationships };
  }
  // Support for both OpenAPI 2.0 and 3.0 formats
};

export default OpenApiSchemaUtil;
