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 () => {
    // 1. Firebase auth user
    const fbUser = auth.currentUser;

    if (!fbUser) {
      return null; // NO ESTÁ LOGGEADO
    }

    // 2. Attempt to load matching Krow User from DataConnect
    // (because your Krow user metadata is stored in the "users" table)
    let krowUser = null;
    try {
      const response = await dcSdk.getUserById(dataConnect, { id: fbUser.uid });
      krowUser = response.data?.user || null;
    } catch (err) {
      console.warn("Krow user not found in DataConnect, returning Firebase-only info.");
    }

    // 3. Build unified "me" object
    return {
      id: fbUser.uid,
      email: fbUser.email,
      fullName: krowUser?.fullName || fbUser.displayName || null,
      role: krowUser?.role || "user",
      user_role: krowUser?.userRole || null,
      firebase: fbUser,
      krow: krowUser
    };
  },

  /**
   * 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;
  },
};

const dataconnectEntityConfig = {
  User: {
    list: 'listUsers',
    get: 'getUserById',
    create: 'createUser',
    update: 'updateUser',
    delete: 'deleteUser',
    filter: 'filterUsers',
  },
  Event: {
    list: 'listEvents',
    create: 'createEvent',
    get: 'getEventById',
    update: 'updateEvent',
    delete: 'deleteEvent',
    filter: 'filterEvents',
  },

  Staff: {
    list: 'listStaff',
    create: 'createStaff',
    get: 'getStaffById',
    update: 'updateStaff',
    delete: 'deleteStaff',
    filter: 'filterStaff',
  },

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

  VendorRate: {
    list: 'listVendorRate',
    get: 'getVendorRateById',
    create: 'createVendorRate',
    update: 'updateVendorRate',
    delete: 'deleteVendorRate',
    filter: 'filterVendorRates',
  },
  
  VendorDefaultSetting:{
    list: 'listVendorDefaultSettings',
    get: 'getVendorDefaultSettingById',
    create: 'createVendorDefaultSetting',
    update: 'updateVendorDefaultSetting',
    delete: 'deleteVendorDefaultSetting',
    filter: 'filterVendorDefaultSettings',
  },

  Invoice:{
    list: 'listInvoice',
    get: 'getInvoiceById',
    create: 'createInvoice',
    update: 'updateInvoice',
    delete: 'deleteInvoice',
    filter: 'filterInvoices',

  },
  
  Business:{
    list: 'listBusiness',
    get: 'getBusinessById',
    create: 'createBusiness',
    update: 'updateBusiness',
    delete: 'deleteBusiness',
    filter: 'filterBusiness',
  },

  Certification:{
    list: 'listCertification',
    get: 'getCertificationById',
    create: 'createCertification',
    update: 'updateCertification',
    delete: 'deleteCertification',
    filter: 'filterCertification',
  },
  
  Team:{
    list: 'listTeam',
    get: 'getTeamById',
    create: 'createTeam',
    update: 'updateTeam',
    delete: 'deleteTeam',
    filter: 'filterTeam',
  },

  TeamMember: {
    list: 'listTeamMember',
    get: 'getTeamMemberById',
    create: 'createTeamMember',
    update: 'updateTeamMember',
    delete: 'deleteTeamMember',
    filter: 'filterTeamMember',
  },

  TeamHub: {
    list: 'listTeamHub',
    get: 'getTeamHubById',
    create: 'createTeamHub',
    update: 'updateTeamHub',
    delete: 'deleteTeamHub',
    filter: 'filterTeamHub',
  },

  TeamMemberInvite: {
    list: 'listTeamMemberInvite',
    get: 'getTeamMemberInviteById',
    create: 'createTeamMemberInvite',
    update: 'updateTeamMemberInvite',
    delete: 'deleteTeamMemberInvite',
    filter: 'filterTeamMemberInvite',
  },
  
  Conversation:{
    list: 'listConversation',
    get: 'getConversationById',
    create: 'createConversation',
    update: 'updateConversation',
    delete: 'deleteConversation',
    filter: 'filterConversation',
  }, 
  
  Message:{
    list: 'listMessage',
    get: 'getMessageById',
    create: 'createMessage',
    update: 'updateMessage',
    delete: 'deleteMessage',
    filter: 'filterMessage',
  }, 
  
  ActivityLog:{
    list: 'listActivityLog',
    get: 'getActivityLogById',
    create: 'createActivityLog',
    update: 'updateActivityLog',
    delete: 'deleteActivityLog',
    filter: 'filterActivityLog',
  },

  Enterprise:{
    list: 'listEnterprise',
    get: 'getEnterpriseById',
    create: 'createEnterprise',
    update: 'updateEnterprise',
    delete: 'deleteEnterprise',
    filter: 'filterEnterprise',
  }, 
  
  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,
};
