(ns auto-ap.ssr.company.yodlee
  (:require
   [auto-ap.datomic
    :refer [add-sorter-fields apply-pagination apply-sort-3 conn merge-query
            pull-attr pull-many query2]]
   [auto-ap.graphql.utils :refer [assert-can-see-client is-admin?]]
   [auto-ap.permissions :refer [wrap-must]]
   [auto-ap.query-params :refer [wrap-copy-qp-pqp]]
   [auto-ap.routes.utils :refer [wrap-client-redirect-unauthenticated
                                 wrap-secure]]
   [auto-ap.ssr-routes :as ssr-routes]
   [auto-ap.ssr.components :as com]
   [auto-ap.ssr.grid-page-helper :as helper :refer [wrap-apply-sort]]
   [auto-ap.ssr.svg :as svg]
   [auto-ap.ssr.utils :refer [apply-middleware-to-all-handlers
                              default-grid-fields-schema entity-id
                              html-response modal-response wrap-merge-prior-hx
                              wrap-schema-enforce]]
   [auto-ap.time :as atime]
   [auto-ap.yodlee.core2 :as yodlee]
   [bidi.bidi :as bidi]
   [config.core :refer [env]]
   [datomic.api :as dc]
   [hiccup2.core :as hiccup]
   [malli.core :as mc]))

(def default-read '[:db/id
                    [:yodlee-provider-account/last-updated :xform clj-time.coerce/from-date]
                    :yodlee-provider-account/status
                    :yodlee-provider-account/id
                    :yodlee-provider-account/detailed-status
                    {:yodlee-provider-account/accounts [:yodlee-account/name :yodlee-account/number]
                     :yodlee-provider-account/client   [:client/code]}])

(def query-schema (mc/schema
                   [:maybe 
                           (into [:map {}
                                  [:client-id {:optional true} [:maybe entity-id]] ]
                                 default-grid-fields-schema)]))

(defn fetch-ids [db request]
  (let [query-params (:query-params request)
        query (cond-> {:query {:find []
                          :in ['$ '[?xx ...]]
                          :where ['[?e :yodlee-provider-account/id]
                                  '[?e :yodlee-provider-account/client ?xx]]}
                  :args [db (:trimmed-clients request)]}


           (:sort query-params) (add-sorter-fields {"status" ['[?e :yodlee-provider-account/status ?sort-status]]
                                                    "client" ['[?e :yodlee-provider-account/client ?c]
                                                              '[?c :client/code ?sort-client]]
                                                    "provider-account" ['[?e :yodlee-provider-account/id ?sort-provider-account]]
                                                    "last-updated" ['[?e :yodlee-provider-account/last-updated ?sort-last-updated]]}
                                           query-params)
           true
           (merge-query {:query {:find  ['?e ]
                                 :where ['[?e :yodlee-provider-account/id]]}}))]
    (->> query

         (query2)
         (apply-sort-3 query-params)
         (apply-pagination query-params))))


(defn hydrate-results [ids db _]
  (let [results (->> (pull-many db default-read ids)
                     (group-by :db/id))]
    (->> ids
         (map results)
         (map first))))


(defn fetch-page [request]
  (let [db (dc/db conn)
        {ids-to-retrieve :ids matching-count :count} (fetch-ids db request)]
    [(->> (hydrate-results ids-to-retrieve db request))
     matching-count]))


(defn fastlink-dialog [{:keys [client]}]
  (modal-response
    (com/modal
      {}
      (com/modal-card
        {}
        [:div.flex [:div.p-2 "Yodlee Fastlink"] ]
        [:div
         [:div#fa-spot]
         [:script {:lang "text/javascript"}
          (hiccup/raw 
            (format "
fastlink.open({fastLinkURL: '%s',
               accessToken: '%s',
               params: {'configName': 'Aggregation'},
               onError: function(e) {
                   console.log(e);
                   htmx.trigger(\"#yodlee-table\", \"notification\", {value: \"Yodlee returned the following error: '\" + e.message + \"'.\\n\\nYou may want to refresh your browser and try again.\"});
                   setTimeout(hideModal, 300);
               }},
              'fa-spot');

" (:yodlee2-fastlink env) (yodlee/get-access-token (:client/code client))))]
         ]
        [:div]))))

(defn reauthenticate [{:keys [form-params identity]}]
  (assert-can-see-client identity (-> (dc/pull (dc/db conn) '[{:yodlee-provider-account/client [:db/id]}] (Long/parseLong (get form-params "id")))
                                      :yodlee-provider-account/client
                                      :db/id))
  (html-response
    (com/modal
      {}
      (com/modal-card
        {}
        [:div.flex [:div.p-2 "Yodlee Fastlink"] ]
        [:div
         [:div#fa-spot]
         [:script {:lang "text/javascript"}
          (hiccup/raw 
            (format "
fastlink.open({fastLinkURL: '%s',
               accessToken: '%s',
               params: {'configName': 'Aggregation',
                        'providerAccountId': %d,
                        'flow': 'edit'}},
              'fa-spot');

"
                    (:yodlee2-fastlink env)
                    (yodlee/get-access-token (-> (dc/pull (dc/db conn)
                                                          [{:yodlee-provider-account/client [:client/code]}]
                                                          (Long/parseLong (get form-params "id")))
                                                 :yodlee-provider-account/client
                                                 :client/code))
                    (pull-attr (dc/db conn) :yodlee-provider-account/id (Long/parseLong (get form-params "id")))))]]
        [:div]))))

(def grid-page
  (helper/build 
    {:id          "yodlee-table"
     :nav         com/company-aside-nav
     :id-fn       :db/id
     :fetch-page  fetch-page
     :breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes
                                             :company)}
                    "My Company"]
                   [:a {:href (bidi/path-for ssr-routes/only-routes
                                             :company-yodlee)}
                    "Yodlee"]]
     :title          "Yodlee Accounts"
     :entity-name    "Yodlee accounts"
                 :query-schema query-schema
     :route          :company-yodlee-table
     :action-buttons (fn [request]
                       [[:div.flex.flex-col.flex-shrink
                         [:div.flex-shrink 
                          (com/button {:color     :primary
                                       :on-click  "openFastlink()"
                                       :disabled  (if (:client request)
                                                    false
                                                    true)
                                       :hx-get    (bidi/path-for ssr-routes/only-routes
                                                                 :company-yodlee-fastlink-dialog)
                                       :hx-target "#modal-holder"}
                                      (com/button-icon {} svg/refresh)
                                      "Link new account")]
                         (when-not (:client request)
                           [:div.text-xs "Note: please select a specific customer to link a new account."])]])
     :row-buttons    (fn [request _]
                       [
                        (com/button {:hx-put    (bidi/path-for ssr-routes/only-routes
                                                               :company-yodlee-provider-account-reauthenticate)
                                     :color     :primary
                                     :hx-target "#modal-holder"}
                                    "Reauthenticate")
                        (when (is-admin? (:identity request))
                          (com/icon-button {:hx-put    (bidi/path-for ssr-routes/only-routes
                                                                      :company-yodlee-provider-account-refresh)
                                            :hx-target "closest tr"}
                                           svg/refresh))])
     :headers        [{:key      "client"
                       :name     "Client"
                       :sort-key "client"
                       :hide?    (fn [args]
                                   (= (count (:clients args)) 1))
                       :render   #(-> % :yodlee-provider-account/client :client/code)}
                      {:key      "provider-account"
                       :name     "Provider Account"
                       :sort-key "provider-account"
                       :render   :yodlee-provider-account/id}
                      {:key      "status"
                       :name     "Status"
                       :sort-key "status"
                       :render   #(when-let [status (:yodlee-provider-account/status %)] 
                                    (com/pill {:color (if (not= status "SUCCESS")
                                                        :yellow
                                                        :primary) }
                                              status))}
                      {:key      "detailed-status"
                       :name     "Detailed Status"
                       :sort-key "detailed-status"
                       :render   #(when-let [status (:yodlee-provider-account/detailed-status %)] 
                                    status)}

                      {:key      "last-updated"
                       :name     "Last Updated"
                       :sort-key "last-updated"
                       :render   #(atime/unparse-local (:yodlee-provider-account/last-updated %)
                                                       atime/normal-date)}
                      {:key           "accounts"
                       :name          "Accounts"
                       :show-starting "md"
                       :render        (fn [e]
                                        [:ul
                                         (for [a (:yodlee-provider-account/accounts e)]
                                           [:li (:yodlee-account/name a) " - " (:yodlee-account/number a)])])}]}))

(def page (helper/page-route grid-page))
(def table (helper/table-route grid-page))

(defn refresh-provider-account [{:keys [form-params identity]}]
  (let [provider-account (dc/pull (dc/db conn) default-read (some-> (get form-params "id") not-empty Long/parseLong))]
    (yodlee/refresh-provider-account (:client/code (:yodlee-provider-account/client provider-account))
                                     (:yodlee-provider-account/id provider-account))
    (html-response
      (helper/row*
        grid-page
        identity
        provider-account
        {:flash? true}))))


(def key->handler 
  (apply-middleware-to-all-handlers 
   {
    :company-yodlee                                 page
    :company-yodlee-table                           table
    :company-yodlee-fastlink-dialog                 fastlink-dialog
    }
   (fn [h]
      (-> h
          (wrap-copy-qp-pqp)
          (wrap-apply-sort grid-page)
          (wrap-merge-prior-hx)
          (wrap-schema-enforce :query-schema query-schema)
          (wrap-schema-enforce :hx-schema query-schema)
          (wrap-client-redirect-unauthenticated)
          (wrap-secure)))))