package models

import (
	"LAPP_LF_MOM_BACKEND/conf"
	"LAPP_LF_MOM_BACKEND/db"
	"LAPP_LF_MOM_BACKEND/utils"
	"bufio"
	"errors"
	"github.com/tealeg/xlsx"
	"log"
	"os"
	"path"
	"path/filepath"
	"strings"
	"time"
	"xorm.io/core"
)

type PrintTask struct {
	TaskId          string
	TaskFile        string // 保存打印文件的文件路径
	PrinterId       string
	Printhead       Printheadtab
	PrintdetailList []Printdetailtab
}

type ByteFile struct {
	ByteLine []byte
}

// 基于模板将打印任务转换成字节码输出
func (t *PrintTask) GenBytesFile(conf *conf.EnvConfig) ([]ByteFile, error) {
	templatefile := filepath.Join(conf.TemplatePath, t.Printhead.Templatefile)
	f, err := os.Open(templatefile)
	defer f.Close()

	if err != nil {
		log.Printf("failed to open template file: %s due to: %v", templatefile, err)
		return nil, err
	}

	var results []ByteFile
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		linetext := scanner.Text()
		for _, pd := range t.PrintdetailList {
			// -1 替换所有； 1 替换第一个； 5 替换前5个
			linetext = strings.Replace(linetext, pd.Varname, pd.Varvalue, -1)
		}
		var r ByteFile
		r.ByteLine = []byte(linetext)
		results = append(results, r)
	}

	return results, nil
}

// 基于模板将打印任务转换成打印文件输出
func (t *PrintTask) GenPrintFile(conf *conf.EnvConfig) error {
	templatefile := filepath.Join(conf.TemplatePath, t.Printhead.Templatefile)
	f, err := os.Open(templatefile)
	defer f.Close()

	if err != nil {
		log.Printf("GenPrintFile: failed to open template file: %s due to: %v", templatefile, err)
		return err
	}

	// 获取替换文件的内容行
	var results []string
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		linetext := scanner.Text()
		for _, pd := range t.PrintdetailList {
			// -1 替换所有； 1 替换第一个； 5 替换前5个
			linetext = strings.Replace(linetext, pd.Varname, pd.Varpos, -1)
		}
		results = append(results, linetext)
	}

	// 输出替换内容行到新建的打印文件
	fileext := path.Ext(templatefile)
	printfile := t.TaskId + fileext
	t.TaskFile = filepath.Join(conf.Inbox, printfile)
	fn, err := os.Create(t.TaskFile)
	defer fn.Close()
	if err != nil {
		log.Printf("GenPrintFile: failed to create print file for task: %s due to: %v", t.TaskId, err)
		return err
	}
	w := bufio.NewWriter(fn)
	for _, linetext := range results {
		_, err := w.WriteString(linetext)
		if err != nil {
			log.Printf("GenPrintFile: failed to write print file for task: %s due to: %v", t.TaskId, err)
			return err
		}
	}
	w.Flush()

	return nil
}

// 基于模板将打印任务转换成Excel文件输出
func (t *PrintTask) GenExcelFile(conf *conf.EnvConfig) error {
	var (
		templatefile string
		xlFile       *xlsx.File
		sheet        *xlsx.Sheet
		row, col     int
		err          error
	)

	templatefile = filepath.Join(conf.TemplatePath, t.Printhead.Templatefile)
	xlFile, err = xlsx.OpenFile(templatefile)
	if err != nil {
		log.Printf("Failed to open the template file: %s due to: %v", templatefile, err)
		return err
	}

	// 获取模板文件的第一个sheet
	if len(xlFile.Sheets) <= 0 {
		log.Printf("The specified excel template : %s has no sheets!", t.Printhead.Templatefile)
		return errors.New("The specified excel template has no sheets!")
	} else {
		sheet = xlFile.Sheet[xlFile.Sheets[0].Name]
	}

	// 获取替换文件的内容行并替换Excel表格中的内容
	for _, pd := range t.PrintdetailList {
		// 替换单元格对应的内容
		row, col, _ = utils.GetExcelCellIntPos(pd.Varpos)
		sheet.Cell(row, col).Value = pd.Varvalue
	}

	// 输出替换内容行到新建的Excel文件
	fileext := path.Ext(templatefile)
	printfile := t.TaskId + fileext
	t.TaskFile = filepath.Join(conf.Inbox, printfile)
	err = xlFile.Save(t.TaskFile)
	if err != nil {
		log.Printf("GenExcelFile: failed to create excel file for task: %s due to: %v", t.TaskId, err)
		return err
	}

	return nil
}

// 获取打印任务
func (t *PrintTask) GetPrintTaskList(stalist []string, prnlist []string, conf *conf.EnvConfig) ([]PrintTask, error) {
	var (
		tasklist      []PrintTask
		printheadlist []Printheadtab
		err           error
	)
	e := db.Eloquent.Master()
	// 获取所有开口的打印任务头
	if len(prnlist) > 0 {
		err = e.Where("finr = ?", conf.Finr).In("status", stalist).In("printerid", prnlist).OrderBy("printheadid").Find(&printheadlist)
	} else {
		err = e.Where("finr = ?", conf.Finr).In("status", stalist).OrderBy("printheadid").Find(&printheadlist)
	}
	if err != nil {
		log.Printf("failed to query printheadtab due to: %v", err)
		return nil, err
	}
	// 遍历打印任务头
	for _, p := range printheadlist {
		var t PrintTask
		t.Printhead = p
		t.Printhead.Clipped()
		t.TaskId = t.Printhead.Printheadid
		t.PrinterId = t.Printhead.Printerid

		var pdlist []Printdetailtab
		err := e.Where("finr = ? and printheadid = ?", conf.Finr, t.Printhead.Printheadid).OrderBy("pos").Find(&pdlist)
		if err != nil {
			log.Printf("failed to query printdetailtab due to: %v", err)
			return nil, err
		}
		for _, pd := range pdlist {
			pd.Clipped()
			t.PrintdetailList = append(t.PrintdetailList, pd)
		}

		tasklist = append(tasklist, t)
	}

	return tasklist, nil
}

// 关闭打印任务
func (t *PrintTask) ChangePrintTaskStatus(task PrintTask, newStatus string) error {
	e := db.Eloquent.Master()
	task.Printhead.Status = newStatus
	task.Printhead.Lastmodif = time.Now().Format("20060102150405")
	_, err := e.Id(core.PK{task.Printhead.Finr, task.Printhead.Printheadid}).Cols("status", "lastmodif").Update(&task.Printhead)
	if err != nil {
		log.Printf("failed to change printerheadtab status for printheadid: %s", task.Printhead.Printheadid)
		return err
	}
	return nil
}
