package dev_services

import (
	"fmt"
	"math"
	"strconv"
	"strings"

	"cpone/db"
	"cpone/models"

	dbx "cpone/package/database"

	"go.uber.org/zap"
)

func NewServicesMasterMenuUserGroup(uStore db.AppStore) *ServicesMasterMenuUserGroup {

	return &ServicesMasterMenuUserGroup{

		MasterMenuUserGroupStore: uStore,
	}
}

// MasterMenu struct
type Breadcrumb struct {
	IDBreadcrumb string `json:"id_breadcrumb"`
	Name         string `json:"name"`
	Url          string `json:"url"`
}

type ChildrenMenu struct {
	ChildrenParentID string `json:"children_parent_id"`
	ChildrenMenuID   string `json:"children_menu_id"`
	ChildrenMenuName string `json:"children_menu_name"`
	ChildrenMenuURL  string `json:"children_menu_url"`
	// Breadcrumb       []Breadcrumb `json:"breadcrumb"`
}

type MasterMenu struct {
	ID             string         `json:"id"`
	ParentMenuID   string         `json:"parent_menu_id"`
	ParentMenuName string         `json:"parent_menu_name"`
	ParentUrl      string         `json:"parent_url"`
	ParentIcon     string         `json:"parent_icon"`
	Children       []ChildrenMenu `json:"children"`
}

type ServicesMasterMenuUserGroup struct {
	MasterMenuUserGroupStore db.AppStore
}

type AutoComplete struct {
	Name string `json:"name"`
}

func (ug *ServicesMasterMenuUserGroup) GetUserGroup() ([]models.UserGroup, error) {
	data := []models.UserGroup{
		{UserGroupID: 1, UserGroupKode: "A", UserGroupName: "UG1"},
		{UserGroupID: 2, UserGroupKode: "B", UserGroupName: "UG2"},
		{UserGroupID: 3, UserGroupKode: "C", UserGroupName: "UG3"},
	}
	return data, nil
}

func (ug *ServicesMasterMenuUserGroup) GetUserGroupByID(id string) (models.UserGroup, error) {
	listdata := []models.UserGroup{
		{UserGroupID: 1, UserGroupKode: "A", UserGroupName: "UG1"},
		{UserGroupID: 2, UserGroupKode: "B", UserGroupName: "UG2"},
		{UserGroupID: 3, UserGroupKode: "C", UserGroupName: "UG3"},
	}
	var data models.UserGroup
	idData, err := strconv.Atoi(id)
	if err != nil {
		return data, fmt.Errorf("pack %v: %w", "Error", err)
	}
	for _, v := range listdata {

		if v.UserGroupID == idData {
			data = v
		}
	}
	// time.Sleep(5 * time.Second)
	return data, nil
}

// try
func (su *ServicesMasterMenuUserGroup) GetListMasterUserGroup() ([]models.UserGroupV1, error) {
	var userGroupList []models.UserGroupV1

	query := `
		SELECT
			ROW_NUMBER() OVER () AS nomor,
			M_UserGroupID,
			M_UserGroupCode,
			M_UserGroupName,
			M_UserGroupCreated,
			M_UserGroupLastUpdated,
			M_UserGroupIsActive
		FROM m_usergroup
		WHERE M_UserGroupIsActive = 'Y'
		order by M_UserGroupID ASC
	`

	if err := dbx.Handlex.Select(&userGroupList, query); err != nil {
		return nil, fmt.Errorf("error querying database: %v", err)
	}

	return userGroupList, nil
}

func (su *ServicesMasterMenuUserGroup) GetListBreadCrumb(title string) (models.BreadCrumbV1, error) {
	var ret models.BreadCrumbV1

	dummyBreadcrumb := []models.BreadCrumbV1{
		{
			Title: "Master User Group",
			Item: []models.ItemBreadCrumbV1{
				{
					Item: "Dashboard",
					Url:  "/dev/dashboard",
				},
				{
					Item: "Master",
					Url:  "/dev/master",
				},
				{
					Item: "User Group",
					Url:  "",
				},
			},
		},

		{
			Title: "Master User",
			Item: []models.ItemBreadCrumbV1{
				{
					Item: "Dashboard",
					Url:  "/dev/dashboard",
				},
				{
					Item: "Master",
					Url:  "/dev/master",
				},
				{
					Item: "User",
					Url:  "",
				},
			},
		},
	}

	for _, breadcrumb := range dummyBreadcrumb {
		// if utils.Contains(breadcrumb.Title, title) {
		// 	ret = breadcrumb
		// 	return ret, nil
		// }
		if breadcrumb.Title == title {
			ret = breadcrumb
			return ret, nil
		}
	}

	return ret, nil
}

func (ug *ServicesMasterMenuUserGroup) GetUserGroupByIDV1(id string) (models.UserGroupV1, error) {
	logger, _ := zap.NewProduction()

	var data models.UserGroupV1
	err := dbx.Handlex.Get(&data, `SELECT * FROM m_usergroup
	WHERE M_UserGroupID = ?`, id)

	if err != nil {
		defer logger.Sync()
		logger.Error("Error get data ug by id vs",
			zap.String("ID", id),
			zap.Error(err),
		)
		return data, fmt.Errorf("QUERY_FAILED")
	}
	return data, nil
}
func (ug *ServicesMasterMenuUserGroup) AddUserGroup(code string, name string) (models.UserGroupV1, error) {
	logger, _ := zap.NewProduction()
	var data models.UserGroupV1
	var datacek []models.UserGroupV1

	qryCek := `SELECT M_UserGroupCode FROM m_usergroup WHERE M_UserGroupCode = ? AND M_UserGroupIsActive = 'Y'`
	err := dbx.Handlex.Select(&datacek, qryCek, code)

	if err != nil {
		defer logger.Sync()
		logger.Error("Error cek data by code",
			zap.String("code", code),
			zap.Any("datacek", datacek),
		)
		return data, fmt.Errorf("QUERY_FAILED")
	}
	if len(datacek) > 0 {
		defer logger.Sync()
		logger.Error("Code already taken by another data",
			zap.String("code", code),
		)
		return data, fmt.Errorf("code sudah dipakai")
	}
	qry := `INSERT INTO m_usergroup
			(M_UserGroupCode,
			M_UserGroupName)
			VALUES (?,?);`
	// time.Sleep(5 * time.Second)
	rst := dbx.Handlex.MustExec(qry, code, name)
	insertedID, err := rst.LastInsertId()
	if err != nil {
		defer logger.Sync()
		logger.Error("Error Insert usergroup",
			zap.String("code", code),
			zap.String("name", name),
		)
		return data, fmt.Errorf("QUERY_FAILED")
	}
	s := strconv.Itoa(int(insertedID))
	data, err = ug.GetUserGroupByIDV1(s)
	if err != nil {
		defer logger.Sync()
		logger.Error("Error get usergroup by id",
			zap.String("code", code),
			zap.String("name", name),
		)
		return data, fmt.Errorf("QUERY_FAILED")
	}
	return data, nil
}
func (ug *ServicesMasterMenuUserGroup) EditUserGroup(id string, code string, name string) (models.UserGroupV1, error) {
	logger, _ := zap.NewProduction()
	var data models.UserGroupV1
	var datacek []models.UserGroupV1

	qryCek := `SELECT M_UserGroupCode FROM m_usergroup WHERE M_UserGroupCode = ? AND M_UserGroupIsActive = 'Y' AND M_UserGroupID <> ?`
	err := dbx.Handlex.Select(&datacek, qryCek, code, id)

	if err != nil {
		defer logger.Sync()
		logger.Error("Error cek data by code",
			zap.String("code", code),
			zap.Any("datacek", datacek),
		)
		return data, fmt.Errorf("QUERY_FAILED")
	}
	if len(datacek) > 0 {
		defer logger.Sync()
		logger.Error("Code already taken by another data",
			zap.String("code", code),
		)
		return data, fmt.Errorf("code sudah dipakai")
	}
	qry := `UPDATE m_usergroup
			SET M_UserGroupCode = ?,
			M_UserGroupName= ?
			WHERE M_UserGroupID = ?;`
	// time.Sleep(5 * time.Second)
	rst := dbx.Handlex.MustExec(qry, code, name, id)
	_, err = rst.RowsAffected()
	if err != nil {
		defer logger.Sync()
		logger.Error("Error Update usergroup",
			zap.String("code", code),
			zap.String("name", name),
		)
		return data, fmt.Errorf("QUERY_FAILED")
	}

	data, err = ug.GetUserGroupByIDV1(id)
	if err != nil {
		defer logger.Sync()
		logger.Error("Error get usergroup by id",
			zap.String("code", code),
			zap.String("name", name),
		)
		return data, fmt.Errorf("QUERY_FAILED")
	}
	return data, nil
}

func (ug *ServicesMasterMenuUserGroup) DeleteUserGroup(id string) (models.UserGroupV1, error) {
	logger, _ := zap.NewProduction()
	var data models.UserGroupV1
	qry := `UPDATE m_usergroup
			SET M_UserGroupIsActive = 'N'
			WHERE M_UserGroupID = ?;`
	// time.Sleep(5 * time.Second)
	rst := dbx.Handlex.MustExec(qry, id)
	_, err := rst.RowsAffected()
	if err != nil {
		defer logger.Sync()
		logger.Error("Error delete usergroup",
			zap.String("id", id),
		)
		return data, fmt.Errorf("QUERY_FAILED")
	}

	data, err = ug.GetUserGroupByIDV1(id)
	if err != nil {
		defer logger.Sync()
		logger.Error("Error get usergroup by id",
			zap.String("id", id),
		)
		return data, fmt.Errorf("QUERY_FAILED")
	}
	return data, nil
}

func (su *ServicesMasterMenuUserGroup) GetListMasterUserGroupV2(search string, currentPage int, rowPerPage int) ([]models.UserGroupV1, int, error) {
	var userGroupList []models.UserGroupV1
	var totalData int
	offset := (currentPage - 1) * rowPerPage
	prm := "%" + strings.TrimSpace(search) + "%"
	querytotal := `
		SELECT COUNT(*) 
		FROM m_usergroup
		WHERE M_UserGroupIsActive = 'Y'
		AND (M_UserGroupCode LIKE ? OR M_UserGroupName LIKE ?) 
	`
	if err := dbx.Handlex.Get(&totalData, querytotal, prm, prm); err != nil {
		return nil, 0, fmt.Errorf("error querying database: %v", err)
	}
	query := `
		SELECT
			ROW_NUMBER() OVER () AS nomor,
			M_UserGroupID,
			M_UserGroupCode,
			M_UserGroupName,
			M_UserGroupCreated,
			M_UserGroupLastUpdated,
			M_UserGroupIsActive
		FROM m_usergroup
		WHERE M_UserGroupIsActive = 'Y'
		AND (M_UserGroupCode LIKE ? OR M_UserGroupName LIKE ?)
		order by M_UserGroupID ASC
		LIMIT ? OFFSET ?
	`

	if err := dbx.Handlex.Select(&userGroupList, query, prm, prm, rowPerPage, offset); err != nil {
		return nil, 0, fmt.Errorf("error querying database: %v", err)
	}
	totalPage := int(math.Ceil(float64(totalData) / float64(rowPerPage)))

	return userGroupList, totalPage, nil
}
