(ns auto-ap.yodlee.core
  (:require [clj-http.client :as client]
            [clojure.data.json :as json]
            [config.core :refer [env]]))

(defn auth-header
  ([cob-session] (str "{cobSession=" cob-session "}"))
  ([cob-session user-session] (str "{cobSession=" cob-session ",userSession=" user-session "}")))

(def base-headers {"Api-Version" "1.1"
                   "Cobrand-Name" (:yodlee-cobrand-name env) 
                   "Content-Type" "application/json"})

(defn login-cobrand []
  (-> (str (:yodlee-base-url env) "/cobrand/login") 
   (client/post {:headers base-headers
                 :body
                 (json/write-str {:cobrand {:cobrandLogin (:yodlee-cobrand-login env)
                                            :cobrandPassword  (:yodlee-cobrand-password env)
                                            :locale "en_US"}}) 
                 :as :json}
                )
   :body
   :session
   :cobSession))


(defn login-user [cob-session]
  (-> (str (:yodlee-base-url env) "/user/login")
      (client/post {:headers (merge base-headers {"Authorization" (auth-header cob-session)})
                 :body
                 (json/write-str {:user {:loginName (:yodlee-user-login env) 
                                         :password (:yodlee-user-password env) 
                                         :locale "en_US"}}) 
                 :as :json})
   :body
   :user
   :session
   :userSession))

(defn get-accounts []
  (let [cob-session (login-cobrand)
        user-session (login-user cob-session)]
    (-> (str (:yodlee-base-url env) "/accounts") 
        (client/get {:headers (merge base-headers {"Authorization" (auth-header cob-session user-session)}) 
                     :as :json})
        :body
        :account)))

(defn get-account [i]
  (let [cob-session (login-cobrand)
        user-session (login-user cob-session)]
    (-> (str (:yodlee-base-url env) (str "/accounts/" i)) 
        (client/get {:headers (merge base-headers {"Authorization" (auth-header cob-session user-session)}) 
                     :as :json})
        :body
        :account)))

(defn get-provider-accounts []
  (let [cob-session (login-cobrand)
        user-session (login-user cob-session)]
    (-> (str (:yodlee-base-url env) "/providerAccounts") 
        (-> (client/get {:headers (merge base-headers {"Authorization" (auth-header cob-session user-session)})
                         :as :json})
            :body
            :providerAccount)
        )))

(defn get-transactions []
  (let [cob-session (login-cobrand)
        user-session (login-user cob-session)
        batch-size 100
        get-transaction-batch (fn [skip]
                                (-> (str (:yodlee-base-url env) "/transactions?top=" batch-size "&skip=" skip) 
                                    (doto println)

                                    (client/get {:headers (doto
                                                              (merge base-headers {"Authorization" (auth-header cob-session user-session)})
                                                            println) 
                                                 :as :json})
                                    :body
                                    :transaction
                                    ))]

    (loop [transactions [] 
           skip 0]
      (let [transaction-batch (get-transaction-batch skip)]
        (if (seq transaction-batch)
          (recur (concat transactions transaction-batch) (+ batch-size skip))
          transactions)))))

(defn get-provider-accounts []
  (let [cob-session (login-cobrand)
        user-session (login-user cob-session)
        batch-size 100]

    (-> (str (:yodlee-base-url env) "/providerAccounts") 

        (client/get {:headers (doto
                                  (merge base-headers {"Authorization" (auth-header cob-session user-session)})
                                println) 
                     :as :json})
        :body
        :providerAccount
        )))



(defn get-provider-account [id]
  (let [cob-session (login-cobrand)
        user-session (login-user cob-session)
        batch-size 100]

    (-> (str (:yodlee-base-url env) "/providerAccounts/" id) 

        (client/get {:headers (doto
                                  (merge base-headers {"Authorization" (auth-header cob-session user-session)})
                                println) 
                     :as :json})
        :body
        :providerAccount)))

(defn update-provider-account [pa]
  (let [cob-session (login-cobrand)
        user-session (login-user cob-session)
        batch-size 100]

    (-> (str (:yodlee-base-url env) "/providerAccounts?providerAccountIds=" pa) 

        (client/put {:headers (doto
                                  (merge base-headers {"Authorization" (auth-header cob-session user-session)})
                                println) 
                     :body "{\"dataSetName\": [\"BASIC_AGG_DATA\"]}"
                     :as :json}))))

(defn update-yodlee [id]
  (update-provider-account (:providerAccountId (first (filter #(= (:id %) id)  (get-accounts)))))
  (get-provider-account (:providerAccountId (first (filter #(= (:id %) id)  (get-accounts))))))

(defn get-specific-transactions [account]
  (let [cob-session (login-cobrand)
        user-session (login-user cob-session)
        batch-size 100
        get-transaction-batch (fn [skip]
                                (-> (str (:yodlee-base-url env) "/transactions?top=" batch-size "&skip=" skip "&accountId=" account) 
                                    (doto println)

                                    (client/get {:headers (doto
                                                              (merge base-headers {"Authorization" (auth-header cob-session user-session)})
                                                            println) 
                                                 :as :json})
                                    :body
                                    :transaction
                                    ))]

    (loop [transactions [] 
           skip 0]
      (let [transaction-batch (get-transaction-batch skip)]
        (if (seq transaction-batch)
          (recur (concat transactions transaction-batch) (+ batch-size skip))
          transactions)))))

(defn get-access-token []
  (let [cob-session (login-cobrand)
        user-session (login-user cob-session)
        token (->  
                (str (:yodlee-base-url env) "/user/accessTokens?appIds=" 10003600)

                (client/get 
                 {:headers (merge base-headers {"Authorization" (auth-header cob-session user-session)}) 
                  :as :json})
                :body
                :user
                :accessTokens
                first
                :value
                )]
    [user-session token]))

(defn create-user []
  (let [cob-session (login-cobrand)]
    (-> (str (:yodlee-base-url env) "/user/register") 
        (client/post {:headers (merge base-headers {"Authorization" (auth-header cob-session)}) 
                      :body (json/write-str {:user {:loginName "brycesPersoonal2"
                                                    :password "kV@mdv3TU11"
                                                    :email "yodleepersonal2@brycecovertoperations.com"}})
                     :as :json})
        :body)))

#_(defn get-users []
  (let [cob-session (login-cobrand)]
    (-> "https://developer.api.yodlee.com/ysl/user" 
        (client/get {:headers (merge base-headers {"Authorization" (auth-header cob-session)}) 
                     :as :json})
        :body)))
