lib/wolf_core/infrastructure/fkm_operations.rb



module WolfCore
  module FkmOperations
    include WolfCore::HttpOperations
    include WolfCore::ExceptionOperations
    include WolfCore::LoggingUtils

    def get_foreign_key_destination_id(tenant:, source:, source_id:, destination:)
      foreign_key = get_foreign_key_by_destination(
        tenant: tenant, source: source, source_id: source_id,
        destination: destination
      )
      foreign_key&.dig("destination_id")
    end

    def get_foreign_key_by_destination(tenant:, source:, source_id:, destination:)
      foreign_keys = get_foreign_keys(tenant: tenant, source: source, source_id: source_id)
      foreign_keys.find { |fk| fk["destination"] == destination }
    end

    def get_foreign_keys(tenant:, source:, source_id:)
      response = http_get(
        url: "#{ENV["FKM_URL"]}/Prod/lookup?tenant=#{tenant}&source=#{source}&source_id=#{source_id}"
      )
      response = parse_http_response(response)
      log_object response, title: "get_foreign_keys response is"
      validate_http_response(response: response, message: "Error getting foreign keys")
      response.body
    end

    def get_foreign_keys_by_destination(tenant:, destination:, destination_id:)
      response = http_get(
        url: "#{ENV["FKM_URL"]}/Prod/lookup?tenant=#{tenant}&destination=#{destination}&destination_id=#{destination_id}"
      )
      response = parse_http_response(response)
      log_object response, title: "get_foreign_keys_by_destination response is"
      validate_http_response(response: response, message: "Error getting foreign keys by destination id")
      response.body
    end

    def create_foreign_key(tenant:, source:, source_id:, destination:, destination_id:)
      raise_service_error({ message: "tenant is required to create a foreign key", tenant: tenant }) if tenant.blank?
      raise_service_error({ message: "source is required to create a foreign key", source: source }) if source.blank?
      if source_id.blank?
        raise_service_error({ message: "source_id is required to create a foreign key",
                              source_id: source_id })
      end
      if destination.blank?
        raise_service_error({ message: "destination is required to create a foreign key",
                              destination: destination })
      end
      if destination_id.blank?
        raise_service_error({ message: "destination_id is required to create a foreign key",
                              destination_id: destination_id })
      end
      response = http_post(
        url: "#{ENV["FKM_URL"]}/Prod/create",
        body: {
          tenant: tenant,
          source: source,
          source_id: source_id,
          destination: destination,
          destination_id: destination_id
        }
      )
      response = parse_http_response(response)
      log_object response, title: "create_foreign_key response is"
      validate_http_response(response: response, message: "Error creating foreign key")
      parse_http_response(response).body
    end

    def find_or_create_foreign_key(tenant:, source:, source_id:, destination:, destination_id:)
      found_destination_id = get_foreign_key_destination_id(
        tenant: tenant, source: source, source_id: source_id,
        destination: destination
      )
      log_object "find_or_create_foreign_key found_destination_id is #{found_destination_id}"
      return Result.success(data: { operation: :find }) if found_destination_id.present?

      create_foreign_key(
        tenant: tenant, source: source, source_id: source_id,
        destination: destination, destination_id: destination_id
      )
      Result.success(data: { operation: :create })
    end

    def upsert_foreign_key(tenant:, auth_token:, source:, source_id:, destination:, destination_id:)
      foreign_key = get_foreign_key_by_destination(
        tenant: tenant, source: source, source_id: source_id,
        destination: destination
      )
      if foreign_key.present?
        update_foreign_key(
          tenant: tenant, auth_token: auth_token, uuid: foreign_key["uuid"],
          source: source, source_id: source_id,
          destination: destination, destination_id: destination_id
        )
      else
        create_foreign_key(
          tenant: tenant, source: source, source_id: source_id,
          destination: destination, destination_id: destination_id
        )
      end
    end

    def update_foreign_key(tenant:, auth_token:, uuid:, source: nil, source_id: nil, destination: nil,
                           destination_id: nil)
      raise_service_error({ message: "tenant is required to update a foreign key", tenant: tenant }) if tenant.blank?
      if auth_token.blank?
        raise_service_error({ message: "auth_token is required to update a foreign key",
                              auth_token: auth_token })
      end
      raise_service_error({ message: "uuid is required to update a foreign key", uuid: uuid }) if uuid.blank?

      fields_to_update = {
        source: source,
        source_id: source_id,
        destination: destination,
        destination_id: destination_id
      }.compact

      if fields_to_update.blank?
        raise_service_error({ message: "At least one field to update is required to update a foreign key",
                              source: source })
      end

      body = {
        tenant: tenant,
        authentication_token: auth_token,
        uuid: uuid
      }.merge(fields_to_update)
      log_object body, title: "update_foreign_key body is"

      response = safe_http_put(
        url: "#{ENV["FKM_URL"]}/Prod/update",
        body: body,
        title: "update_foreign_key response is",
        error_message: "Error updating foreign key"
      )
      response.body
    end
  end
end