package handlers

import (
	"errors"
	"fmt"
	"github.com/gofiber/fiber/v3"
	"lmika.dev/lmika/hugo-cms/models"
	"lmika.dev/lmika/hugo-cms/services/posts"
	"net/http"
)

type Post struct {
	Post *posts.Service
}

func (h *Post) Posts(c fiber.Ctx) error {
	site := GetSite(c)

	posts, err := h.Post.ListPostOfSite(c.Context(), site)
	if err != nil {
		return err
	}

	return c.Render("posts/index", fiber.Map{
		"posts": posts,
	}, "layouts/site")
}

func (h *Post) New(c fiber.Ctx) error {
	return c.Render("posts/new", fiber.Map{
		"post": models.Post{},
	}, "layouts/site")
}

func (h *Post) Create(c fiber.Ctx) error {
	site := GetSite(c)

	var req struct {
		Title string `json:"title" form:"title"`
		Body  string `json:"body" form:"body"`
	}
	if err := c.Bind().Body(&req); err != nil {
		return err
	}

	_, err := h.Post.Create(c.Context(), site, posts.NewPost{
		Title: req.Title,
		Body:  req.Body,
	})
	if err != nil {
		return err
	}

	return c.Redirect().To(fmt.Sprintf("/sites/%v/posts", site.ID))
}

func (h *Post) Edit(c fiber.Ctx) error {
	site := GetSite(c)

	postID := fiber.Params[int](c, "postId")
	if postID == 0 {
		return errors.New("postId is required")
	}

	post, err := h.Post.GetPost(c.Context(), postID)
	if err != nil {
		return err
	} else if post.SiteID != site.ID {
		return fmt.Errorf("post id %v not equal to site id %v", postID, site.ID)
	}

	return c.Render("posts/new", fiber.Map{
		"post": post,
	}, "layouts/site")
}

func (h *Post) Update(c fiber.Ctx) error {
	site := GetSite(c)

	postID := fiber.Params[int](c, "postId")
	if postID == 0 {
		return errors.New("postId is required")
	}

	var req struct {
		Title string `json:"title" form:"title"`
		Body  string `json:"body" form:"body"`
	}
	if err := c.Bind().Body(&req); err != nil {
		return err
	}

	post, err := h.Post.GetPost(c.Context(), postID)
	if err != nil {
		return err
	} else if post.SiteID != site.ID {
		return fmt.Errorf("post id %v not equal to site id %v", postID, site.ID)
	}

	post.Title = req.Title
	post.Body = req.Body

	if err := h.Post.Save(c.Context(), site, &post); err != nil {
		return err
	}

	return c.Redirect().To(fmt.Sprintf("/sites/%v/posts", site.ID))
}

func (h *Post) Delete(c fiber.Ctx) error {
	site := GetSite(c)

	postID := fiber.Params[int](c, "postId")
	if postID == 0 {
		return errors.New("postId is required")
	}

	if err := h.Post.DeletePost(c.Context(), site, postID); err != nil {
		return err
	}

	return Select(c,
		HTMX(func(c fiber.Ctx) error {
			return c.Status(http.StatusOK).SendString("")
		}),
		Otherwise(func(c fiber.Ctx) error {
			return c.Redirect().To(fmt.Sprintf("/sites/%v/posts", site.ID))
		}),
	)
}