package service

import (
	"fmt"
	"syscall"
	"unsafe"
)

// CSN Printer SDK — Go wrapper for CsnPrinterLibs.dll (x64)

var csnDll *syscall.LazyDLL

func InitCSN(dllPath string) error {
	csnDll = syscall.NewLazyDLL(dllPath)
	// Test load
	if err := csnDll.Load(); err != nil {
		return fmt.Errorf("加载 CsnPrinterLibs.dll 失败: %w", err)
	}
	return nil
}

// === Port functions ===

func Csn_EnumUSB() string {
	if csnDll == nil {
		return ""
	}
	buf := make([]byte, 256)
	ret, _, _ := csnDll.NewProc("Port_EnumUSB").Call(
		uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)))
	if ret == 0 {
		return ""
	}
	return string(buf[:ret])
}

func csn_OpenUSB(name string) (uintptr, error) {
	if csnDll == nil {
		return 0, fmt.Errorf("DLL 未加载")
	}
	nameBytes := append([]byte(name), 0)
	ret, _, _ := csnDll.NewProc("Port_OpenUSBIO").Call(
		uintptr(unsafe.Pointer(&nameBytes[0])))
	if ret == 0 {
		return 0, fmt.Errorf("打开 USB 打印机失败: %s", name)
	}
	return ret, nil
}

func csn_OpenPRN(name string) (uintptr, error) {
	if csnDll == nil {
		return 0, fmt.Errorf("DLL 未加载")
	}
	nameBytes := append([]byte(name), 0)
	ret, _, _ := csnDll.NewProc("Port_OpenPRNIO").Call(
		uintptr(unsafe.Pointer(&nameBytes[0])))
	if ret == 0 {
		return 0, fmt.Errorf("打开 Windows 打印机失败: %s", name)
	}
	return ret, nil
}

func csn_SetPort(handle uintptr) {
	if csnDll != nil && handle != 0 {
		csnDll.NewProc("Port_SetPort").Call(handle)
	}
}

func csn_Close(handle uintptr) {
	if csnDll != nil && handle != 0 {
		csnDll.NewProc("Port_ClosePort").Call(handle)
	}
}

// === Print functions ===

func csn_Reset() {
	if csnDll != nil {
		csnDll.NewProc("Pos_Reset").Call()
	}
}

func csn_FeedLine() {
	if csnDll != nil {
		csnDll.NewProc("Pos_FeedLine").Call()
	}
}

func csn_FeedLines(n int) {
	if csnDll != nil {
		csnDll.NewProc("Pos_Feed_N_Line").Call(uintptr(n))
	}
}

func csn_Align(value int) { // 0=左, 1=中, 2=右
	if csnDll != nil {
		csnDll.NewProc("Pos_Align").Call(uintptr(value))
	}
}

func csn_FullCut() {
	if csnDll != nil {
		csnDll.NewProc("Pos_FullCutPaper").Call()
	}
}

func csn_Text(text string, widthTimes, heightTimes, fontType, fontStyle int) {
	if csnDll == nil {
		return
	}
	// Pos_Text(const wchar_t *prnText, int nLan, int nOrgx, int nWidthTimes, int nHeightTimes, int FontType, int nFontStyle)
	wstr, _ := syscall.UTF16FromString(text)
	csnDll.NewProc("Pos_Text").Call(
		uintptr(unsafe.Pointer(&wstr[0])),
		0, // nLan: 0=default
		0, // nOrgx
		uintptr(widthTimes),
		uintptr(heightTimes),
		uintptr(fontType),
		uintptr(fontStyle))
	csn_FeedLine()
}

func csn_QRCode(data string, width int) {
	if csnDll == nil {
		return
	}
	wstr, _ := syscall.UTF16FromString(data)
	csnDll.NewProc("Pos_Qrcode").Call(
		uintptr(unsafe.Pointer(&wstr[0])),
		uintptr(width), 0, 4) // nVersion=0(auto), nErrLevel=4
}

func csn_Barcode(data string, barcodeType int, unitWidth, unitHeight, fontStyle, fontPos int) {
	if csnDll == nil {
		return
	}
	dataBytes := append([]byte(data), 0)
	csnDll.NewProc("Pos_Barcode").Call(
		uintptr(unsafe.Pointer(&dataBytes[0])),
		uintptr(barcodeType), 0, uintptr(unitWidth), uintptr(unitHeight),
		uintptr(fontStyle), uintptr(fontPos))
}
