package test_data

import (
	"bufio"
	"encoding/json"
	"log"
	"math"
	"os"
	"strconv"
	"strings"
	"testData/global"
	"testData/model"
	"testData/request"
)

func LotInAFileSelection(product, lot, pbi, subBatch, step string) ([]string, []string, []string, []string) {
	var fileHandle *model.FileHandled
	global.PostGreSQL.Where("product = ? AND lot = ? AND pbi = ? AND sub_batch = ? AND step = ?",
		product, lot, pbi, subBatch, step).Find(&fileHandle)
	f, err := os.Open(fileHandle.Path)
	if err != nil {
		log.Println(err)
	}
	defer f.Close()
	scanner := bufio.NewScanner(f)
	var selection []string
	datas := make([][]string, 0)
	fieldMap := make(map[string]int)
	for scanner.Scan() {
		line := scanner.Text()
		s := strings.Split(line, ",")
		datas = append(datas, s[:len(s)-1])
		if len(datas) == 1 {
			if step == "CP" {
				selection = s[8 : len(s)-1]
			} else {
				selection = s[6 : len(s)-1]
			}
			for index, cell := range s {
				if index == len(s)-1 {
					continue
				}
				fieldMap[cell] = index
			}
		}
	}
	binMap := make(map[string]interface{})
	hBinMap := make(map[string]int)
	siteMap := make(map[string]int)
	for _, data := range datas {
		siteMap[data[fieldMap["SITE_NUM"]]] = 1
	}
	var sBin, hBin, site []string
	_ = json.Unmarshal([]byte(fileHandle.SbinHbin), &binMap)
	for k, v := range binMap {
		sBin = append(sBin, k)
		sBinInfoMap := v.(map[string]interface{})
		hBinMap[sBinInfoMap["HBin"].(string)] = 1
	}
	for k := range siteMap {
		site = append(site, k)
	}
	for k := range hBinMap {
		hBin = append(hBin, k)
	}
	return selection, sBin, hBin, site
}

func LotInAFile(product, lot, pbi, subBatch, waferID string) ([][]string, map[string]int) {
	var fileHandle *model.FileHandled
	if subBatch != "" {
		global.PostGreSQL.Where("product = ? AND lot = ? AND pbi = ? AND sub_batch = ? AND step != ?",
			product, lot, pbi, subBatch, "RT").Find(&fileHandle)
	} else if waferID != "" {
		global.PostGreSQL.Where("product = ? AND lot = ? AND pbi = ? AND wafer_id = ?",
			product, lot, pbi, waferID).Find(&fileHandle)
	} else {
		return nil, nil
	}

	f, err := os.Open(fileHandle.Path)
	if err != nil {
		log.Println(err)
	}
	defer f.Close()
	xyMap := make(map[string]int)
	scanner := bufio.NewScanner(f)
	datas := make([][]string, 0)
	fieldMap := make(map[string]int)
	for scanner.Scan() {
		line := scanner.Text()
		s := strings.Split(line, ",")
		if strings.Contains(fileHandle.Step, "CP") {
			x := s[fieldMap["X_COORD"]]
			y := s[fieldMap["Y_COORD"]]
			if _, ok := xyMap[x+","+y]; !ok {
				xyMap[x+","+y] = len(datas)
				datas = append(datas, s[:len(s)-1])
			} else {
				datas[xyMap[x+","+y]] = s[:len(s)-1]
			}
		} else {
			datas = append(datas, s[:len(s)-1])
		}
		if len(datas) == 1 {
			for index, cell := range s {
				if index == len(s)-1 {
					continue
				}
				fieldMap[cell] = index
			}
		}
	}
	if len(datas) >= 1 {
		datas = datas[1:]
	}
	return datas, fieldMap
}

func LotInMultipleFilesSelection(product, lot, pbi string) map[string][]string {
	var fileHandles []*model.FileHandled
	global.PostGreSQL.Where("product = ? AND lot = ? AND pbi = ?", product, lot, pbi).Find(&fileHandles)

	datas := make([][]string, 0)
	fieldMap := make(map[string]int)
	binMap := make(map[string]interface{})
	subBatchMap := make(map[string]int)
	waferIDMap := make(map[string]int)
	var selection []string
	var subBatch, waferID []string
	for _, fileHandle := range fileHandles {
		if strings.Contains(fileHandle.Step, "CP") {
			waferIDMap[fileHandle.WaferID] = 1
		} else {
			subBatchMap[fileHandle.SubBatch] = 1
		}

		singleDatas := make([][]string, 0)
		_ = json.Unmarshal([]byte(fileHandle.SbinHbin), &binMap)
		f, err := os.Open(fileHandle.Path)
		if err != nil {
			log.Println(err)
		}
		scanner := bufio.NewScanner(f)
		xyMap := make(map[string]int)
		for scanner.Scan() {
			line := scanner.Text()
			s := strings.Split(line, ",")
			if strings.Contains(fileHandle.Step, "CP") {
				x := s[fieldMap["X_COORD"]]
				y := s[fieldMap["Y_COORD"]]
				if _, ok := xyMap[x+","+y]; !ok {
					xyMap[x+","+y] = len(singleDatas)
					singleDatas = append(singleDatas, s[:len(s)-1])
				}
			} else {
				singleDatas = append(singleDatas, s[:len(s)-1])
			}
			if len(singleDatas) == 1 {
				if strings.Contains(fileHandle.Step, "CP") {
					selection = s[8 : len(s)-1]
				} else {
					selection = s[6 : len(s)-1]
				}
				for index, cell := range s {
					if index == len(s)-1 {
						continue
					}
					fieldMap[cell] = index
				}
			}
		}
		if len(singleDatas) >= 1 {
			singleDatas = singleDatas[1:]
		}
		datas = append(datas, singleDatas...)
		f.Close()
	}

	sBinMap := make(map[string]int)
	siteMap := make(map[string]int)
	for _, data := range datas {
		sBinMap[data[fieldMap["SOFT_BIN"]]] = 1
		siteMap[data[fieldMap["SITE_NUM"]]] = 1
	}
	hBinMap := make(map[string]int)
	var sBin, hBin, site []string
	for k := range sBinMap {
		if _, ok := binMap[k]; ok {
			sBin = append(sBin, k)
			sBinInfoMap := binMap[k].(map[string]interface{})
			hBinMap[sBinInfoMap["HBin"].(string)] = 1
		}
	}
	for k := range siteMap {
		site = append(site, k)
	}
	for k := range hBinMap {
		hBin = append(hBin, k)
	}
	for k := range subBatchMap {
		subBatch = append(subBatch, k)
	}
	for k := range waferIDMap {
		waferID = append(waferID, k)
	}
	res := make(map[string][]string)
	res["selection"] = selection
	res["sbin"] = sBin
	res["hbin"] = hBin
	res["site"] = site
	res["subBatch"] = subBatch
	res["waferID"] = waferID
	return res
}

func LotInMultipleFiles(product, lot, pbi string) ([][]string, map[string]int) {
	var fileHandles []*model.FileHandled
	global.PostGreSQL.Where("product = ? AND lot = ? AND pbi = ? AND step != ?", product, lot, pbi, "RT").Find(&fileHandles)
	datas := make([][]string, 0)
	fieldMap := make(map[string]int)
	for _, fileHandle := range fileHandles {
		fileDatas := make([][]string, 0)
		f, err := os.Open(fileHandle.Path)
		if err != nil {
			log.Println(err)
		}
		xyMap := make(map[string]int)
		scanner := bufio.NewScanner(f)
		for scanner.Scan() {
			line := scanner.Text()
			s := strings.Split(line, ",")
			if strings.Contains(fileHandle.Step, "CP") {
				x := s[fieldMap["X_COORD"]]
				y := s[fieldMap["Y_COORD"]]
				if _, ok := xyMap[x+","+y]; !ok {
					xyMap[x+","+y] = len(fileDatas)
					fileDatas = append(fileDatas, s[:len(s)-1])
				} else {
					fileDatas[xyMap[x+","+y]] = s[:len(s)-1]
				}
			} else {
				fileDatas = append(fileDatas, s[:len(s)-1])
			}
			if len(datas) == 0 {
				for index, cell := range s {
					if index == len(s)-1 {
						continue
					}
					fieldMap[cell] = index
				}
			}
		}
		f.Close()
		if len(fileDatas) >= 1 {
			fileDatas = fileDatas[1:]
		}
		datas = append(datas, fileDatas...)
	}
	return datas, fieldMap
}

func SelectionLimit(req *request.SelectionLimit) (string, string) {
	// CP测试没有子批次
	var fileHandle *model.FileHandled
	global.PostGreSQL.Where("pbi = ? AND product = ? AND lot = ? AND wafer_id = ?", req.PBI, req.Product, req.Lot, req.WaferID).
		Find(&fileHandle)
	f, err := os.Open(fileHandle.Path)
	if err != nil {
		log.Println(err)
		return "", ""
	}
	defer f.Close()
	scanner := bufio.NewScanner(f)
	datas := make([][]string, 0)
	fieldMap := make(map[string]int)
	for scanner.Scan() {
		line := scanner.Text()
		s := strings.Split(line, ",")
		datas = append(datas, s[:len(s)-1])
		if len(datas) == 1 {
			for index, cell := range s {
				if index == len(s)-1 {
					continue
				}
				fieldMap[cell] = index
			}
		}
	}
	if len(datas) >= 1 {
		datas = datas[1:]
	}
	maxStr := strconv.Itoa(math.MinInt)
	minStr := strconv.Itoa(math.MaxInt)
	sbinHbinMap := make(map[string]map[string]string)
	selectionData := make(map[string]int)
	sbinHbinByte := []byte(fileHandle.SbinHbin)
	_ = json.Unmarshal(sbinHbinByte, &sbinHbinMap)
	for _, data := range datas {
		binInfoMap := sbinHbinMap[data[fieldMap["SOFT_BIN"]]]
		// 筛选Site
		var siteInclude bool
		if len(req.Site) == 0 {
			siteInclude = true
		} else {
			for _, site := range req.Site {
				if data[fieldMap["SITE_NUM"]] == site {
					siteInclude = true
					break
				}
			}
		}
		if !siteInclude {
			continue
		}
		// 筛选Soft Bin
		var sBinInclude bool
		if len(req.SBin) == 0 {
			sBinInclude = true
		} else {
			for _, bin := range req.SBin {
				if data[fieldMap["SOFT_BIN"]] == bin {
					sBinInclude = true
					break
				}
			}
		}
		if !sBinInclude {
			continue
		}
		// 筛选Hard Bin
		var hBinInclude bool
		if len(req.HBin) == 0 {
			hBinInclude = true
		} else {
			for _, bin := range req.HBin {
				if binInfoMap["HBin"] == bin {
					hBinInclude = true
					break
				}
			}
		}
		if !hBinInclude {
			continue
		}
		if len(data) > fieldMap[req.Selection] && data[fieldMap[req.Selection]] != "" {
			selectionData[data[fieldMap[req.Selection]]] = 1
		}
	}
	for k := range selectionData {
		maxDecimal, _ := strconv.ParseFloat(maxStr, 64)
		minDecimal, _ := strconv.ParseFloat(minStr, 64)
		dataDecimal, _ := strconv.ParseFloat(k, 64)
		if dataDecimal <= minDecimal {
			minStr = k
		}
		if maxDecimal <= dataDecimal {
			maxStr = k
		}
	}
	if maxStr == strconv.Itoa(math.MinInt) {
		maxStr = "NA"
	}
	if minStr == strconv.Itoa(math.MaxInt) {
		minStr = "NA"
	}
	return maxStr, minStr
}
