(ns auto-ap.integration.graphql.accounts
  (:require
   [auto-ap.datomic :refer [conn]]
   [auto-ap.graphql.accounts :as sut]
   [auto-ap.integration.util :refer [admin-token user-token wrap-setup]]
   [datomic.api :as dc]
   [clojure.test :as t :refer [deftest is testing use-fixtures]]))

(use-fixtures :each wrap-setup)

#_(deftest test-account-search

  (with-redefs [auto-ap.solr/impl (auto-ap.solr/->InMemSolrClient (atom {}))]
    (testing "It should find matching account names"
      @(dc/transact conn [{:account/name              "Food Research"
                           :db/ident                  :client-specific-account
                           :account/numeric-code      51100
                           :account/search-terms      "Food Research"
                           :account/applicability     :account-applicability/global
                           :account/default-allowance :allowance/allowed}])
      (sut/rebuild-search-index)
      (clojure.pprint/pprint auto-ap.solr/impl)
      (is (> (count (sut/search {:id (admin-token)}
                                {:query "Food Research"}
                                nil))
             0)))
    (testing "It should find exact matches by numbers"
      (is (= (count (sut/search {:id (admin-token)}
                                {:query "51100"}
                                nil))
             1)))
    (testing "It should filter out accounts that are not allowed for clients"
      @(dc/transact conn [{:account/name              "CLIENT SPECIFIC"
                           :db/ident                  :client-specific-account
                           :account/numeric-code      99999
                           :account/search-terms      "CLIENTSPECIFIC"
                           :account/applicability     :account-applicability/customized
                           :account/default-allowance :allowance/allowed}])
      (sut/rebuild-search-index)
      (is (= [] (sut/search {:id (admin-token)}
                            {:query "CLIENTSPECIFIC"}
                            nil)))

      (testing "It should show up for the client specific version"
        (let [client-id (-> @(dc/transact conn [{:client/name "CLIENT"
                                                 :db/id       "client"}
                                                {:db/ident                 :client-specific-account
                                                 :account/client-overrides [{:account-client-override/client       "client"
                                                                             :account-client-override/name         "HI"
                                                                             :account-client-override/search-terms "HELLOWORLD"}]}])
                            :tempids
                            (get "client"))]
          (sut/rebuild-search-index)
          (is (= 1 (count (sut/search {:id (admin-token)}
                                      {:query "HELLOWORLD"
                                       :client_id client-id}
                                      nil))))))

      (testing "It should hide accounts that arent applicable"
        @(dc/transact conn [{:account/name              "DENIED"
                             :db/ident                  :denied-account
                             :account/numeric-code      99998
                             :account/search-terms      "DENIED"
                             :account/applicability     :account-applicability/global
                             :account/default-allowance :allowance/denied
                             :account/vendor-allowance  :allowance/denied
                             :account/invoice-allowance :allowance/denied}])
        (is (= 0 (count (sut/search {:id (admin-token)}
                                    {:query "DENIED"}
                                    nil))))
        (is (= 0 (count (sut/search {:id (admin-token)}
                                    {:query "DENIED"
                                     :allowance :invoice}
                                    nil))))
        (is (= 0 (count (sut/search {:id (admin-token)}
                                    {:query "DENIED"
                                     :allowance :vendor}
                                    nil)))))

      (testing "It should warn when using a warn account"
        @(dc/transact conn [{:account/name              "WARNING"
                             :db/ident                  :warn-account
                             :account/numeric-code      99997
                             :account/search-terms      "WARNING"
                             :account/applicability     :account-applicability/global
                             :account/default-allowance :allowance/warn
                             :account/vendor-allowance  :allowance/warn
                             :account/invoice-allowance :allowance/warn}])
        (sut/rebuild-search-index)
        (is (some? (:warning (first (sut/search {:id (admin-token)}
                                                {:query     "WARNING"
                                                 :allowance :global}
                                                nil)))))
        (is (some? (:warning (first (sut/search {:id (admin-token)}
                                                {:query     "WARNING"
                                                 :allowance :invoice}
                                                nil)))))
        (is (some? (:warning (first (sut/search {:id (admin-token)}
                                                {:query     "WARNING"
                                                 :allowance :vendor}
                                                nil))))))
      (testing "It should only include admin accounts for admins"
        @(dc/transact conn [{:account/name              "ADMINONLY"
                             :db/ident                  :warn-account
                             :account/numeric-code      99997
                             :account/search-terms      "ADMINONLY"
                             :account/applicability     :account-applicability/global
                             :account/default-allowance :allowance/admin-only
                             :account/vendor-allowance  :allowance/admin-only
                             :account/invoice-allowance :allowance/admin-only}])
        (sut/rebuild-search-index)
        (is (= 1 (count (sut/search {:id (admin-token)}
                                    {:query "ADMINONLY"}
                                    nil))))
        (is (= 0 (count (sut/search {:id (user-token)}
                                    {:query "ADMINONLY"}
                                    nil)))))

      (testing "It should allow searching for vendor accounts for invoices"
        (let [vendor-id (-> @(dc/transact conn [{:account/name              "VENDORONLY"
                                                 :db/id                     "vendor-only"
                                                 :db/ident                  :vendor-only
                                                 :account/numeric-code      99996
                                                 :account/search-terms      "VENDORONLY"
                                                 :account/applicability     :account-applicability/global
                                                 :account/default-allowance :allowance/allowed
                                                 :account/vendor-allowance  :allowance/allowed
                                                 :account/invoice-allowance :allowance/denied}
                                                {:vendor/name            "Allowed"
                                                 :vendor/default-account "vendor-only"
                                                 :db/id                  "vendor"}])
                            :tempids
                            (get "vendor"))]
          (sut/rebuild-search-index)
          (is (= 0 (count (sut/search {:id (admin-token)}
                                      {:query     "VENDORONLY"
                                       :allowance :invoice}
                                      nil))))

          (is (= 1 (count (sut/search {:id (admin-token)}
                                      {:query     "VENDORONLY"
                                       :allowance :invoice
                                       :vendor_id vendor-id}
                                      nil)))))))

    (deftest get-graphql
      (testing "should retrieve a single account"
        @(dc/transact conn [{:account/numeric-code      1
                             :account/default-allowance :allowance/allowed
                             :account/type              :account-type/asset
                             :account/location          "A"
                             :account/name              "Test"}])

        (is (= {:name              "Test",
                :invoice_allowance nil,
                :numeric_code      1,
                :vendor_allowance  nil,
                :location          "A",
                :applicability     nil}
               (dissoc (first (:accounts (sut/get-graphql {:id (admin-token)} {} nil)))
                       :id
                       :type
                       :default_allowance)))))))

#_(deftest upsert-account
  (testing "should create a new account"
    (let [result (sut/upsert-account {:id (admin-token)} {:account {:client_overrides  []
                                                                    :numeric_code      123
                                                                    :location          "A"
                                                                    :applicability     :global
                                                                    :account-set       "global"
                                                                    :name              "Test"
                                                                    :invoice-allowance :allowed
                                                                    :vendor-allowance  :allowed
                                                                    :type              :asset}} nil)]
      (is (= {:search_terms      "Test",          
              :name              "Test",
              :invoice_allowance :allowed,
              :numeric_code      123,
              :code              "123",
              :account_set       "global",
              :vendor_allowance  :allowed,
              :location          "A",
              :applicability     :global}
             (dissoc result
               :id
               :type
               :default_allowance)))
      (testing "Should allow updating account"
        (let [edit-result (sut/upsert-account {:id (admin-token)} {:account {:client_overrides  []
                                                                             :id (:id result)
                                                                             :numeric_code      890
                                                                             :location          "B"
                                                                             :applicability     :global
                                                                             :account-set       "global"
                                                                             :name              "Hello"
                                                                             :invoice-allowance :denied
                                                                             :vendor-allowance  :denied
                                                                             :type              :expense}} nil)]
          (is (= {:search_terms      "Hello",          
                  :name              "Hello",
                  :invoice_allowance :denied,
                  :code              "123",
                  :account_set       "global",
                  :vendor_allowance  :denied,
                  :location          "B",
                  :applicability     :global}
                 (dissoc edit-result
                         :id
                         :type
                         :default_allowance
                         :numeric_code)))
          (testing "Should not allow changing numeric code"

            (is (= 123 (:numeric_code edit-result)))))))))
