package service

import (
	"fmt"
	"time"
	"wails-app/internal/dao"
	"wails-app/internal/global"
)

const sdkDllPath = `D:\lq\资料\停车场 道闸 车牌识别 收费机\票机自制\打印机\EMD807嵌入式热敏票据打印模组\5、SDK指令集\Win_SDK_Demo_2023_08_14\Win_SDK_Demo_2023_08_14\lib\x64\CsnPrinterLibs.dll`

type PrintService struct{}

func NewPrintService() *PrintService { return &PrintService{} }

func (s *PrintService) PrintTicket(printerID uint, lotName, channelCode, plateNo string, ticketID uint, ticketNo string) error {
	var printer dao.Printer
	if err := global.GVA_DB.First(&printer, printerID).Error; err != nil {
		return fmt.Errorf("打印机未配置: id=%d", printerID)
	}

	var err error
	var srl *SerialPrinter
	var usbHandle uintptr
	useCSN := false

	if len(printer.PortName) >= 3 && printer.PortName[:3] == "COM" {
		srl, err = NewSerialPrinter(printer.PortName, printer.BaudRate)
		if err == nil {
			defer srl.Close()
		}
	} else {
		err = InitCSN(sdkDllPath)
		if err != nil {
			return fmt.Errorf("加载 CSN DLL 失败: %w (path=%s)", err, sdkDllPath)
		}
		// 尝试 OpenUSB → OpenPRN
		name := printer.PortName
		if name == "USB" || name == "auto" || name == "" {
			name = Csn_EnumUSB()
		}
		usbHandle, err = csn_OpenUSB(name)
		if err != nil {
			usbHandle, err = csn_OpenPRN(name)
		}
		if err != nil {
			return fmt.Errorf("打开打印机失败: %w (name=%s)", err, name)
		}
		useCSN = true
		csn_SetPort(usbHandle) // 激活端口！
		defer csn_Close(usbHandle)
	}

	now := time.Now().Format("02-01-2006 15:04:05")
	slipNo := fmt.Sprintf("%d", ticketID)

	if useCSN {
		csn_Reset()
		csn_Align(1)
		csn_Text("PARKING TICKET", 2, 2, 0, 0)
		csn_Text("", 1, 1, 0, 0)
		csn_Text(lotName, 1, 1, 0, 0)
		csn_Text("A-General Car", 1, 1, 0, 0)
		csn_Text("", 1, 1, 0, 0)
		csn_Text("PARK AT YOUR OWN RISK", 1, 1, 0, 1)
		csn_Text("================================", 1, 1, 0, 0)
		csn_Align(0)
		csn_Text("In-Time::"+now, 1, 1, 0, 0)
		if channelCode != "" { csn_Text("InGate::"+channelCode, 1, 1, 0, 0) }
		if plateNo != "" { csn_Text("Veh No::"+plateNo, 1, 1, 0, 0) }
		csn_Text("================================", 1, 1, 0, 0)
		csn_Text("Slip No::"+slipNo, 1, 1, 0, 0)
		csn_Text("================================", 1, 1, 0, 0)
		csn_Align(1)
		csn_FeedLine()
		csn_QRCode(ticketNo, 4)
		csn_FeedLine()
		csn_Text("SCAN AND PAY WITH", 1, 1, 0, 0)
		csn_Text("NEW THE CANADIA BANK APP", 1, 1, 0, 0)
		csn_FeedLines(3)
		csn_FullCut()
		global.GVA_DB.Model(&printer).Update("status", "online")
		return nil
	}

	// Serial ESC/POS fallback
	write := func(data []byte) { srl.Write(data) }
	line32 := "================================"
	write(InitCmd); write(AlignCenterCmd); write(DoubleHeightCmd); write(BoldOnCmd)
	write(ESCPOS_Text("PARKING TICKET"))
	write(BoldOffCmd); write(NormalCmd)
	write(ESCPOS_Text("")); write(ESCPOS_Text(lotName))
	write(ESCPOS_Text("A-General Car")); write(ESCPOS_Text(""))
	write(ESCPOS_Text("PARK AT YOUR OWN RISK")); write(ESCPOS_Text(line32))
	write(AlignLeftCmd)
	write(ESCPOS_Text("In-Time::"+now))
	if channelCode != "" { write(ESCPOS_Text("InGate::"+channelCode)) }
	if plateNo != "" { write(ESCPOS_Text("Veh No::"+plateNo)) }
	write(ESCPOS_Text(line32)); write(ESCPOS_Text("Slip No::"+slipNo)); write(ESCPOS_Text(line32))
	write(AlignCenterCmd); write(ESCPOS_Text(""))
	write(ESCPOS_QRCode(ticketNo)); write(ESCPOS_Text(""))
	write(AlignCenterCmd)
	write(ESCPOS_Text("SCAN AND PAY WITH"))
	write(ESCPOS_Text("NEW THE CANADIA BANK APP"))
	write(InitCmd); write(ESCPOS_Text("")); write(ESCPOS_Text("")); write(ESCPOS_Text(""))
	write(CutPaperCmd)

	global.GVA_DB.Model(&printer).Update("status", "online")
	return nil
}
