package server

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"text/template"
	"time"

	"git.linuxit.ro/turos.robert/mynotes/cmds/webservice/types"
	"git.linuxit.ro/turos.robert/mynotes/lib/inout"
	"github.com/yuin/goldmark"
	"github.com/yuin/goldmark/extension"
)

func Notes(w http.ResponseWriter, r *http.Request, fisier string) {
	var buf bytes.Buffer
	notita := types.Notita{}
	err := inout.FileToObj(fisier, &notita)
	if err != nil {
		WriteError(w, err)
		return
	}
	if err := goldmark.Convert([]byte(notita.Continut), &buf); err != nil {
		WriteError(w, err)
		return
	}
	notita.HTML = buf.String()
	resp, code := inout.ParseTemplate("templates/notita.tmpl", notita)
	w.WriteHeader(code)
	w.Write(resp)
}

func ListNotes(w http.ResponseWriter, r *http.Request, s *Server) {

	if r.Method == "GET" {
		f := inout.Folder{}
		err := inout.GetFolderStructure(s.NotesDir, &f)
		if err != nil {
			WriteError(w, err)
			return
		}
		resp, code := inout.ParseTemplate("templates/list_notes.tmpl", f)
		w.Header().Set("Content-Type", "text/html")
		w.WriteHeader(code)
		w.Write(resp)
		return
	}
	w.WriteHeader(http.StatusMethodNotAllowed)
	w.Write([]byte("methoda nepermisa"))
}

func EditNotes(w http.ResponseWriter, r *http.Request, filename string) {

	if r.Method == "GET" {
		f := types.Notita{}
		err := inout.FileToObj(filename, &f)
		if err != nil {
			WriteError(w, err)
			return
		}
		resp, code := inout.ParseTemplate("templates/edit_notes.tmpl", f)
		w.WriteHeader(code)
		w.Write(resp)
		return
	}
	WriteError(w, fmt.Errorf("method %s not allowed", r.Method))
}

func MDToHTML(w http.ResponseWriter, r *http.Request) {
	body, err := io.ReadAll(r.Body)
	if err != nil {
		fmt.Fprintf(w, "%+v", err)
	}
	mp := make(map[string]any)
	err = json.Unmarshal(body, &mp)
	if err != nil {
		fmt.Fprintf(w, "%+v", err)
	}
	var buff bytes.Buffer
	md := goldmark.New(
		goldmark.WithExtensions(extension.Table,
			extension.DefinitionList,
			extension.Footnote,
			extension.Typographer))
	err = md.Convert([]byte(mp["markdown"].(string)), &buff)
	if err != nil {
		fmt.Fprintf(w, "%+v", err)
	}
	w.Write(buff.Bytes())
}

func API(w http.ResponseWriter, r *http.Request, s *Server) {
	action := strings.Trim(strings.TrimPrefix(r.URL.Path, "/api/"), "/")
	fmt.Println(action)
	if r.Method == "POST" {
		//w.WriteHeader(http.StatusNotImplemented)
		//w.Write(fmt.Appendf(nil, "action not implemented: %s", action))
		switch action {
		case "save_note":
			r.ParseForm()
			n := types.Notita{}
			n.Titlu = r.Form.Get("titlu")
			n.Continut = r.Form.Get("notita")
			n.Folder = r.Form.Get("director")
			if n.Folder == "" {
				n.Folder = "default"
			}
			err := inout.SafeDir(n.Folder)
			if err != nil {
				WriteError(w, err)
				return
			}
			path := filepath.Join(s.NotesDir, n.Folder)
			err = os.MkdirAll(path, 0755)
			fmt.Println(n.Folder)
			if err != nil {
				WriteError(w, err)
				return
			}

			fisier := fmt.Sprintf("notita-%s.json", time.Now().Format("2006-01-02-150405.999999"))
			n.Path = filepath.Join("notes_folder", n.Folder, fisier)
			//fmt.Println(fisier, r.Form)
			//return

			err = inout.ObjToFile(filepath.Join(s.NotesDir, n.Folder, fisier), n, true)
			if err != nil {
				WriteError(w, err)
				return
			}
			referinta := r.Referer()
			fmt.Println(referinta)
			if referinta != "" {
				http.Redirect(w, r, referinta, http.StatusSeeOther)
			} else {
				http.Redirect(w, r, "/index.html", http.StatusSeeOther)
			}
		case "update_note":
			r.ParseForm()
			n := types.Notita{}
			n.Titlu = r.Form.Get("titlu")
			n.Path = r.Form.Get("path")
			n.Folder = r.Form.Get("director")
			n.Continut = r.Form.Get("notita")
			fmt.Println(n.Path)
			err := inout.ObjToFile(n.Path, n, true)
			if err != nil {
				WriteError(w, err)
				return
			}
			referinta := r.Referer()
			if referinta != "" {
				http.Redirect(w, r, referinta, http.StatusSeeOther)
			} else {
				http.Redirect(w, r, "/index.html", http.StatusSeeOther)
			}
		case "create_dir":
			r.ParseForm()
			path := filepath.Join("notes_folder", r.Form.Get("director"), r.Form.Get("subdirector"))
			fmt.Println(path)
			err := os.Mkdir(path, 0755)
			if err != nil {
				WriteError(w, err)
				return
			}
			referinta := r.Referer()
			if referinta != "" {
				http.Redirect(w, r, referinta, http.StatusSeeOther)
			} else {
				http.Redirect(w, r, "/index.html", http.StatusSeeOther)
			}
		}
	}
	resp, code := inout.ParseTemplate("templates/error.tmpl", fmt.Errorf("method %s not allowed", r.Method))
	w.Header().Set("Content-Type", "text/html")
	w.WriteHeader(code)
	w.Write(resp)
}

func Design_viewer(w http.ResponseWriter, r *http.Request, s *Server) {
	f := inout.Folder{}
	err := inout.GetFolderStructure(s.NotesDir, &f)
	if err != nil {
		WriteError(w, err)
		return
	}
	data := struct {
		Folders inout.Folder
	}{
		Folders: f,
	}
	renderPage(w, []string{
		"templates/design.tmpl",
		"templates/design/sections/nav_big.tmpl",
	}, data)

}

func WriteError(w http.ResponseWriter, err error) {
	resp, code := inout.ParseTemplate("templates/error.tmpl", err)
	w.Header().Set("Content-Type", "text/html")
	w.WriteHeader(code)
	w.Write(resp)

}

func renderPage(w http.ResponseWriter, templates []string, data any) {
	tmpl, err := template.New(filepath.Base(templates[0])).Funcs(inout.GetFuncMap()).ParseFiles(templates...)
	if err != nil {
		WriteError(w, err)
		return
	}
	err = tmpl.ExecuteTemplate(w, filepath.Base(templates[0]), data)
	if err != nil {
		WriteError(w, err)
		return
	}

}
