require_relative '../../../services/sql-api/sql_api'
require_relative '../../../app/controllers/carto/controller_helper'

module Carto
  class DataLibraryService
    # - source_api_key is used to retrieve metadata from the dataset
    # - granted_api_key is stored as the one to use for the importing
    def load_dataset!(carto_api_client,
                      source_dataset:, source_username:, source_api_key:,
                      target_username:, granted_api_key:, format: 'gpkg')
      target_user = Carto::User.find_by_username(target_username)
      raise Carto::LoadError.new("User not found: #{target_username}") unless target_user

      remote_visualization = carto_api_client.get_visualization_v1(
        username: source_username, name: source_dataset, params: { api_key: source_api_key }
      )
      remote_table = remote_visualization[:table]
      privacy = target_user.default_dataset_privacy
      remote_attributes = remote_visualization.slice(:name, :description, :tags, :license, :source, :attributions)

      base_url = "#{carto_api_client.scheme}://#{carto_api_client.base_url(source_username)}"
      sql_api_url = CartoDB::SQLApi.with_username_api_key(source_username, granted_api_key, privacy, base_url: base_url)
                                   .export_table_url(source_dataset, format)
      external_source = Carto::ExternalSource.new(
        import_url: sql_api_url,
        rows_counted: remote_table[:row_count],
        size: remote_table[:size],
        geometry_types: remote_table[:geometry_types],
        username: source_username
      )
      visualization = Carto::Visualization.create!(
        remote_attributes.merge(
          display_name: display_name(remote_visualization),
          user: target_user,
          type: Carto::Visualization::TYPE_REMOTE,
          privacy: privacy,
          external_source: external_source
        )
      )

      visualization
    end

    def load_datasets!(carto_api_client,
                       source_username:, source_api_key:,
                       target_username:, granted_api_key:, format: 'gpkg')
      api_keys = carto_api_client.get_api_keys_v3(username: source_username, params: { api_key: granted_api_key })
      api_key = api_keys[:result].find { |key| key[:token] == granted_api_key }

      return unless api_key

      database_grants = api_key[:grants].select { |g| g[:type] == 'database' }
      database_grants.each do |database_grant|
        tables = database_grant[:tables]
        tables.each do |table|
          if table[:permissions].include?('select')
            load_dataset!(carto_api_client,
                          source_dataset: table[:name],
                          source_username: source_username, source_api_key: source_api_key,
                          target_username: target_username, granted_api_key: granted_api_key,
                          format: format)
          end
        end
      end
    end

    private

    def display_name(remote_visualization)
      remote_visualization[:display_name].presence || remote_visualization[:name]
    end
  end
end
