package main

import (
	"html/template"
	"net/http"
	"strings"

	"github.com/stevedylandev/andromeda/pkg/auth"
	"github.com/stevedylandev/andromeda/pkg/web"
)

func (a *App) loginGetHandler(w http.ResponseWriter, r *http.Request) {
	web.Render(a.Templates, w, "login.html", loginPageData{Error: r.URL.Query().Get("error")}, a.Log)
}

func (a *App) loginPostHandler(w http.ResponseWriter, r *http.Request) {
	if err := r.ParseForm(); err != nil {
		web.RedirectWithError(w, r, "/login", "Invalid request")
		return
	}
	if !auth.SecureEqual(r.FormValue("password"), a.Password) {
		web.RedirectWithError(w, r, "/login", "Invalid password")
		return
	}
	token, err := a.Sessions.Create()
	if err != nil {
		a.Log.Error("create session failed", "err", err)
		web.RedirectWithError(w, r, "/login", "Server error")
		return
	}
	http.SetCookie(w, a.Sessions.SessionCookie(token))
	http.Redirect(w, r, "/", http.StatusSeeOther)
}

func (a *App) logoutHandler(w http.ResponseWriter, r *http.Request) {
	if c, err := r.Cookie(a.Sessions.CookieName); err == nil && c.Value != "" {
		a.Sessions.Delete(c.Value)
	}
	http.SetCookie(w, a.Sessions.ClearCookie())
	http.Redirect(w, r, "/login", http.StatusSeeOther)
}

func (a *App) indexHandler(w http.ResponseWriter, r *http.Request) {
	notes, err := listNotes(a.DB)
	if err != nil {
		a.Log.Error("list notes failed", "err", err)
		http.Error(w, "internal server error", http.StatusInternalServerError)
		return
	}
	web.Render(a.Templates, w, "index.html", indexPageData{Notes: notes}, a.Log)
}

func (a *App) newNoteGetHandler(w http.ResponseWriter, r *http.Request) {
	web.Render(a.Templates, w, "new.html", newPageData{Error: r.URL.Query().Get("error")}, a.Log)
}

func (a *App) createNoteHandler(w http.ResponseWriter, r *http.Request) {
	if err := r.ParseForm(); err != nil {
		web.RedirectWithError(w, r, "/notes/new", "Invalid request")
		return
	}
	title := strings.TrimSpace(r.FormValue("title"))
	content := r.FormValue("content")
	if title == "" {
		web.RedirectWithError(w, r, "/notes/new", "Title is required")
		return
	}
	note, err := createNote(a.DB, title, content)
	if err != nil {
		a.Log.Error("create note failed", "err", err)
		web.RedirectWithError(w, r, "/notes/new", "Failed to create note")
		return
	}
	http.Redirect(w, r, "/notes/"+note.ShortID, http.StatusSeeOther)
}

func (a *App) viewNoteHandler(w http.ResponseWriter, r *http.Request) {
	shortID := r.PathValue("short_id")
	note, err := getNoteByShortID(a.DB, shortID)
	if err != nil {
		a.Log.Error("get note failed", "err", err)
		http.Error(w, "internal server error", http.StatusInternalServerError)
		return
	}
	if note == nil {
		http.Error(w, "Note not found", http.StatusNotFound)
		return
	}
	rendered, err := renderMarkdown(note.Content)
	if err != nil {
		a.Log.Error("render markdown failed", "err", err)
		http.Error(w, "internal server error", http.StatusInternalServerError)
		return
	}
	web.Render(a.Templates, w, "view.html", viewPageData{Note: *note, Rendered: template.HTML(rendered)}, a.Log)
}

func (a *App) editNoteGetHandler(w http.ResponseWriter, r *http.Request) {
	shortID := r.PathValue("short_id")
	note, err := getNoteByShortID(a.DB, shortID)
	if err != nil {
		a.Log.Error("get note failed", "err", err)
		http.Error(w, "internal server error", http.StatusInternalServerError)
		return
	}
	if note == nil {
		http.Error(w, "Note not found", http.StatusNotFound)
		return
	}
	web.Render(a.Templates, w, "edit.html", editPageData{Note: *note, Error: r.URL.Query().Get("error")}, a.Log)
}

func (a *App) updateNoteHandler(w http.ResponseWriter, r *http.Request) {
	shortID := r.PathValue("short_id")
	if err := r.ParseForm(); err != nil {
		web.RedirectWithError(w, r, "/notes/"+shortID+"/edit", "Invalid request")
		return
	}
	title := strings.TrimSpace(r.FormValue("title"))
	content := r.FormValue("content")
	if title == "" {
		web.RedirectWithError(w, r, "/notes/"+shortID+"/edit", "Title is required")
		return
	}
	note, err := updateNoteByShortID(a.DB, shortID, title, content)
	if err != nil {
		a.Log.Error("update note failed", "err", err)
		web.RedirectWithError(w, r, "/notes/"+shortID+"/edit", "Failed to update note")
		return
	}
	if note == nil {
		http.Error(w, "Note not found", http.StatusNotFound)
		return
	}
	http.Redirect(w, r, "/notes/"+shortID, http.StatusSeeOther)
}

func (a *App) deleteNoteHandler(w http.ResponseWriter, r *http.Request) {
	shortID := r.PathValue("short_id")
	if _, err := deleteNoteByShortID(a.DB, shortID); err != nil {
		a.Log.Error("delete note failed", "err", err)
	}
	http.Redirect(w, r, "/", http.StatusSeeOther)
}
