package admin

import (
  "maps"
  "reflect"
  "fmt"
  "github.com/gofiber/fiber/v2"
  "MY/webapp/data"
  "MY/webapp/api"
  . "MY/webapp/common"
)

func GetApiTableIndex(c *fiber.Ctx) error {
  _, err := api.CheckAuthed(c, true)
  if err != nil { return c.Redirect("/") }

  var tables []string

  for k := range maps.Keys(data.Models()) {
    tables = append(tables, k)
  }

  return c.JSON(tables)
}

func GetApiSelectAll(c *fiber.Ctx) error {
  _, err := api.CheckAuthed(c, true)
  if err != nil { return c.Redirect("/") }

  table := c.Params("table")
  if table == "" { return c.Redirect("/admin/table/") }
  type_is := data.Models()[table]

  page := c.QueryInt("page", 0)
  if page < 0 { page = 0 }

  search := c.Query("search", "")
  var result []any

  if search == "" {
    result, err = SelectTable(table, type_is, 20, uint64(page));
    if err != nil { return IfErrNil(err, c) }
  } else {
    // NOTE: need a 404 here when there's no result? or empty list?
    result, err = SearchTable(search, table, type_is, 20, uint64(page));
    if err != nil { return IfErrNil(err, c) }
  }

  return c.JSON(result)
}

func GetPageSelectAll(c *fiber.Ctx) error {
  _, err := api.CheckAuthed(c, true)
  if err != nil { return c.Redirect("/") }

  return c.Render("admin/table/contents", fiber.Map{"Table": c.Params("table")})
}

func GetApiSelectOne(c *fiber.Ctx) error {
  _, err := api.CheckAuthed(c, true)
  if err != nil { return c.Redirect("/") }

  table := c.Params("table")
  id, err := c.ParamsInt("id", -1)
  if err != nil || id < 0 { return IfErrNil(err, c) }

  type_is := data.Models()[table]

  result, err := Get(table, type_is, int64(id))
  if err != nil { return IfErrNil(err, c) }

  return c.JSON(result.Interface())
}

func GetPageSelectOne(c *fiber.Ctx) error {
  _, err := api.CheckAuthed(c, true)
  if err != nil { return c.Redirect("/") }

  table := c.Params("table")
  id, err := c.ParamsInt("id", -1)
  if err != nil || id < 0 { return IfErrNil(err, c) }

  return c.Render("admin/table/view", fiber.Map{
    "Table": table,
    "Id": id,
  })
}

func PostApiUpdate(c *fiber.Ctx) error {
  _, err := api.CheckAuthed(c, true)
  if err != nil { return c.Redirect("/") }

  table := c.Params("table")
  typeOf := data.Models()[table]
  obj, err := ReflectOnPost(typeOf, c)
  if err != nil { return IfErrNil(err, c) }

  err = Update(table, obj.Elem())
  if err != nil { return IfErrNil(err, c) }

  return c.RedirectBack("/admin/table/", 303)
}

func GetPageInsert(c *fiber.Ctx) error {
  _, err := api.CheckAuthed(c, true)
  if err != nil { return c.Redirect("/") }

  table := c.Params("table")
  return c.Render("admin/table/new", fiber.Map{ "Table": table })
}

func GetApiInsert(c *fiber.Ctx) error {
  _, err := api.CheckAuthed(c, true)
  if err != nil { return c.Redirect("/") }

  table := c.Params("table")
  typeOf := data.Models()[table]
  result := reflect.New(typeOf)
  return c.JSON(result.Interface())
}

func PostApiInsert(c *fiber.Ctx) error {
  _, err := api.CheckAuthed(c, true)
  if err != nil { return c.Redirect("/") }

  table := c.Params("table")

  typeOf := data.Models()[table]
  obj, err := ReflectOnPost(typeOf, c)
  if err != nil { return IfErrNil(err, c) }

  id, _, err := Insert(table, obj.Elem())
  if err != nil { return IfErrNil(err, c) }

  return c.Redirect(fmt.Sprintf("/admin/table/%s/%d/", table, id), 303)
}

func DeleteApi(c *fiber.Ctx) error {
  _, err := api.CheckAuthed(c, true)
  if err != nil { return c.Redirect("/") }

  table := c.Params("table")

  id, err := c.ParamsInt("id", -1)
  if err != nil || id < 0 { return IfErrNil(err, c) }

  err = Delete(table, int64(id))
  if err != nil { return IfErrNil(err, c) }

  return c.JSON(fiber.Map{})
}

func GetPageAdminIndex(c *fiber.Ctx) error {
  _, err := api.CheckAuthed(c, true)
  if err != nil { return c.Redirect("/") }

  return c.Render("admin/table/index", fiber.Map{})
}

func Setup(app *fiber.App) {
  app.Get("/admin/table/", GetPageAdminIndex)
  app.Get("/admin/table/:table/", GetPageSelectAll)
  app.Get("/admin/new/table/:table/", GetPageInsert)
  app.Get("/admin/table/:table/:id/", GetPageSelectOne)

  app.Get("/api/admin/table", GetApiTableIndex)
  app.Get("/api/admin/table/:table", GetApiSelectAll)
  app.Get("/api/admin/new/table/:table", GetApiInsert)
  app.Post("/api/admin/new/table/:table", PostApiInsert)
  app.Get("/api/admin/table/:table/:id", GetApiSelectOne)
  app.Post("/api/admin/table/:table/:id", PostApiUpdate)
}
