package mcu_corporate_services

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

	"go.uber.org/zap"
)

type TabKelainanGlobalServices struct {
	TabKelainanGlobalServicesStore db.AppStore
}

func NewTabKelainanGlobalServices(store db.AppStore) *TabKelainanGlobalServices {
	return &TabKelainanGlobalServices{
		TabKelainanGlobalServicesStore: store,
	}
}

func (tkg *TabKelainanGlobalServices) GetBarChartConf(title string, data models.BarDataset) (models.Barchart, error) {
	isEmpty := ""
	if len(data.Source) <= 1 {
		isEmpty = "Data tidak ditemukan"
	}

	option := models.Barchart{}
	option.Title = struct {
		Text string "json:\"text\""
		Left string `json:"left"`
	}{
		Text: title,
		Left: "center",
	}
	option.Dataset = data
	option.Grid.ContainLabel = true
	option.XAxis.Name = "person"
	option.YAxis.Type = "category"
	option.VisualMap.Orient = "horizontal"
	option.VisualMap.Left = "center"
	option.VisualMap.Min = 0
	option.VisualMap.Max = 10
	option.VisualMap.Show = false
	option.VisualMap.Dimension = 0
	option.VisualMap.InRange.Color = []string{"#035bff", "#42aaf5", "#00eaf2"}
	option.Series = []struct {
		Label struct {
			Position  string "json:\"position\""
			Show      bool   "json:\"show\""
			Formatter string "json:\"formatter\""
		} "json:\"label\""
		Type   string "json:\"type\""
		Encode struct {
			X string "json:\"x\""
			Y string "json:\"y\""
		} "json:\"encode\""
	}{
		{
			Label: struct {
				Position  string "json:\"position\""
				Show      bool   "json:\"show\""
				Formatter string "json:\"formatter\""
			}{
				Position:  "right",
				Show:      true,
				Formatter: "{@[3]} %",
			},
			Type: "bar",
			Encode: struct {
				X string "json:\"x\""
				Y string "json:\"y\""
			}{
				X: "amount",
				Y: "product",
			},
		},
	}
	option.Tooltip = struct {
		Trigger     string "json:\"trigger\""
		AxisPointer struct {
			Type string "json:\"type\""
		} "json:\"axisPointer\""
	}{
		Trigger: "axis",
		AxisPointer: struct {
			Type string "json:\"type\""
		}{
			Type: "shadow",
		},
	}
	option.Graphic = struct {
		Type  string "json:\"type\""
		Left  string "json:\"left\""
		Top   string "json:\"top\""
		Style struct {
			Text       string "json:\"text\""
			FontSize   string "json:\"fontSize\""
			FontWeight string "json:\"fontWeight\""
		} "json:\"style\""
	}{
		Type: "text",
		Left: "center",
		Top:  "middle",
		Style: struct {
			Text       string "json:\"text\""
			FontSize   string "json:\"fontSize\""
			FontWeight string "json:\"fontWeight\""
		}{
			Text:       isEmpty,
			FontSize:   "15",
			FontWeight: "bold",
		},
	}

	return option, nil
}

func (tkg *TabKelainanGlobalServices) GetKelainanGlobalMCU(mcuID string) (models.Barchart, error) {
	logger, _ := zap.NewProduction()
	var option models.Barchart
	var data []models.KelainanGlobalMCUModel

	q := `
	SELECT
	IFNULL(Nat_TestName ,Mcu_KelainanGroupName) AS Test,
	COUNT(Mgm_HeaderT_OrderHeaderID) AS total
	FROM mgm_header
	JOIN mgm_detail ON Mgm_DetailMgm_HeaderID = Mgm_HeaderID AND Mgm_DetailIsActive = 'Y'
	JOIN mcu_kelainan ON Mgm_DetailMcu_KelainanID = Mcu_KelainanID
	JOIN mcu_kelainangroup ON Mgm_DetailMcu_KelainanGroupID = Mcu_KelainanGroupID
	LEFT JOIN nat_test ON Nat_TestCode = Mgm_HeaderNat_TestCode 
	WHERE Mgm_HeaderIsActive = 'Y' AND Mgm_HeaderMgm_McuID = ?
	AND Mgm_HeaderIsNormal = 'N' 
	GROUP BY Mcu_KelainanGroupID ORDER BY COUNT(Mgm_HeaderT_OrderHeaderID) DESC	
	`
	// Mgm_DetailMcu_KelainanID ->> versi php
	// Mcu_KelainanGroupID ->> versi excel
	if err := dbx.Handlex.Select(&data, q, mcuID); err != nil {
		return option, fmt.Errorf("error get data kelainan global mcu %v", err)
	}
	defer logger.Sync()
	logger.Info("resp data", zap.Any("data", data))

	title := "Kelainan MCU"
	chartData := models.BarDataset{
		Source: [][]interface{}{
			{"score", "amount", "product", "percentage"},
		},
	}

	max := 1
	for _, d := range data {
		if d.Total >= max {
			max = d.Total
		}
	}

	for i, d := range data {
		percentage := float64(d.Total) / float64(max) * 100
		roundedPercentage := math.Round(percentage*100) / 100
		percentStr := strconv.FormatFloat(roundedPercentage, 'f', -1, 64)
		chartData.Source = append(chartData.Source, []interface{}{
			i, d.Total, d.Test, percentStr,
		})
	}

	option, err := tkg.GetBarChartConf(title, chartData)
	if err != nil {
		return option, fmt.Errorf("error insert data to barchart %v", err)
	}

	return option, nil
}

func (tkg *TabKelainanGlobalServices) GetKelainanFisik(mcuID string) (models.Barchart, error) {
	logger, _ := zap.NewProduction()
	var option models.Barchart
	var data []models.KelainanGlobalFisikModel

	q := `
	SELECT 
	Mcu_KelainanName, 
	COUNT(Mgm_HeaderT_OrderHeaderID)  AS total
	FROM mgm_header
	JOIN mgm_detail ON Mgm_DetailMgm_HeaderID = Mgm_HeaderID  
	AND Mgm_DetailIsActive = 'Y'
	JOIN mcu_kelainan ON Mgm_DetailMcu_KelainanID = Mcu_KelainanID
	JOIN mcu_kelainangroup ON Mgm_DetailMcu_KelainanGroupID = Mcu_KelainanGroupID
	WHERE Mgm_HeaderIsActive = 'Y'  AND Mgm_HeaderMgm_McuID = ?
	AND Mgm_HeaderType = 'F'
	AND Mgm_HeaderIsNormal = 'N'
	GROUP BY Mcu_KelainanID  
	ORDER BY total DESC	
	`
	if err := dbx.Handlex.Select(&data, q, mcuID); err != nil {
		return option, fmt.Errorf("error get data kelainan global fisik %v", err)
	}
	defer logger.Sync()
	logger.Info("resp data", zap.Any("data", data))

	title := "Kelainan Fisik"
	chartData := models.BarDataset{
		Source: [][]interface{}{
			{"score", "amount", "product", "percentage"},
		},
	}

	max := 1
	for _, d := range data {
		if d.Total >= max {
			max = d.Total
		}
	}

	for _, d := range data {
		percentage := float64(d.Total) / float64(max) * 100
		roundedPercentage := math.Round(percentage*100) / 100
		percentStr := strconv.FormatFloat(roundedPercentage, 'f', -1, 64)
		chartData.Source = append(chartData.Source, []interface{}{
			d.Total, d.Total, d.Mcu_KelainanName, percentStr,
		})
	}

	option, err := tkg.GetBarChartConf(title, chartData)
	if err != nil {
		return option, nil
	}

	return option, nil
}

func (tkg *TabKelainanGlobalServices) GetKelainanGlobalV2(mcuID string) (models.Barchart, error) {
	var option models.Barchart
	var data []models.KelainanGlobalModel

	q := `
		SELECT * FROM (
			SELECT Mcu_KelainanID,
			Mcu_KelainanName as Test,
			count(distinct T_OrderHeaderID) as Total
			FROM t_kelainan_lab
			JOIN t_orderheader ON T_KelainanLabT_OrderHeaderID = T_OrderHeaderID
			JOIN mcu_summarylab ON T_KelainanLabMcu_SummaryLabID = Mcu_SummaryLabID        
			join mcu_kelainan on Mcu_summaryLabMcu_KelainanID = Mcu_KelainanID
			join mcu_kelainangroup on Mcu_KelainanMcu_KelainanGroupID = Mcu_KelainanGroupID
			JOIN nat_test ON Mcu_SummaryLabNat_TestID = Nat_TestID AND T_KelainanLabNat_TestID = Mcu_SummaryLabNat_TestID
			where T_KelainanLabIsActive = 'Y'   and T_OrderHeaderMgm_McuID = ?
			group by Mcu_KelainanID
			UNION
			SELECT Mcu_KelainanID, Mcu_KelainanName as Test,
			count(distinct T_OrderHeaderID) as Total
			FROM t_kelainan_nonlab
			JOIN t_orderheader ON T_KelainanNonLabT_OrderHeaderID = T_OrderHeaderID
			JOIN mcu_summarynonlab ON T_KelainanNonLabMcu_SummaryNonlabID = Mcu_SummaryNonlabID        
			join mcu_kelainan on Mcu_SummaryNonlabMcu_KelainanID = Mcu_KelainanID
			join mcu_kelainangroup on Mcu_KelainanMcu_KelainanGroupID = Mcu_KelainanGroupID
			JOIN nat_test ON Mcu_SummaryNonlabNat_TestID = Nat_TestID AND 
			T_KelainanNonLabNat_TestID = Mcu_SummaryNonlabNat_TestID
			where T_KelainanNonLabIsActive = 'Y'   and T_OrderHeaderMgm_McuID = ?
			group by Mcu_KelainanID
			UNION 
			SELECT Mcu_KelainanID, Mcu_KelainanName as Test,
			count(distinct T_OrderHeaderID) as Total
			FROM t_kelainan_fisik
			JOIN t_orderheader ON T_KelainanFiskT_OrderHeaderID = T_OrderHeaderID
			JOIN mcu_summaryfisik ON T_KelainanFiskMcu_SummaryFisikID = Mcu_SummaryFisikID AND 
			Mcu_SummaryFisikID NOT IN (63,67,68,69,70,71,72,73)
			join mcu_kelainan on Mcu_SummaryFisikMcu_KelainanID = Mcu_KelainanID
			join mcu_kelainangroup on Mcu_KelainanMcu_KelainanGroupID = Mcu_KelainanGroupID
			where T_KelainanFiskIsActive = 'Y' and T_OrderHeaderMgm_McuID = ? AND
			Mcu_KelainanClasification NOT IN ('who','kemenkes','JNC-VIII','ESC/ESH')
			group by Mcu_KelainanID
		) a

		ORDER BY  total DESC
		LIMIT 10
	`
	if err := dbx.Handlex.Select(&data, q, mcuID, mcuID, mcuID); err != nil {
		return option, fmt.Errorf("error get data kelainan global %v", err)
	}

	var jumlahPeserta models.TotalPesertaModel

	q = `
		SELECT 
		COUNT(distinct(T_OrderHeaderID)) as peserta,
		COUNT( distinct(Mcu_PreregisterPatientsM_PatientID)) as total
		FROM mcu_preregister_patients
		LEFT JOIN t_orderheader ON Mcu_PreregisterPatientsT_OrderHeaderID = T_OrderHeaderID AND
		T_OrderHeaderIsActive = 'Y'
		WHERE
		Mcu_PreregisterPatientsMgm_McuID = ? AND
		Mcu_PreregisterPatientsIsActive = 'Y'
	`
	if err := dbx.Handlex.Get(&jumlahPeserta, q, mcuID); err != nil {
		return option, fmt.Errorf("error get jumlah peserta %v", err)
	}

	title := "Kelainan Global (10 Terbesar)"
	chartData := models.BarDataset{
		Source: [][]interface{}{
			{"score", "amount", "product", "percentage"},
		},
	}

	for i, d := range data {
		percentage := float64(d.Total) / float64(jumlahPeserta.Peserta) * 100
		roundedPercentage := math.Round(percentage*100) / 100
		percentStr := strconv.FormatFloat(roundedPercentage, 'f', -1, 64)
		newText := utils.SplitStrings(d.Test, 2)
		chartData.Source = append(chartData.Source, []interface{}{
			i, d.Total, newText, percentStr,
		})
	}

	option, err := tkg.GetBarChartConf(title, chartData)
	if err != nil {
		return option, fmt.Errorf("error insert data to barchart %v", err)
	}

	return option, nil
}

func (tkg *TabKelainanGlobalServices) GetChartRenderGlobal(mcuID string) ([]models.McuTabModels, error) {
	var ret []models.McuTabModels

	q := `
	SELECT
	Mcu_ImageGrafikGroupResult,
	Mcu_ImageGrafikGroupMenu,
	Mcu_ImageGrafikName,
	Mcu_ImageGrafikJsonRender
	FROM mgm_mcugrafik
	JOIN mcu_image_grafik ON Mcu_ImageGrafikID = Mgm_McuGrafikMcu_ImageGrafikID
	WHERE Mgm_McuGrafikMgm_McuID = ?
	AND Mcu_ImageGrafikGroupMenu = "GLOBAL"
	AND Mgm_McuGrafikIsActive = 'Y'
	ORDER BY Mcu_ImageGrafikID
	`
	if err := dbx.Handlex.Select(&ret, q, mcuID); err != nil {
		return ret, fmt.Errorf("error get data tab peserta: %v", err)
	}

	return ret, nil
}
