# frozen_string_literal: true

require "rails_helper"

RSpec.describe GraphqlController, type: :controller do
  let!(:app) do
    FactoryBot.create(:app)
  end

  let!(:user) do
    app.add_user(email: "test@test.cl")
  end

  let!(:agent_role) do
    app.add_agent(
      { email: "test2@test.cl" },
      bot: nil,
      role_attrs: { access_list: ["manage"], role: "admin" }
    )
  end

  let!(:unprivileged_agent_role) do
    app.add_agent(
      {
        email: "test3@test.cl",
        bot: nil
      }
    )
  end

  let(:app_package) do
    AppPackage.find_by(name: "Slack")
  end

  before do
    AppPackagesCatalog.update_all
    @graphql_client = GraphQL::TestClient.new
    @graphql_client.get_actions
  end

  context "privileged" do
    before :each do
      stub_current_user(agent_role)

      allow_any_instance_of(Plan).to receive(
        :allow_feature!
      ).and_return(true)
    end

    describe "add package" do
      it "return app" do
        expect do
          graphql_post(@graphql_client.data_for(
                         type: "CREATE_INTEGRATION", variables: {
                           appKey: app.key,
                           appPackage: app_package.name,
                           params: {
                             api_secret: "123455",
                             api_key: "asd",
                             slack_channel_name: "chan1",
                             slack_channel_name_leads: "chan1"
                           }
                         }
                       ))
        end.to change { app.app_package_integrations.count }.by(1)

        expect(graphql_response.errors).to be_nil
      end

      it "unprivileged" do
        # unprivileged_agent_role
      end
    end

    describe "add package with errors" do
      it "return app" do
        app_package.update(definitions: [
                             {
                               name: "api_key",
                               label: "App ID",
                               type: "string",
                               required: true
                             },
                             {
                               name: "api_secret",
                               label: "Client Secret",
                               type: "string",
                               required: true
                             }
                           ])
        expect do
          graphql_post(@graphql_client.data_for(
                         type: "CREATE_INTEGRATION",
                         variables: {
                           appKey: app.key,
                           appPackage: app_package.name,
                           params: {
                             api_key: "asd"
                           }
                         }
                       ))
        end.to_not change { app.app_package_integrations.count }

        expect(graphql_response.errors).to be_nil
        expect(graphql_response.data.integrationsCreate.errors.api_secret).to be_present
      end
    end

    describe "update package" do
      before :each do
        graphql_post(@graphql_client.data_for(type: "CREATE_INTEGRATION", variables: {
                                                appKey: app.key,
                                                appPackage: app_package.name,
                                                params: {
                                                  api_secret: "123455",
                                                  api_key: "asd",
                                                  slack_channel_name: "chan1",
                                                  slack_channel_name_leads: "chan1"
                                                }
                                              }))
      end

      it "created in app" do
        graphql_post(@graphql_client.data_for(type: "UPDATE_INTEGRATION", variables: {
                                                appKey: app.key,
                                                id: app.app_package_integrations.first.id.to_s,
                                                params: {
                                                  api_secret: "123455",
                                                  api_key: "asd",
                                                  slack_channel_name: "chan1",
                                                  slack_channel_name_leads: "chan1"
                                                }
                                              }))
        expect(graphql_response.data.integrationsUpdate.integration.name).to be_present
        expect(graphql_response.data.integrationsUpdate.integration.id).to be_present
        expect(graphql_response.data.integrationsUpdate.integration.settings).to be_present
      end

      it "delete in app" do
        expect do
          graphql_post(@graphql_client.data_for(type: "DELETE_INTEGRATION", variables: {
                                                  appKey: app.key,
                                                  id: app.app_package_integrations.first.id.to_s
                                                }))
        end.to change { app.app_package_integrations }.by([])

        expect(graphql_response.data.integrationsDelete.integration.name).to be_present
        expect(graphql_response.data.integrationsDelete.integration.id).to be_present
      end
    end

    describe "queries app_packages" do
      it "will return list of app packages" do
        app_package
        graphql_post(@graphql_client.data_for(type: "APP_PACKAGES", variables: {
                                                appKey: app.key
                                              }))
        expect(graphql_response.data.app.appPackages).to be_present
      end
    end
  end

  context "unprivileged" do
    before :each do
      stub_current_user(unprivileged_agent_role)

      allow_any_instance_of(Plan).to receive(
        :allow_feature!
      ).and_return(true)
    end

    describe "add package" do
      it "return app" do
        expect do
          graphql_post(@graphql_client.data_for(type: "CREATE_INTEGRATION", variables: {
                                                  appKey: app.key,
                                                  appPackage: app_package.name,
                                                  params: {
                                                    api_secret: "123455",
                                                    api_key: "asd",
                                                    slack_channel_name: "chan1",
                                                    slack_channel_name_leads: "chan1"
                                                  }
                                                }))
        end.to_not change { app.app_package_integrations.count }
        expect(graphql_response.errors).to be_present
      end
    end

    describe "update package" do
      before :each do
        app.app_package_integrations.create(
          app_package: app_package,
          api_secret: "123455",
          api_key: "asd"
        )
      end

      it "created in app" do
        graphql_post(@graphql_client.data_for(type: "UPDATE_INTEGRATION", variables: {
                                                appKey: app.key,
                                                id: app.app_package_integrations.first.id,
                                                params: {
                                                  api_key: "123455",
                                                  api_secret: "123455",
                                                  slack_channel_name: "chan1",
                                                  slack_channel_name_leads: "chan1"
                                                }
                                              }))
        puts graphql_response
        expect(graphql_response.errors).to be_present
      end

      it "delete in app" do
        graphql_post(@graphql_client.data_for(type: "DELETE_INTEGRATION", variables: {
                                                appKey: app.key,
                                                id: app.app_package_integrations.first.id
                                              }))

        expect(graphql_response.errors).to be_present
      end
    end

    describe "queries app_packages" do
      it "will return list of app packages" do
        app_package

        graphql_post(@graphql_client.data_for(type: "APP_PACKAGES", variables: {
                                                appKey: app.key
                                              }))
        expect(graphql_response.errors).to_not be_blank
      end
    end
  end
end
