(ns auto-ap.routes.auth
  (:require [auto-ap.datomic.users :as users]
            [buddy.sign.jwt :as jwt]
            [clj-http.client :as http]
            [clj-time.core :as time]
            [compojure.core :refer [GET defroutes]]
            [config.core :refer [env]]
            [clojure.tools.logging :as log]))

(def google-client-id "264081895820-0nndcfo3pbtqf30sro82vgq5r27h8736.apps.googleusercontent.com")
(def google-client-secret "OC-WemHurPXYpuIw5cT-B90g")

(defn make-api-token []
  (jwt/sign {:user "API"
             :exp (time/plus (time/now) (time/days 1000))
             :user/role "admin"
             :user/name "API"}
            (:jwt-secret env)
            {:alg :hs512}))

(defroutes routes
  (GET "/oauth" {{:strs [code]} :query-params :keys [scheme] :as r {:strs [host]} :headers}
       (try
         (let [auth (-> "https://accounts.google.com/o/oauth2/token"
                        (http/post 
                         {:form-params {"client_id" google-client-id
                                        "client_secret" google-client-secret
                                        "code" code
                                        "redirect_uri" (str (:scheme env) "://" host  "/api/oauth")
                                        "grant_type" "authorization_code"}
                          :as :json})
                        :body)
               token (:access_token auth)
               profile (-> (http/get "https://www.googleapis.com/oauth2/v1/userinfo"
                                     {:headers {"Authorization" (str "Bearer " token)} :as :json})
                           :body)
               user (users/find-or-insert! {:user/provider "google"
                                            :user/provider-id (:id profile)
                                            :user/role :user-role/none
                                            :user/name (:name profile)})
               ]
           (log/info "authenticated as user" user)
           
           ;; TODO - these namespaces are not being transmitted/deserialized properly
           (if (and token user)
             (let [jwt (jwt/sign {:user (:name profile)
                                  :exp (time/plus (time/now) (time/days 30))
                                  :user/clients (map (fn [c]
                                                       (dissoc c :client/bank-accounts :client/location-matches :client/forecasted-transactions :client/matches :client/week-a-debits :client/week-a-credits :client/week-b-debits :client/week-b-credits :client/signature-file :client/address))
                                                     (:user/clients user))
                                  :user/role (name (:user/role user))
                                  :user/name (:name profile)}
                                 (:jwt-secret env)
                                 {:alg :hs512})]
               
               {:status 301
                :headers {"Location" (str "/?jwt=" jwt)}})
             {:status 401
              :body "Couldn't authenticate"}))
         (catch Exception e
           (log/warn e )
           {:status 401
            :body (str "Couldn't authenticate "  (.toString e))}))))
