package routes

import (
	"dk/internal/actions"
	"dk/internal/components"
	"dk/internal/database"
	"dk/internal/models/towns"
	"dk/internal/models/users"
	"slices"
	"strconv"

	sushi "git.sharkk.net/Sharkk/Sushi"
)

func Index(ctx sushi.Ctx) {
	if !ctx.IsAuthenticated() {
		components.RenderPage(ctx, "", "intro.html", nil)
		return
	}

	user := ctx.GetCurrentUser().(*users.User)

	switch user.Currently {
	case "In Town":
		ctx.Redirect("/town")
	case "Exploring":
		ctx.Redirect("/explore")
	case "Fighting":
		ctx.Redirect("/fight")
	default:
		ctx.Redirect("/explore")
	}
}

func Move(ctx sushi.Ctx) {
	sess := ctx.GetCurrentSession()
	user := ctx.GetCurrentUser().(*users.User)

	if user.Currently == "Fighting" {
		sess.SetFlash("error", "You can't just run from a fight!")
		ctx.Redirect("/fight")
		return
	}

	dir, err := strconv.Atoi(string(ctx.PostArgs().Peek("direction")))
	if err != nil {
		ctx.SendError(400, "move form parsing error")
		return
	}

	currently, newX, newY, err := actions.Move(user, actions.Direction(dir))
	if err != nil {
		ctx.SendError(400, "move error: "+err.Error())
		return
	}

	err = database.Transaction(func() error {
		return database.Update("users", map[string]any{
			"currently": currently,
			"x":         newX,
			"y":         newY,
		}, "id", user.ID)
	})

	if err != nil {
		ctx.SendError(500, "failed to update user position")
		return
	}

	switch currently {
	case "In Town":
		ctx.Redirect("/town")
	case "Fighting":
		ctx.Redirect("/fight")
	default:
		ctx.Redirect("/explore")
	}
}

func Explore(ctx sushi.Ctx) {
	user := ctx.GetCurrentUser().(*users.User)
	if user.Currently != "Exploring" {
		ctx.Redirect("/")
		return
	}
	components.RenderPage(ctx, "", "explore.html", nil)
}

func Teleport(ctx sushi.Ctx) {
	sess := ctx.GetCurrentSession()

	id := ctx.Param("id").Int()

	town, err := towns.Find(id)
	if err != nil {
		sess.SetFlash("error", "Failed to teleport. Unknown town.")
		ctx.Redirect("/")
		return
	}

	user := ctx.GetCurrentUser().(*users.User)
	if !slices.Contains(user.GetTownIDs(), id) {
		sess.SetFlash("error", "You don't have a map to "+town.Name+".")
		ctx.Redirect("/")
		return
	}

	if user.TP < town.TPCost {
		sess.SetFlash("error", "You don't have enough TP to teleport to "+town.Name+".")
		ctx.Redirect("/")
		return
	}

	err = database.Transaction(func() error {
		return database.Update("users", map[string]any{
			"tp":        user.TP - town.TPCost,
			"x":         town.X,
			"y":         town.Y,
			"currently": "In Town",
		}, "id", user.ID)
	})

	if err != nil {
		sess.SetFlash("error", "Failed to complete teleport.")
		ctx.Redirect("/")
		return
	}

	sess.SetFlash("success", "You teleported to "+town.Name+" successfully!")
	ctx.Redirect("/town")
}
