package main

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"strconv"

	"github.com/google/uuid"
	_ "modernc.org/sqlite"
)

var (
	db *sql.DB
)

func main() {
	fmt.Println("ugh. can i go back to eep?")
	fmt.Println("*eeps*")
	var err error
	db, err = sql.Open("sqlite", "./db/notes.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	http.HandleFunc("/get", func(w http.ResponseWriter, r *http.Request) {
		r.ParseForm()
		if !r.Form.Has("user") {
			w.WriteHeader(400)
			fmt.Fprint(w, "This endpoint requires parameters 'user'")
			return
		}

		limit, err := strconv.Atoi(r.Form.Get("max"))
		if err != nil {
			limit = 100
		}

		rows := getNotes(r.Form.Get("user"), limit)
		jsonString, err := json.Marshal(rows)
		if err != nil {
			log.Fatal(err)
		}
		w.Header().Add("Content-Type", "text/json")
		fmt.Fprint(w, string(jsonString))
		// fmt.Println(string(jsonString))
	})

	http.HandleFunc("/new", func(w http.ResponseWriter, r *http.Request) {
		r.ParseForm()
		if !r.Form.Has("user") || !r.Form.Has("data") {
			w.WriteHeader(400)
			fmt.Fprint(w, "This endpoint requires parameters 'user' and 'data'")
			return
		}

		uuid, err := uuid.NewUUID()
		if err != nil {
			log.Fatal(err)
		}

		newNote(r.Form.Get("user"), r.Form.Get("data"), uuid.String())
		fmt.Fprint(w, uuid)
	})

	http.HandleFunc("/replace", func(w http.ResponseWriter, r *http.Request) {
		r.ParseForm()
		if !r.Form.Has("user") || !r.Form.Has("data") || !r.Form.Has("id") {
			w.WriteHeader(400)
			fmt.Fprint(w, "This endpoint requires parameters 'user' and 'data'")
			return
		}

		removeNote(r.Form.Get("user"), r.Form.Get("id"))
		newNote(r.Form.Get("user"), r.Form.Get("data"), r.Form.Get("id"))
		fmt.Fprint(w, http.StatusText(200))
	})

	http.HandleFunc("/remove", func(w http.ResponseWriter, r *http.Request) {
		r.ParseForm()
		if !r.Form.Has("user") || !r.Form.Has("id") {
			w.WriteHeader(400)
			fmt.Fprint(w, "This endpoint requires parameters 'user' and 'id'")
			return
		}

		removeNote(r.Form.Get("user"), r.Form.Get("id"))
		fmt.Fprint(w, http.StatusText(200))
	})

	fmt.Println("listening on :3000")
	log.Fatal(http.ListenAndServe(":3000", nil))
}

func getNotes(user string, limit int) [][2]string {
	var rowCount int
	err := db.QueryRow("SELECT COUNT(*) FROM notes WHERE user = ?", user).Scan(&rowCount)
	if err != nil {
		log.Fatal(err)
	}
	if rowCount > limit {
		rowCount = limit
	}

	rows, err := db.Query("SELECT * FROM notes WHERE user = ? LIMIT ?", user, limit)
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	notes := make([][2]string, rowCount)
	var dummy string

	for i := 0; rows.Next(); i++ {
		var currentRow [2]string
		if err := rows.Scan(&currentRow[0], &dummy, &currentRow[1]); err != nil {
			log.Fatal(err)
		}
		notes[i] = currentRow
	}

	return notes
}

func newNote(user string, data string, uuid string) {
	stmt, err := db.Prepare("INSERT INTO notes VALUES(?, ?, ?)")
	if err != nil {
		log.Fatal(err)
	}

	if _, err := stmt.Exec(uuid, user, data); err != nil {
		log.Fatal(err)
	}
}

func removeNote(user string, uuid string) {
	stmt, err := db.Prepare("DELETE FROM notes WHERE user = ? AND id = ?")
	if err != nil {
		log.Fatal(err)
	}

	if _, err := stmt.Exec(user, uuid); err != nil {
		log.Fatal(err)
	}
}
