package main

import (
	"bytes"
	"fmt"
	"net/http"
	"strconv"
	"strings"

	"brainminder.speedtech.it/internal/request"
	"brainminder.speedtech.it/internal/response"
	"brainminder.speedtech.it/internal/validator"
	"brainminder.speedtech.it/models"
	"github.com/alexedwards/flow"
)

type quicknoteForm struct {
	Id           int64               `form:"Id"`
	Note         string              `form:"Note"`
	NoteRendered string              `form:"Note_rendered"`
	Validator    validator.Validator `form:"-"`
}

type quicknoteTransformForm struct {
	Title          string   `form:"Title"`
	TypeId         int64    `form:"Type_id"`
	Description    string   `form:"Description"`
	Tags           string   `form:"Tags"`
	Categories     []string `form:"Categories"`
	Notebooks      []string `form:"Notebooks"`
	KeepInQuickbox int      `form:"Keep_in_quickbox"`
}

func (app *application) quickboxAll(w http.ResponseWriter, r *http.Request) {
	var fullBuf = new(bytes.Buffer)

	data := app.newTemplateData(r)

	quicknoteModel := &models.QuicknoteModel{BaseModel: &models.BaseModel{DB: app.db}}

	params := r.URL.Query()
	offsetStr := params.Get("offset")
	var offset int64 = 0
	if len(offsetStr) == 0 {
		offset = 0
	} else {
		offset, _ = strconv.ParseInt(offsetStr, 10, 64)
	}
	data["offset"] = offset

	rows, _, _ := quicknoteModel.AllQB(offset)
	data["quicknotes"] = rows

	err := response.HXFragment(fullBuf, []string{"quickbox/list.tmpl"}, "quickbox:list", data)
	if err != nil {
		app.serverError(w, r, err)
	}
	_, err = fullBuf.WriteTo(w)
	if err != nil {
		app.logError("Building quickbox list buffer : ", err)
	}
	w.WriteHeader(http.StatusOK)
}

func (app *application) quickboxAdd(w http.ResponseWriter, r *http.Request) {
	quicknoteModel := models.NewQuicknoteModel(app.db)
	var fullBuf = new(bytes.Buffer)
	var quicknoteId int64
	data := app.newTemplateData(r)

	var quicknoteFromForm quicknoteForm

	err := request.DecodePostForm(r, &quicknoteFromForm)
	if err != nil {
		app.serverError(w, r, err)
	}

	quicknote := &models.Quicknote{
		Note: quicknoteFromForm.Note,
	}

	quicknoteId, err = quicknoteModel.Create(quicknote)
	if err != nil {
		app.badRequest(w, err)
		return
	}

	data["quicknote"] = quicknoteForm{
		Id:           quicknoteId,
		Note:         quicknote.Note,
		NoteRendered: quicknote.NoteRendered,
	}

	err = response.HXFragment(fullBuf, []string{"quickbox/add.tmpl"}, "quickbox:add", data)
	if err != nil {
		app.serverError(w, r, err)
		return
	}

	w.Header().Add("HX-Trigger", `{"quickboxNoteClear": ""}`)

	_, err = fullBuf.WriteTo(w)
	if err != nil {
		app.logError("Building quickbox add buffer : ", err)
	}
	w.WriteHeader(http.StatusUnprocessableEntity)
}

func (app *application) quickboxTransform(w http.ResponseWriter, r *http.Request) {
	quicknoteModel := models.NewQuicknoteModel(app.db)
	quicknoteIdStr := flow.Param(r.Context(), "quicknote_id")
	quicknoteId, _ := strconv.ParseInt(quicknoteIdStr, 10, 64)
	quicknote, _, _ := quicknoteModel.One(quicknoteId)

	data := app.newTemplateData(r)

	var fullBuf = new(bytes.Buffer)

	switch r.Method {
	case http.MethodGet:

		data["quicknote"] = quicknoteForm{
			Id:   quicknote.Id,
			Note: quicknote.Note,
		}

		data["categories"] = app.getCategoriesAsOptions()
		data["categoriesMap"] = app.getCategoriesAsMap()
		data["types"] = app.getTypesAsOptions(r)
		data["notebooks"] = app.getNotebooksAsOptions()

		err := response.HXFragment(fullBuf, []string{"quickbox/transform.tmpl"}, "page:content", data)
		if err != nil {
			app.serverError(w, r, err)
		}

		w.Header().Add("HX-Trigger-After-Settle", `{"showModalDialog": ""}`)
		_, err = fullBuf.WriteTo(w)
		if err != nil {
			app.logError("Building quickbox transform form buffer : ", err)
		}

	case http.MethodPost:
		itemModel := models.NewItemModel(app.db)
		var quicknoteTransformFromForm quicknoteTransformForm

		err := request.DecodePostForm(r, &quicknoteTransformFromForm)
		if err != nil {
			app.serverError(w, r, err)
		}

		item := &models.Item{
			TypeId:      quicknoteTransformFromForm.TypeId,
			Title:       quicknoteTransformFromForm.Title,
			Description: quicknoteTransformFromForm.Description,
			Tags:        quicknoteTransformFromForm.Tags,
		}

		notebookStr := strings.Join(quicknoteTransformFromForm.Notebooks, "|")
		if len(notebookStr) > 0 {
			notebookStr = "|" + notebookStr + "|"
		}
		item.Notebooks = notebookStr

		categoriesStr := strings.Join(quicknoteTransformFromForm.Categories, "|")
		if len(categoriesStr) > 0 {
			categoriesStr = "|" + categoriesStr + "|"
		}
		item.Categories = categoriesStr

		itemId, err := itemModel.Create(item)
		item.Id = itemId

		typeModel := &models.TypeModel{DB: app.db}
		aType, _, _ := typeModel.One(item.TypeId)
		item.TypeTitle = aType.Title

		fieldModel := &models.FieldModel{DB: app.db}
		var fields, _, _ = fieldModel.ByType(item.TypeId)
		fieldsValues := make(map[int64]map[int]string)

		err = itemModel.SaveKeywords(item, &fields, fieldsValues)
		if err != nil {
			app.logError("Quickbox save keywords : ", err)
		}

		data["messageType"] = "success"
		data["messageContent"] = "Quicknote transformed successfully"
		err = response.HXFragment(fullBuf, []string{"partials/message.tmpl"}, "message", data)
		if err != nil {
			app.serverError(w, r, err)
		}

		triggerResponse := fmt.Sprintf(`{"closeQuickboxTransformModal":{"quickNoteId": "%d", "keepQuickNote": "%d"}}`, quicknoteId, quicknoteTransformFromForm.KeepInQuickbox)
		w.Header().Add("HX-Trigger-After-Settle", triggerResponse)
		_, err = fullBuf.WriteTo(w)
		if err != nil {
			app.logError("Building quickbox transform form buffer on post : ", err)
		}
		w.WriteHeader(http.StatusUnprocessableEntity)
	}
}

func (app *application) quickboxUpdate(w http.ResponseWriter, r *http.Request) {
	quicknoteModel := models.NewQuicknoteModel(app.db)
	quicknoteIdStr := flow.Param(r.Context(), "quicknote_id")
	quicknoteId, _ := strconv.ParseInt(quicknoteIdStr, 10, 64)
	quicknote, _, _ := quicknoteModel.One(quicknoteId)

	data := app.newTemplateData(r)
	data["formAction"] = "/quicknote/update/" + quicknoteIdStr
	data["formTarget"] = "#message"
	data["messageType"] = ""
	data["messageContent"] = ""

	var fullBuf = new(bytes.Buffer)

	switch r.Method {
	case http.MethodGet:

		data["quicknote"] = quicknoteForm{
			Id:   quicknote.Id,
			Note: quicknote.Note,
		}

		if r.Header.Get("HX-Request") == "true" {

			buf, err := response.Fragment([]string{"quicknotes/form.tmpl", "partials/message.tmpl"}, "page:content", data)
			if err != nil {
				app.serverError(w, r, err)
			}
			fullBuf.Write(buf.Bytes())

			fullBuf.WriteString("<div hx-swap-oob=\"true\" id=\"page-title\">")
			buf, err = response.Fragment([]string{"quicknotes/update_title.tmpl"}, "page:title", data)
			if err != nil {
				app.serverError(w, r, err)
			}
			fullBuf.Write(buf.Bytes())
			fullBuf.WriteString("</div>")

			_, err = fullBuf.WriteTo(w)
			if err != nil {
				app.logError("Building quickbox update form buffer : ", err)
			}

		} else {
			err := response.Page(w, http.StatusOK, data, []string{"quicknotes/update_title.tmpl", "quicknotes/form.tmpl", "partials/message.tmpl"})
			if err != nil {
				app.serverError(w, r, err)
			}
		}

	case http.MethodPost:
		var quicknoteFromForm quicknoteForm

		err := request.DecodePostForm(r, &quicknoteFromForm)
		if err != nil {
			app.serverError(w, r, err)
		}

		quicknote.Note = quicknoteFromForm.Note

		err = quicknoteModel.Update(quicknote)
		if err != nil {
			app.badRequest(w, err)
			return
		}

		data["quicknote"] = quicknoteForm{
			Id:   quicknote.Id,
			Note: quicknote.Note,
		}

		data["messageType"] = "success"
		data["messageContent"] = "Quicknote saved successfully"

		buf, err := response.Fragment([]string{"partials/message.tmpl"}, "message", data)
		if err != nil {
			app.serverError(w, r, err)
		}
		fullBuf.Write(buf.Bytes())

		fullBuf.WriteString("<div hx-swap-oob=\"true\" id=\"page-title\">")
		buf, err = response.Fragment([]string{"quicknotes/update_title.tmpl"}, "page:title", data)
		if err != nil {
			app.serverError(w, r, err)
		}
		fullBuf.Write(buf.Bytes())
		fullBuf.WriteString("</div>")

		fullBuf.WriteString("<div hx-swap-oob=\"true\" id=\"current_quicknote_id\">")
		buf, err = response.Fragment([]string{"partials/quicknotes-list.tmpl"}, "partial:quicknotes-list", data)
		if err != nil {
			app.serverError(w, r, err)
		}
		fullBuf.Write(buf.Bytes())
		fullBuf.WriteString("</div>")

		_, err = fullBuf.WriteTo(w)
		if err != nil {
			app.logError("Building quickbox update form buffer on post : ", err)
		}

		w.WriteHeader(http.StatusUnprocessableEntity)
	}
}

func (app *application) quickboxDelete(w http.ResponseWriter, r *http.Request) {
	quicknoteModel := models.NewQuicknoteModel(app.db)
	quicknoteIdStr := flow.Param(r.Context(), "quicknote_id")
	quicknoteId, _ := strconv.ParseInt(quicknoteIdStr, 10, 64)

	_, err := quicknoteModel.Delete(quicknoteId)
	if err != nil {
		app.serverError(w, r, err)
	}
}
