package controllers

import (
	"fmt"
	"math"
	"strconv"
	"time"
	"zatobay_api/database"
	"zatobay_api/models"

	"github.com/gofiber/fiber/v2"

	datatable "zatobay_api/utils/datatable"
)

type FilterAjaxSchool struct {
	SchoolName string `json:"school_name" url:"school_name" query:"school_name"`
	Page       string `json:"page" url:"page" query:"page"`
	PerPage    string `json:"length" url:"length" query:"length"`
	Sort       string `json:"column" url:"column" query:"column"`
	SortDir    string `json:"dir" url:"dir" query:"dir"`
	Draw       string `json:"draw" url:"draw" query:"draw"`
}

func CreateSchool(c *fiber.Ctx) error {

	// user auth

	var data map[string]string

	if err := c.BodyParser(&data); err != nil {
		return c.Status(400).JSON(err.Error())
	}

	school_info := models.Schools{
		SchoolName: data["school_name"],
		CreatedAt:  time.Now(),
		UpdatedAt:  time.Now(),
	}

	res := database.DB.Create(&school_info)
	if res.Error != nil {
		return c.Status(400).JSON(fiber.Map{
			"status": "error",
			"error":  res.Error,
		})
	}
	return c.Status(200).JSON(fiber.Map{
		"status": "success",
		"data":   school_info,
	})
}

func GetSchool(c *fiber.Ctx) error {

	var school_info []models.Schools

	result := database.DB.Find(&school_info)

	if result.RowsAffected == 0 {
		return c.SendStatus(404)
	}

	return c.Status(200).JSON(fiber.Map{
		"status": "success",
		"data":   school_info,
	})
}

func GetSchoolById(c *fiber.Ctx) error {

	var school_info models.Schools

	paramsId := c.Params("id")

	id_int, err := strconv.Atoi(paramsId)

	if err != nil {
		return err
	}

	result := database.DB.Find(&school_info, id_int)

	if result.RowsAffected == 0 {
		return c.SendStatus(404)
	}

	return c.Status(200).JSON(fiber.Map{
		"status": "success",
		"data":   school_info,
	})
}

func UpdateSchool(c *fiber.Ctx) error {
	var data map[string]string

	if err := c.BodyParser(&data); err != nil {
		return c.Status(400).JSON(err.Error())
	}

	id := c.Params("id")
	id_int, err := strconv.Atoi(id)

	if err != nil {
		return err
	}

	school := models.Schools{
		SchoolName: data["school_name"],
		UpdatedAt:  time.Now(),
	}

	result := database.DB.Where("id = ?", id_int).Updates(&school)

	if result.RowsAffected == 0 {
		return c.SendStatus(404)
	}

	return c.Status(200).JSON(fiber.Map{
		"message": "success update school, id :" + id,
		"data":    school,
		"status":  "success",
	})
}

func DeleteSchool(c *fiber.Ctx) error {

	id := c.Params("id")
	id_int, err := strconv.Atoi(id)

	if err != nil {
		id_int = -1
	}

	var School models.Schools

	result := database.DB.Delete(&School, id_int)

	if result.RowsAffected == 0 {
		return c.SendStatus(404)
	}

	return c.Status(200).JSON(fiber.Map{
		"message": "success delete school, id :" + id,
		"status":  "success",
	})
}

func SchoolAjaxList(c *fiber.Ctx) error {

	filterAjax := new(FilterAjaxSchool)

	if err := c.QueryParser(filterAjax); err != nil {
		return c.Status(400).JSON(err.Error())
	}

	page, err := strconv.Atoi(filterAjax.Page)
	if err != nil {
		page = 1
	}
	perPage, err := strconv.Atoi(filterAjax.PerPage)
	if err != nil {
		perPage = 10
	}

	Schools := models.Schools{
		SchoolName: filterAjax.SchoolName,
	}

	var sort map[string]string
	sort = make(map[string]string)
	if filterAjax.Sort != "" {
		if filterAjax.SortDir == "" {
			sort[filterAjax.Sort] = "desc"
		} else {
			sort[filterAjax.Sort] = filterAjax.SortDir
		}
	}
	limit := perPage
	offset := (page - 1) * limit

	data, total, err := SchoolQueryAjaxList(Schools, limit, offset, sort)

	if err != nil {
		return c.Status(400).JSON(err.Error())
	}
	pages := math.Ceil(float64(*total) / float64(perPage))
	meta := datatable.MetaDataTable{
		CurrentPage: page,
		From:        offset + 1,
		LastPage:    int(pages),
		Path:        "",
		PerPage:     fmt.Sprintf("%v", limit),
		To:          offset + limit,
		Total:       int(*total),
	}

	datatableFormat := datatable.DataTable{
		Meta: datatable.MetaDataTable{
			CurrentPage: page,
			From:        0,
			LastPage:    1,
			Path:        *datatable.BuildUrlForLink(c.Request(), 0),
			PerPage:     strconv.Itoa(perPage),
			To:          0,
			Total:       0,
		},
		Data: nil,
		Links: datatable.LinkDatatable{
			First: *datatable.BuildUrlForLink(c.Request(), 1),
			Last:  nil,
			Next:  nil,
			Prev:  nil,
		},
		Payload: filterAjax,
	}

	if err == nil {
		var dataResponseSchool []models.Schools

		for _, data := range data {
			dataResponseSchool = append(dataResponseSchool, data)
		}

		datatableFormat.Data = dataResponseSchool
		meta.Path = *datatable.BuildUrlForLink(c.Request(), 0)
		datatableFormat.Meta = meta
		datatableFormat.Links = datatable.BuildLinksData(c.Request(), meta)
	}

	return c.JSON(fiber.Map{
		"status": "success",
		"data":   datatableFormat,
	})
}

func SchoolQueryAjaxList(filter models.Schools, limit, offset int, sort map[string]string) ([]models.Schools, *int64, error) {
	var (
		result []models.Schools
		count  int64
	)

	query := database.DB.Where(filter)
	if sort == nil {
		query = query.Order("id")
	} else {
		for key, val := range sort {
			query = query.Order(fmt.Sprintf("%s %s", key, val))
		}
	}
	query = query.Offset(offset).Limit(limit).Find(&result)
	fmt.Println(query)
	if query.Error != nil {
		return nil, nil, query.Error
	}
	dbCount := database.DB.Table("schools").Where(filter).Select("id").Count(&count)
	if dbCount.Error != nil {
		return nil, nil, dbCount.Error
	}
	return result, &count, nil

}
