package dev_services

import (
	"cpone/db"
	"cpone/models"
	dbx "cpone/package/database"
	"fmt"
	"math"
	"strconv"
	"strings"

	"go.uber.org/zap"
)

func NewServicesMasterKelainan(uStore db.AppStore) *ServicesMasterKelainan {

	return &ServicesMasterKelainan{

		MasterKelainanStore: uStore,
	}
}

type ServicesMasterKelainan struct {
	MasterKelainanStore db.AppStore
}

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

	dummyBreadcrumb := []models.BreadCrumbV1{
		{
			Title: "Master Pola Kelainan",
			Item: []models.ItemBreadCrumbV1{
				{
					Item: "Dashboard",
					Url:  "/dev/dashboard",
				},
				{
					Item: "Master",
					Url:  "/dev/master",
				},
				{
					Item: "Pola Kelainan",
					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
}

// master group kelainan
func (su *ServicesMasterKelainan) GetListMasterKelainan(search string, currentPage int, rowPerPage int) ([]models.Kelainan, int, error) {
	var kelainanList []models.Kelainan
	var totalData int
	offset := (currentPage - 1) * rowPerPage
	prm := "%" + strings.TrimSpace(search) + "%"

	querytotal := `
		SELECT COUNT(*)
		FROM mcu_kelainangroup
		WHERE Mcu_KelainanGroupIsActive = 'Y'
		AND (Mcu_KelainanGroupName LIKE ?)
	`
	if err := dbx.Handlex.Get(&totalData, querytotal, prm); err != nil {
		return nil, 0, fmt.Errorf("error query database: %v", err)
	}

	query := `
		SELECT 
			ROW_NUMBER() OVER (ORDER BY Mcu_KelainanGroupID DESC) AS nomor,
			Mcu_KelainanGroupID,
			Mcu_KelainanGroupName,
			Mcu_KelainanGroupFlagActive,
			Mcu_KelainanGroupIsActive,
			Mcu_KelainanGroupCreated,
			Mcu_KelainanGroupLastUpdated
		FROM mcu_kelainangroup
		WHERE Mcu_KelainanGroupIsActive = 'Y'
		AND (Mcu_KelainanGroupName LIKE ?)
		order by Mcu_KelainanGroupID DESC
		LIMIT ? OFFSET ?
	`

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

	return kelainanList, totalPage, nil
}

func (su *ServicesMasterKelainan) GetKelainanByID(id string) (models.Kelainan, error) {
	logger, _ := zap.NewProduction()

	var data models.Kelainan
	err := dbx.Handlex.Get(&data, `SELECT * FROM mcu_kelainangroup
	WHERE Mcu_KelainanGroupID = ?`, id)

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

func (su *ServicesMasterKelainan) AddKelainan(name string) (models.Kelainan, error) {
	logger, _ := zap.NewProduction()
	var data models.Kelainan

	var datacek []models.Kelainan

	qryCek := `SELECT Mcu_KelainanGroupName FROM mcu_kelainangroup
			WHERE Mcu_KelainanGroupName = ? AND Mcu_KelainanGroupIsActive = 'Y'`
	err := dbx.Handlex.Select(&datacek, qryCek, name)

	if err != nil {
		defer logger.Sync()
		logger.Error("Error cek data by name",
			zap.Any("datacek", datacek),
		)
		return data, fmt.Errorf("QUERY_FAILED")
	}
	if len(datacek) > 0 {
		defer logger.Sync()
		logger.Error("Name already taken by another data",
			zap.String("name", name),
		)
		return data, fmt.Errorf("name sudah dipakai")
	}

	qry := `INSERT INTO mcu_kelainangroup(
		Mcu_KelainanGroupName,
		Mcu_KelainanGroupCreated,
		Mcu_KelainanGroupLastUpdated) VALUES(?,NOW(),NOW())`
	rst := dbx.Handlex.MustExec(qry, name)
	insertedID, err := rst.LastInsertId()

	if err != nil {
		defer logger.Sync()
		logger.Error("Error Insert kelainan",
			zap.String("name", name),
		)
		return data, fmt.Errorf("QUERY_FAILED")
	}

	s := strconv.Itoa(int(insertedID))
	data, err = su.GetKelainanByID(s)
	if err != nil {
		defer logger.Sync()
		logger.Error("Error get kelainan by id",
			zap.String("name", name),
		)
		return data, fmt.Errorf("QUERY_FAILED")
	}

	return data, nil
}

func (su *ServicesMasterKelainan) DeleteKelainan(id string) (models.Kelainan, error) {
	logger, _ := zap.NewProduction()
	var data models.Kelainan
	qry := `UPDATE mcu_kelainangroup
		SET Mcu_KelainanGroupIsActive = 'N',
		Mcu_KelainanGroupLastUpdated = NOW()
		WHERE Mcu_KelainanGroupID = ?`

	rst := dbx.Handlex.MustExec(qry, id)
	_, err := rst.RowsAffected()

	if err != nil {
		defer logger.Sync()
		logger.Error("Error delete kelainan grup",
			zap.String("id", id),
		)
		return data, fmt.Errorf("QUERY_FAILED")
	}

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

	return data, nil
}

func (su *ServicesMasterKelainan) UpdateFlagStatusKelainan(id string, status string) (models.Kelainan, error) {
	logger, _ := zap.NewProduction()
	var data models.Kelainan

	if status == "N" {
		qry := `UPDATE mcu_kelainangroup
		SET Mcu_KelainanGroupFlagActive = 'Y',
		Mcu_KelainanGroupLastUpdated = NOW()
		WHERE Mcu_KelainanGroupID = ?`

		rst := dbx.Handlex.MustExec(qry, id)
		_, err := rst.RowsAffected()

		if err != nil {
			defer logger.Sync()
			logger.Error("Error update status",
				zap.String("id", id),
				zap.String("status", status),
			)
			return data, fmt.Errorf("QUERY_FAILED")
		}
	} else {
		qry := `UPDATE mcu_kelainangroup
		SET Mcu_KelainanGroupFlagActive = 'N',
		Mcu_KelainanGroupLastUpdated = NOW()
		WHERE Mcu_KelainanGroupID = ?`

		rst := dbx.Handlex.MustExec(qry, id)
		_, err := rst.RowsAffected()

		if err != nil {
			defer logger.Sync()
			logger.Error("Error update status",
				zap.String("id", id),
				zap.String("status", status),
			)
			return data, fmt.Errorf("QUERY_FAILED")
		}
	}

	return data, nil
}

// end master group kelainan

// master kelainan detail
func (su *ServicesMasterKelainan) GetListMasterKelainanDetail(id string, searchdetail string, currentPage int, rowPerPage int) ([]models.KelainanDetail, int, error) {
	var KelainanDetailList []models.KelainanDetail
	var totalData int
	offset := (currentPage - 1) * rowPerPage
	prm := "%" + strings.TrimSpace(searchdetail) + "%"

	querytotal := `SELECT COUNT(*) 
		FROM mcu_kelainan 
		WHERE Mcu_KelainanIsActive = 'Y'
		AND Mcu_KelainanMcu_KelainanGroupID = ?
		AND (Mcu_KelainanName LIKE ? OR Mcu_KelainanClasification LIKE ?)`

	if err := dbx.Handlex.Get(&totalData, querytotal, id, prm, prm); err != nil {
		return nil, 0, fmt.Errorf("error query database: %v", err)
	}

	query := `SELECT 
		ROW_NUMBER() OVER (ORDER BY Mcu_KelainanID DESC) AS nomor,
		Mcu_KelainanID,
		Mcu_KelainanName,
		Mcu_KelainanClasification,
		Mcu_KelainanMcu_KelainanGroupID,
		Mcu_KelainanFlagActive,
		Mcu_KelainanUserID,
		Mcu_KelainanCreated,
		Mcu_KelainanLastUpdated
		FROM mcu_kelainan 
		WHERE Mcu_KelainanIsActive = 'Y'
		AND Mcu_KelainanMcu_KelainanGroupID = ?
		AND (Mcu_KelainanName LIKE ? OR Mcu_KelainanClasification LIKE ?)
		ORDER BY Mcu_KelainanID DESC
		LIMIT ? OFFSET ?`

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

	return KelainanDetailList, totalPage, nil
}

func (su *ServicesMasterKelainan) GetKelainanDetailByID(id string) (models.KelainanDetail, error) {
	logger, _ := zap.NewProduction()

	var data models.KelainanDetail
	err := dbx.Handlex.Get(&data, `SELECT * FROM mcu_kelainan
		WHERE Mcu_KelainanID = ?`, id)

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

func (su *ServicesMasterKelainan) AddKelainanDetail(name string, nameclassification string, selectedid string) (models.KelainanDetail, error) {
	logger, _ := zap.NewProduction()
	var data models.KelainanDetail

	qry := `INSERT INTO mcu_kelainan(
		Mcu_KelainanName,
		Mcu_KelainanClasification,
		Mcu_KelainanMcu_KelainanGroupID,
		Mcu_KelainanCreated,
		Mcu_KelainanLastUpdated) VALUES(?,?,?,NOW(),NOW())`
	rst := dbx.Handlex.MustExec(qry, name, nameclassification, selectedid)
	_, err := rst.LastInsertId()

	if err != nil {
		defer logger.Sync()
		logger.Error("Error Insert Kelainan Detail",
			zap.String("name", name),
			zap.String("nameclasification", nameclassification),
			zap.Any("selectedid", selectedid),
		)
		return data, fmt.Errorf("QUERY_FAILED")
	}

	return data, nil
}

func (su *ServicesMasterKelainan) DeleteKelainanDetail(id string) (models.KelainanDetail, error) {
	logger, _ := zap.NewProduction()
	var data models.KelainanDetail

	qry := `UPDATE mcu_kelainan
		SET Mcu_KelainanIsActive = 'N',
		Mcu_KelainanLastUpdated = NOW()
		WHERE Mcu_KelainanID = ?`

	rst := dbx.Handlex.MustExec(qry, id)
	_, err := rst.RowsAffected()

	if err != nil {
		defer logger.Sync()
		logger.Error("Error delete kelainan",
			zap.String("id", id),
		)
		return data, fmt.Errorf("QUERY_FAILED")
	}

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

	return data, nil
}
