package kpi_c_report

import (
	"fmt"
	"net/http"
	"strconv"
	"strings"

	"be.ems/lib/dborm"
	"be.ems/lib/services"
	"github.com/gin-gonic/gin"
)

func (k *KpiCReport) Get(c *gin.Context) {
	var reports []KpiCReport
	var conditions []string
	var params []any

	var querys KpiCReportQuery
	if err := c.ShouldBindQuery(&querys); err != nil {
		c.JSON(http.StatusBadRequest, services.ErrResp(err.Error()))
		return
	}

	// construct condition to get
	if querys.NeType != "" {
		conditions = append(conditions, "ne_type = ?")
		params = append(params, strings.ToUpper(querys.NeType))
	} else {
		c.JSON(http.StatusBadRequest, services.ErrResp("Not found NE type"))
		return
	}
	tableName := TableName() + "_" + strings.ToLower(querys.NeType)
	dbg := dborm.DefaultDB().Table(tableName)

	if querys.NeID != "" {
		conditions = append(conditions, "rm_uid = (select n.rm_uid from ne_info n where n.ne_type=? and n.ne_id=?)")
		params = append(params, strings.ToUpper(querys.NeType), querys.NeID)
	} else {
		c.JSON(http.StatusBadRequest, services.ErrResp("Not found required parameter NE ID"))
		return
	}
	if querys.StartTime != "" {
		conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) >= ?")
		params = append(params, querys.StartTime)
	}
	if querys.EndTime != "" {
		conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) <= ?")
		params = append(params, querys.EndTime)
	}
	conditions = append(conditions, "kpi_values != 'null'")

	whereSql := ""
	if len(conditions) > 0 {
		whereSql += strings.Join(conditions, " and ")
		dbg = dbg.Where(whereSql, params...)
	}
	// page number and size
	if pageSize := querys.PageSize; pageSize > 0 {
		dbg = dbg.Limit(pageSize)
		if pageNum := querys.PageNum; pageNum > 0 {
			dbg = dbg.Offset((pageNum - 1) * pageSize)
		}
	}

	// order by
	if sortField, sortOrder := querys.SortField, querys.SortOrder; sortField != "" && sortOrder != "" {
		orderBy := fmt.Sprintf("%s %s", sortField, sortOrder)
		dbg = dbg.Order(orderBy)
	}

	//err := dborm.DefaultDB().Table(tableName).Where(whereSql, params...).Find(&reports).Error
	err := dbg.Find(&reports).Error
	if err != nil {
		c.JSON(http.StatusOK, services.ErrResp(err.Error()))
		return
	}
	c.JSON(http.StatusOK, services.DataResp(reports))
}

func (k *KpiCReport) GetReport2FE(c *gin.Context) {
	var results []KpiCReport
	var conditions []string
	var params []any

	var querys KpiCReportQuery
	if err := c.ShouldBindQuery(&querys); err != nil {
		c.JSON(http.StatusOK, services.ErrResp(err.Error()))
		return
	}

	// construct condition to get
	if querys.NeType != "" {
		conditions = append(conditions, "ne_type = ?")
		params = append(params, strings.ToUpper(querys.NeType))
	} else {
		c.JSON(http.StatusOK, services.ErrResp("Not found required parameter NE type"))
		return
	}
	tableName := TableName() + "_" + strings.ToLower(querys.NeType)
	dbg := dborm.DefaultDB().Table(tableName)

	if querys.NeID != "" {
		conditions = append(conditions, "rm_uid = (select n.rm_uid from ne_info n where n.ne_type=? and n.ne_id=?)")
		params = append(params, querys.NeType, querys.NeID)
	} else {
		c.JSON(http.StatusBadRequest, services.ErrResp("Not found required parameter NE ID"))
		return
	}
	if querys.StartTime != "" {
		conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) >= ?")
		params = append(params, querys.StartTime)
	}
	if querys.EndTime != "" {
		conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) <= ?")
		params = append(params, querys.EndTime)
	}
	conditions = append(conditions, "kpi_values != 'null'")

	whereSql := ""
	if len(conditions) > 0 {
		whereSql += strings.Join(conditions, " and ")
		dbg = dbg.Where(whereSql, params...)
	}
	// page number and size
	if pageSize := querys.PageSize; pageSize > 0 {
		dbg = dbg.Limit(pageSize)
		if pageNum := querys.PageNum; pageNum > 0 {
			dbg = dbg.Offset((pageNum - 1) * pageSize)
		}
	}

	// order by
	if sortField, sortOrder := querys.SortField, querys.SortOrder; sortField != "" && sortOrder != "" {
		orderBy := fmt.Sprintf("%s %s", sortField, sortOrder)
		dbg = dbg.Order(orderBy)
	}

	//err := dborm.DefaultDB().Table(tableName).Where(whereSql, params...).Find(&reports).Error
	err := dbg.Find(&results).Error
	if err != nil {
		c.JSON(http.StatusOK, services.ErrResp(err.Error()))
		return
	}

	reports := []map[string]any{}
	for _, r := range results {
		report := map[string]any{
			// kip_id ...
			"neType":      *r.NeType,
			"neId":        querys.NeID,
			"neName":      *r.NeName,
			"rmUID":       *r.RmUID,
			"startIndex":  r.Index,
			"timeGroup":   r.Date[:10] + " " + *r.EndTime,
			"createdAt":   r.CreatedAt,
			"granularity": r.Granularity,
		}

		for _, k := range r.KpiValues {
			formatted := fmt.Sprintf("%.3f", k.Value)
			formattedFloat, err := strconv.ParseFloat(formatted, 64)
			if err != nil {
				formattedFloat = 0
			}
			report[k.KPIID] = formattedFloat
		}
		reports = append(reports, report)
	}
	c.JSON(http.StatusOK, services.DataResp(reports))
}

func (k *KpiCReport) GetTotalList(c *gin.Context) {
	var reports []KpiCReport
	var conditions []string
	var params []any

	var querys KpiCReportQuery
	if err := c.ShouldBindQuery(&querys); err != nil {
		c.JSON(http.StatusOK, services.ErrResp(err.Error()))
		return
	}

	// construct condition to get
	if querys.NeType != "" {
		conditions = append(conditions, "ne_type = ?")
		params = append(params, strings.ToUpper(querys.NeType))
	} else {
		c.JSON(http.StatusOK, services.ErrResp("Not found NE type"))
		return
	}
	tableName := TableName() + "_" + strings.ToLower(querys.NeType)
	dbg := dborm.DefaultDB().Table(tableName)

	if querys.StartTime != "" {
		conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) >= ?")
		params = append(params, querys.StartTime)
	}
	if querys.EndTime != "" {
		conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) <= ?")
		params = append(params, querys.EndTime)
	}
	conditions = append(conditions, "kpi_values != 'null'")

	whereSql := ""
	if len(conditions) > 0 {
		whereSql += strings.Join(conditions, " and ")
		dbg = dbg.Where(whereSql, params...)
	}

	// get total number
	var total int64 = 0
	err := dbg.Count(&total).Error
	if err != nil {
		c.JSON(http.StatusOK, services.ErrResp(err.Error()))
		return
	}

	// page number and size
	if pageSize := querys.PageSize; pageSize > 0 {
		dbg = dbg.Limit(pageSize)
		if pageNum := querys.PageNum; pageNum > 0 {
			dbg = dbg.Offset((pageNum - 1) * pageSize)
		}
	}

	// order by
	if sortField, sortOrder := querys.SortField, querys.SortOrder; sortField != "" && sortOrder != "" {
		orderBy := fmt.Sprintf("%s %s", sortField, sortOrder)
		dbg = dbg.Order(orderBy)
	}

	//err := dborm.DefaultDB().Table(tableName).Where(whereSql, params...).Find(&reports).Error
	err = dbg.Find(&reports).Error
	if err != nil {
		c.JSON(http.StatusOK, services.ErrResp(err.Error()))
		return
	}

	c.JSON(http.StatusOK, services.TotalDataResp(reports, total))
}

func (k *KpiCReport) Total(c *gin.Context) {
	var conditions []string
	var params []any

	var querys KpiCReportQuery
	if err := c.ShouldBindQuery(&querys); err != nil {
		c.JSON(http.StatusOK, services.ErrResp(err.Error()))
		return
	}

	// construct condition to get
	if querys.NeType != "" {
		conditions = append(conditions, "ne_type = ?")
		params = append(params, strings.ToUpper(querys.NeType))
	} else {
		c.JSON(http.StatusOK, services.ErrResp("Not found NE type"))
		return
	}
	tableName := TableName() + "_" + strings.ToLower(querys.NeType)
	dbg := dborm.DefaultDB().Table(tableName)

	if querys.StartTime != "" {
		conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) >= ?")
		params = append(params, querys.StartTime)
	}
	if querys.EndTime != "" {
		conditions = append(conditions, "(UNIX_TIMESTAMP(created_at) * 1000) <= ?")
		params = append(params, querys.EndTime)
	}
	conditions = append(conditions, "kpi_values != 'null'")

	whereSql := ""
	if len(conditions) > 0 {
		whereSql += strings.Join(conditions, " and ")
		dbg = dbg.Where(whereSql, params...)
	}
	var total int64 = 0
	err := dbg.Count(&total).Error
	if err != nil {
		c.JSON(http.StatusOK, services.ErrResp(err.Error()))
		return
	}

	c.JSON(http.StatusOK, services.TotalResp(total))
}

func (k *KpiCReport) Post(c *gin.Context) {
	var report KpiCReport

	if err := c.ShouldBindJSON(&report); err != nil {
		c.JSON(http.StatusOK, services.ErrResp(err.Error()))
		return
	}
	if err := dborm.DefaultDB().Create(&report).Error; err != nil {
		c.JSON(http.StatusOK, services.ErrResp(err.Error()))
		return
	}
	c.JSON(http.StatusCreated, services.DataResp(report))
}

func (k *KpiCReport) Put(c *gin.Context) {
	var report KpiCReport
	id := c.Param("id")

	if err := dborm.DefaultDB().First(&report, id).Error; err != nil {
		c.JSON(http.StatusOK, services.ErrResp("custom indicator report not found"))
		return
	}

	if err := c.ShouldBindJSON(&report); err != nil {
		c.JSON(http.StatusOK, services.ErrResp(err.Error()))
		return
	}
	dborm.DefaultDB().Save(&report)
	c.JSON(http.StatusOK, services.DataResp(report))
}

func (k *KpiCReport) Delete(c *gin.Context) {
	id := c.Param("id")

	if err := dborm.DefaultDB().Delete(&KpiCReport{}, id).Error; err != nil {
		c.JSON(http.StatusOK, services.ErrResp("custom indicator report not found"))
		return
	}

	c.JSON(http.StatusNoContent, nil) // 204 No Content
}

func InsertKpiCReport(neType string, report KpiCReport) {
	tableName := TableName() + "_" + strings.ToLower(neType)
	if err := dborm.DefaultDB().Table(tableName).Create(&report).Error; err != nil {
		return
	}
}
