package mcu_corporate_services

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

	"go.uber.org/zap"
)

type TabKelainanNonLabServices struct {
	TabKelainanNonLabStore db.AppStore
}

func NewTabKelainanNonLabServices(store db.AppStore) *TabKelainanNonLabServices {
	return &TabKelainanNonLabServices{
		TabKelainanNonLabStore: store,
	}
}

func (tknl *TabKelainanNonLabServices) 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 = 4
	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 (tknl *TabKelainanNonLabServices) ConfBarchartVertical(title string, data []models.KelNonLabModel) (models.BarchartV2, error) {
	chartData := models.BarDataset{
		Source: [][]interface{}{
			{"score", "amount", "product"},
		},
	}

	isEmpty := ""
	if len(data) == 0 {
		isEmpty = "Data tidak ditemukan"
	}

	cnt := len(data)
	for idx, d := range data {
		// if len(d.Test) > 30 {
		// 	var newText = d.Test[:30] + "-  \n" + d.Test[30:]
		// 	chartData.Source = append(chartData.Source, []interface{}{
		// 		idx, d.Total, newText,
		// 	})
		// 	continue
		// }
		newText := utils.SplitStrings(d.Test, 2)
		chartData.Source = append(chartData.Source, []interface{}{
			idx, d.Total, newText,
		})
	}

	option := models.BarchartV2{
		Title: struct {
			Text string "json:\"text\""
			Left string `json:"left"`
		}{
			Text: title,
			Left: "center",
		},
		Dataset: struct {
			Source [][]interface{} "json:\"source\""
		}{chartData.Source},
		Grid: struct {
			ContainLabel bool "json:\"containLabel\""
		}{true},
		XAxis: struct {
			Name      string "json:\"name\""
			Type      string "json:\"type\""
			AxisLabel struct {
				Interval int "json:\"interval\""
				Rotate   int "json:\"rotate\""
			} "json:\"axisLabel\""
		}{
			Name: "",
			Type: "category",
			AxisLabel: struct {
				Interval int "json:\"interval\""
				Rotate   int "json:\"rotate\""
			}{
				Interval: 0,
				Rotate:   0,
			},
		},
		YAxis: struct {
			Type          string "json:\"type\""
			Name          string "json:\"name\""
			NameTextStyle struct {
				Align string "json:\"align\""
			} "json:\"nameTextStyle\""
			NameGap int "json:\"nameGap\""
		}{
			Type: "value",
			Name: "",
			NameTextStyle: struct {
				Align string "json:\"align\""
			}{
				Align: "right",
			},
			NameGap: 20,
		},
		VisualMap: struct {
			Orient    string "json:\"orient\""
			Left      string "json:\"left\""
			Min       int    "json:\"min\""
			Max       int    "json:\"max\""
			Dimension int    "json:\"dimension\""
			Show      bool   "json:\"show\""
			InRange   struct {
				Color []string "json:\"color\""
			} "json:\"inRange\""
		}{
			Orient:    "horizontal",
			Left:      "center",
			Min:       0,
			Max:       cnt,
			Dimension: 0,
			Show:      false,
			InRange: struct {
				Color []string "json:\"color\""
			}{
				Color: []string{"#035bff", "#42aaf5", "#00eaf2"},
			},
		},
		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:  "inside",
					Show:      true,
					Formatter: "{@[1]}",
				},
				Type: "bar",
				Encode: struct {
					X string "json:\"x\""
					Y string "json:\"y\""
				}{
					X: "product",
					Y: "amount",
				},
			},
		},
		Tooltip: struct {
			Trigger     string "json:\"trigger\""
			AxisPointer struct {
				Type string "json:\"type\""
			} "json:\"axisPointer\""
		}{
			Trigger: "axis",
			AxisPointer: struct {
				Type string "json:\"type\""
			}{
				Type: "shadow",
			},
		},
		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 (tknl *TabKelainanNonLabServices) GetDataKelNonLab(mcuID string) (models.Barchart, error) {
	logger, _ := zap.NewProduction()
	var option models.Barchart
	var data []models.KelNonLabModel

	q := `
		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
		ORDER BY total DESC
		LIMIT 10
	`

	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 Non Lab (10 Terbesar)"
	chartData := models.BarDataset{
		Source: [][]interface{}{
			{"score", "amount", "product", "percentage"},
		},
	}

	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)
	}

	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 := tknl.GetBarChartConf(title, chartData)
	if err != nil {
		return option, fmt.Errorf("error insert data to barchart %v", err)
	}

	return option, nil
}

func (tknl *TabKelainanNonLabServices) GetThoraxPA(mcuID string) (models.BarchartV2, error) {
	logger, _ := zap.NewProduction()
	var option models.BarchartV2
	var data []models.KelNonLabModel

	q := `
		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 AND Nat_TestID = 5798
		where T_KelainanNonLabIsActive = 'Y' and T_OrderHeaderMgm_McuID = ?
		group by Mcu_KelainanID
		ORDER BY total DESC
		LIMIT 10
	`

	if err := dbx.Handlex.Select(&data, q, mcuID); err != nil {
		return option, fmt.Errorf("error get data thorax pa %v", err)
	}
	defer logger.Sync()
	logger.Info("resp data", zap.Any("data", data))

	title := "Thorax PA"
	option, err := tknl.ConfBarchartVertical(title, data)
	if err != nil {
		return option, fmt.Errorf("error insert data into chart %v", err)
	}

	return option, nil
}

func (tknl *TabKelainanNonLabServices) GetGangguanJantung(mcuID string) (models.BarchartV2, error) {
	var option models.BarchartV2
	var data []models.KelNonLabModel

	q := `
		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 AND
		Mcu_KelainanGroupID = 10
		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
		ORDER BY total DESC	
		LIMIT 10
	`
	if err := dbx.Handlex.Select(&data, q, mcuID); err != nil {
		return option, fmt.Errorf("error get data gangguan jantung %v", err)
	}

	title := "Gangguan Jantung"
	option, err := tknl.ConfBarchartVertical(title, data)
	if err != nil {
		return option, fmt.Errorf("error insert data into chart %v", err)
	}

	return option, nil
}

func (tknl *TabKelainanNonLabServices) GetAutospirometri(mcuID string) (models.BarchartV2, error) {
	var option models.BarchartV2
	var data []models.KelNonLabModel

	q := `
		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 AND Nat_TestID = 5321
		where T_KelainanNonLabIsActive = 'Y' and T_OrderHeaderMgm_McuID = ?
		group by Mcu_KelainanID
		ORDER BY total DESC
		LIMIT 10
	`
	if err := dbx.Handlex.Select(&data, q, mcuID); err != nil {
		return option, fmt.Errorf("error get data autspirometri %v", err)
	}

	title := "Spirometri"
	option, err := tknl.ConfBarchartVertical(title, data)
	if err != nil {
		return option, fmt.Errorf("error insert data into chart %v", err)
	}

	return option, nil
}

func (tknl *TabKelainanNonLabServices) GetPendengaran(mcuID string) (models.BarchartV2, error) {
	var option models.BarchartV2
	var data []models.KelNonLabModel

	q := `
		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 AND Nat_TestID = 5308
		where T_KelainanNonLabIsActive = 'Y' and T_OrderHeaderMgm_McuID = ?
		group by Mcu_KelainanID
		ORDER BY total DESC
		LIMIT 10
	`
	if err := dbx.Handlex.Select(&data, q, mcuID); err != nil {
		return option, fmt.Errorf("error get data gangguan pendengaran %v", err)
	}

	title := "Gangguan Pendengaran"
	option, err := tknl.ConfBarchartVertical(title, data)
	if err != nil {
		return option, fmt.Errorf("error insert data into chart %v", err)
	}

	return option, nil
}

func (tknl *TabKelainanNonLabServices) GetChartRenderNonLab(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_ImageGrafikGroupResult = "NONLAB"
	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
}
