import apiClient from './client';
import { auth, dataConnect } from '../firebase';
import { signOut } from 'firebase/auth';

import * as dcSdk from '@dataconnect/generated'; // listEvents, createEvent, etc.

// --- Auth Module ---
const authModule = {
  /**
   * Fetches the currently authenticated user's profile from the backend.
   * @returns {Promise<object>} The user profile.
   */
  me: async () => {
    const { data } = await apiClient.get('/auth/me');
    return data;
  },

  /**
   * Logs the user out.
   * @param {string} [redirectUrl] - Optional URL to redirect to after logout.
   */
  logout: async (redirectUrl) => {
    await signOut(auth);
    if (redirectUrl) {
      window.location.href = redirectUrl;
    }
  },

  /**
   * Checks if a user is currently authenticated.
   * @returns {boolean} True if a user is authenticated.
   */
  isAuthenticated: () => {
    return !!auth.currentUser;
  },
};

// --- Core Integrations Module ---
const coreIntegrationsModule = {
  /**
   * Sends an email.
   * @param {object} params - { to, subject, body }
   * @returns {Promise<object>} API response.
   */
  SendEmail: async (params) => {
    const { data } = await apiClient.post('/sendEmail', params);
    return data;
  },

  /**
   * Invokes a large language model.
   * @param {object} params - { prompt, response_json_schema, file_urls }
   * @returns {Promise<object>} API response.
   */
  InvokeLLM: async (params) => {
    const { data } = await apiClient.post('/invokeLLM', params);
    return data;
  },

  /**
   * Uploads a public file.
   * @param {File} file - The file to upload.
   * @returns {Promise<object>} API response with file_url.
   */
  UploadFile: async ({ file }) => {
    const formData = new FormData();
    formData.append('file', file);
    const { data } = await apiClient.post('/uploadFile', formData, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    return data;
  },

  /**
   * Uploads a private file.
   * @param {File} file - The file to upload.
   * @returns {Promise<object>} API response with file_uri.
   */
  UploadPrivateFile: async ({ file }) => {
    const formData = new FormData();
    formData.append('file', file);
    const { data } = await apiClient.post('/uploadPrivateFile', formData, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    return data;
  },

  /**
   * Creates a temporary signed URL for a private file.
   * @param {object} params - { file_uri, expires_in }
   * @returns {Promise<object>} API response with signed_url.
   */
  CreateFileSignedUrl: async (params) => {
    const { data } = await apiClient.post('/createSignedUrl', params);
    return data;
  },
};

// --- Entities Module ---
// Based on docs/07-reference-base44-api-export.md
/*const entityNames = [
  "User", "Event", "Staff", "Vendor", "VendorRate", "Invoice", "Business", 
  "Certification", "Team", "Conversation", "Message", "ActivityLog", 
  "Enterprise", "Sector", "Partner", "Order", "Shift"
];

const entitiesModule = {};

entityNames.forEach(entityName => {
  // This factory creates a standard set of CRUD-like methods for each entity.
  // It assumes a consistent RESTful endpoint structure: /entities/{EntityName}/{method}
  entitiesModule[entityName] = {
    get: async (params) => {
      const { data } = await apiClient.get(`/entities/${entityName}/get`, { params });
      return data;
    },
    create: async (params) => {
      const { data } = await apiClient.post(`/entities/${entityName}/create`, params);
      return data;
    },
    update: async (params) => {
      const { data } = await apiClient.post(`/entities/${entityName}/update`, params);
      return data;
    },
    delete: async (params) => {
      const { data } = await apiClient.post(`/entities/${entityName}/delete`, params);
      return data;
    },
    filter: async (params) => {
      const { data } = await apiClient.post(`/entities/${entityName}/filter`, params);
      return data;
    },
    list: async () => {
      // Assuming a 'filter' with no params can act as 'list'
      const { data } = await apiClient.post(`/entities/${entityName}/filter`, {});
      return data;
    }
  };
});*/

const dataconnectEntityConfig = {
  Event: {
    list: 'listEvents',
    create: 'createEvent',
    // get: 'getEvent',
    // update: 'updateEvent',
    // delete: 'deleteEvent',
    // filter: 'filterEvents',
  },

  Staff: {
    list: 'listStaff',
    create: 'createStaff',

  },

  Vendor: {
    list: 'listVendor',
    get: 'getVendorById',
    create: 'createVendor',
    update: 'updateVendor',
    delete: 'deleteVendor',
    filter: 'filterVendors',
  },

  VendorRate: {

  },
  
  Invoice:{

  },
  
  Business:{

  },

  Certification:{

  },
  
  Team:{

  },
  
  Conversation:{

  }, 
  
  Message:{

  }, 
  
  ActivityLog:{

  },

  Enterprise:{

  }, 
  
  Sector:{

  },
  
  Partner:{

  }, 
  
  Order:{

  }, 
  
  Shift:{

  }
  
};

// Helper for methods not implemented 
const notImplemented = (entityName, method) => async () => {
  throw new Error(`${entityName}.${method} is not implemented yet for Data Connect`);
};

// --- Entities Module ( Data Connect, without REST Base44) ---
const entitiesModule = {};

Object.entries(dataconnectEntityConfig).forEach(([entityName, ops]) => {
  entitiesModule[entityName] = {
    
    get: notImplemented(entityName, 'get'),
    update: notImplemented(entityName, 'update'),
    delete: notImplemented(entityName, 'delete'),
    filter: notImplemented(entityName, 'filter'),
    list: notImplemented(entityName, 'list'),
    create: notImplemented(entityName, 'create'),

    // list
    ...(ops.list && {
      list: async (params) => {
        const fn = dcSdk[ops.list];
        if (typeof fn !== 'function') {
          throw new Error(
            `Data Connect operation "${ops.list}" not found for entity "${entityName}".`
          );
        }
        
        return fn(dataConnect);
      },
    }),

    // create
    ...(ops.create && {
      create: async (params) => {
        const fn = dcSdk[ops.create];
        if (typeof fn !== 'function') {
          throw new Error(
            `Data Connect operation "${ops.create}" not found for entity "${entityName}".`
          );
        }

        const { data } = params ?? {};
        if (!data) {
          throw new Error(
            `${entityName}.create expects a payload like { data: { ...fields } }`
          );
        }

        return fn(dataConnect, data);
      },
    }),

    //get
    ...(ops.get && {
      get: async (params) => {
        const fn = dcSdk[ops.get];
        if (typeof fn !== 'function') {
          throw new Error(
            `Data Connect operation "${ops.get}" not found for entity "${entityName}".`
          );
        }

        if (!params || typeof params !== 'object') {
          throw new Error(`${entityName}.get expects an object of variables (e.g. { id })`);
        }

        return fn(dataConnect, params);
      },
    }),
    
    //update
    ...(ops.update && {
      update: async (params) => {
        const fn = dcSdk[ops.update];
        if (typeof fn !== 'function') {
          throw new Error(
            `Data Connect operation "${ops.update}" not found for entity "${entityName}".`
          );
        }

        if (!params || typeof params !== 'object') {
          throw new Error(
            `${entityName}.update expects an object of variables matching the GraphQL mutation`
          );
        }

        const { id, data } = params;

        if (!id) {
          throw new Error(`${entityName}.update requires an "id" field`);
        }

        if (!data || typeof data !== 'object') {
          throw new Error(
            `${entityName}.update requires a "data" object with the fields to update`
          );
        }
        
        const vars = { id, ...data };

        return fn(dataConnect, vars);

      },
    }),
    
    
    // delete
    ...(ops.delete && {
      delete: async (params) => {
        const fn = dcSdk[ops.delete];
        if (typeof fn !== 'function') {
          throw new Error(
            `Data Connect operation "${ops.delete}" not found for entity "${entityName}".`
          );
        }

        if (!params || typeof params !== 'object') {
          throw new Error(
            `${entityName}.delete expects an object like { id }`
          );
        }

        const { id } = params;

        if (!id) {
          throw new Error(`${entityName}.delete requires an "id" field`);
        }

        // Data Connect solo espera { id } como variables
        return fn(dataConnect, { id });
      },
    }),


    // filter
    ...(ops.filter && {
      filter: async (params) => {
        const fn = dcSdk[ops.filter];
        if (typeof fn !== 'function') {
          throw new Error(
            `Data Connect operation "${ops.filter}" not found for entity "${entityName}".`
          );
        }

        if (!params) {
          if (ops.list) {//if no params, call to list()
            const listFn = dcSdk[ops.list];
            if (typeof listFn !== 'function') {
              throw new Error(
                `Data Connect operation "${ops.list}" not found for entity "${entityName}".`
              );
            }
            return listFn(dataConnect);
          }
          throw new Error(`${entityName}.filter expects params or a list operation`);
        }
        const rawFilters = params.filters ?? params;
        const variables = {};

        for (const [key, value] of Object.entries(rawFilters)) {//cleaning undefined/null/'' values
          if (value !== undefined && value !== null && value !== '') {
            variables[key] = value;
          }
        }

        // if no valid filters, call to list()
        if (Object.keys(variables).length === 0) {
          if (ops.list) {
            const listFn = dcSdk[ops.list];
            if (typeof listFn !== 'function') {
              throw new Error(
                `Data Connect operation "${ops.list}" not found for entity "${entityName}".`
              );
            }
            return listFn(dataConnect);
          }
          throw new Error(`${entityName}.filter received no valid filters and no list operation`);
        }

        return fn(dataConnect, variables);
      },
    }),

  };
});


// --- Main SDK Export ---
export const krowSDK = {
  auth: authModule,
  integrations: {
    Core: coreIntegrationsModule,
  },
  entities: entitiesModule,
};
