(ns todo.events
  (:require [clojure.string :as str]
            [re-frame.core :as rf]
            [todo.db :as db]
            [todo.fx]))

(rf/reg-event-fx
  :initialize-db
  (fn [_ _]
    {:db db/default-db
     :sqlite/init true}))

(rf/reg-event-db
  :todos-loaded
  (fn [db [_ rows]]
    (let [todos (->> rows
                     (map (fn [row]
                            (let [id (:id row)]
                              [id {:id id
                                   :title (:title row)
                                   :completed (= 1 (:completed row))
                                   :category (:category row)
                                   :priority (keyword (:priority row))
                                   :created-at (:created_at row)}])))
                     (into {}))]
      (assoc db :todos todos))))

(rf/reg-event-fx
  :add-todo
  (fn [{:keys [db]} [_ title category priority]]
    (when (seq (str/trim (or title "")))
      {:db (assoc db :show-form? false)
       :sqlite/insert {:title (str/trim title)
                       :category category
                       :priority (name priority)
                       :on-success [:todo-inserted title category priority]}})))

(rf/reg-event-db
  :todo-inserted
  (fn [db [_ title category priority id]]
    (assoc-in db [:todos id]
              {:id id
               :title (str/trim title)
               :completed false
               :category category
               :priority (keyword priority)
               :created-at (js/Math.floor (/ (.now js/Date) 1000))})))

(rf/reg-event-fx
  :toggle-todo
  (fn [{:keys [db]} [_ id]]
    (let [todo (get-in db [:todos id])
          new-completed (not (:completed todo))]
      {:db (assoc-in db [:todos id :completed] new-completed)
       :sqlite/toggle {:id id :completed new-completed}})))

(rf/reg-event-fx
  :update-todo
  (fn [{:keys [db]} [_ id title category priority]]
    {:db (-> db
             (assoc-in [:todos id :title] title)
             (assoc-in [:todos id :category] category)
             (assoc-in [:todos id :priority] priority)
             (assoc :show-form? false
                    :editing-todo nil))
     :sqlite/update {:id id :title title :category category :priority (name priority)}}))

(rf/reg-event-fx
  :delete-todo
  (fn [{:keys [db]} [_ id]]
    {:db (update db :todos dissoc id)
     :sqlite/delete {:id id}}))

(rf/reg-event-db
  :set-filter
  (fn [db [_ filter-val]]
    (assoc db :filter filter-val)))

(rf/reg-event-db
  :show-add-form
  (fn [db _]
    (assoc db :show-form? true :editing-todo nil)))

(rf/reg-event-db
  :show-edit-form
  (fn [db [_ todo]]
    (assoc db :show-form? true :editing-todo todo)))

(rf/reg-event-db
  :hide-form
  (fn [db _]
    (assoc db :show-form? false :editing-todo nil)))
