// Copyright © 2023 OpenIM. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package msg

import (
	"context"
	"fmt"
	"image"
	"image/color"
	_ "image/jpeg"
	_ "image/png"
	"math"
	"os"
	"sync"

	"github.com/makiuchi-d/gozxing"
	"github.com/makiuchi-d/gozxing/qrcode"
	"github.com/openimsdk/tools/log"
)

// openImageFile 打开图片文件
func openImageFile(imagePath string) (*os.File, error) {
	file, err := os.Open(imagePath)
	if err != nil {
		return nil, fmt.Errorf("无法打开文件: %v", err)
	}
	return file, nil
}

// QRDecoder 二维码解码器接口
type QRDecoder interface {
	Name() string
	Decode(ctx context.Context, imagePath string, logPrefix string) (bool, error) // 返回是否检测到二维码
}

// ============================================================================
// QuircDecoder - Quirc解码器包装
// ============================================================================

// QuircDecoder 使用 Quirc 库的解码器
type QuircDecoder struct {
	detectFunc func([]uint8, int, int) (bool, error)
}

// NewQuircDecoder 创建Quirc解码器
func NewQuircDecoder(detectFunc func([]uint8, int, int) (bool, error)) *QuircDecoder {
	return &QuircDecoder{detectFunc: detectFunc}
}

func (d *QuircDecoder) Name() string {
	return "quirc"
}

func (d *QuircDecoder) Decode(ctx context.Context, imagePath string, logPrefix string) (bool, error) {
	if d.detectFunc == nil {
		return false, fmt.Errorf("quirc 解码器未启用")
	}

	// 打开并解码图片
	file, err := openImageFile(imagePath)
	if err != nil {
		log.ZError(ctx, "打开图片文件失败", err, "imagePath", imagePath)
		return false, err
	}
	defer file.Close()

	img, _, err := image.Decode(file)
	if err != nil {
		log.ZError(ctx, "解码图片失败", err, "imagePath", imagePath)
		return false, fmt.Errorf("无法解码图片: %v", err)
	}

	bounds := img.Bounds()
	width := bounds.Dx()
	height := bounds.Dy()

	// 转换为灰度图
	grayData := convertToGrayscale(img, width, height)

	// 调用Quirc检测
	hasQRCode, err := d.detectFunc(grayData, width, height)
	if err != nil {
		log.ZError(ctx, "Quirc检测失败", err, "width", width, "height", height)
		return false, err
	}

	return hasQRCode, nil
}

// ============================================================================
// CustomQRDecoder - 自定义解码器（兼容圆形角）
// ============================================================================

// CustomQRDecoder 自定义二维码解码器，兼容圆形角等特殊格式
type CustomQRDecoder struct{}

func (d *CustomQRDecoder) Name() string {
	return "custom (圆形角兼容)"
}

// Decode 解码二维码，返回是否检测到二维码
func (d *CustomQRDecoder) Decode(ctx context.Context, imagePath string, logPrefix string) (bool, error) {
	file, err := openImageFile(imagePath)
	if err != nil {
		log.ZError(ctx, "打开图片文件失败", err, "imagePath", imagePath)
		return false, fmt.Errorf("无法打开文件: %v", err)
	}
	defer file.Close()

	img, _, err := image.Decode(file)
	if err != nil {
		log.ZError(ctx, "解码图片失败", err, "imagePath", imagePath)
		return false, fmt.Errorf("无法解码图片: %v", err)
	}

	bounds := img.Bounds()
	width := bounds.Dx()
	height := bounds.Dy()

	reader := qrcode.NewQRCodeReader()
	hints := make(map[gozxing.DecodeHintType]interface{})
	hints[gozxing.DecodeHintType_TRY_HARDER] = true
	hints[gozxing.DecodeHintType_PURE_BARCODE] = false
	hints[gozxing.DecodeHintType_CHARACTER_SET] = "UTF-8"

	// 尝试直接解码
	bitmap, err := gozxing.NewBinaryBitmapFromImage(img)
	if err == nil {
		if _, err := reader.Decode(bitmap, hints); err == nil {
			return true, nil
		}

		// 尝试不使用PURE_BARCODE
		delete(hints, gozxing.DecodeHintType_PURE_BARCODE)
		if _, err := reader.Decode(bitmap, hints); err == nil {
			return true, nil
		}
		hints[gozxing.DecodeHintType_PURE_BARCODE] = false
	}

	// 尝试多尺度缩放
	scales := []float64{1.0, 1.5, 2.0, 0.75, 0.5}
	for _, scale := range scales {
		scaledImg := scaleImage(img, width, height, scale)
		if scaledImg == nil {
			continue
		}

		scaledBitmap, err := gozxing.NewBinaryBitmapFromImage(scaledImg)
		if err == nil {
			if _, err := reader.Decode(scaledBitmap, hints); err == nil {
				return true, nil
			}
		}
	}

	// 转换为灰度图进行预处理
	grayData := convertToGrayscale(img, width, height)

	// 尝试多种预处理方法
	preprocessMethods := []struct {
		name string
		fn   func([]byte, int, int) []byte
	}{
		{"Otsu二值化", enhanceImageOtsu},
		{"标准增强", enhanceImage},
		{"强对比度", enhanceImageStrong},
		{"圆形角处理", enhanceImageForRoundedCorners},
		{"去噪+锐化", enhanceImageDenoiseSharpen},
		{"高斯模糊+锐化", enhanceImageGaussianSharpen},
	}

	scalesForPreprocessed := []float64{1.0, 2.0, 1.5, 1.2, 0.8}

	for _, method := range preprocessMethods {
		processed := method.fn(grayData, width, height)

		// 快速检测定位图案
		corners := detectCornersFast(processed, width, height)
		if len(corners) < 2 {
			// 如果没有检测到足够的定位图案，仍然尝试解码
		}

		processedImg := createImageFromGrayscale(processed, width, height)
		bitmap2, err := gozxing.NewBinaryBitmapFromImage(processedImg)
		if err == nil {
			if _, err := reader.Decode(bitmap2, hints); err == nil {
				return true, nil
			}
			delete(hints, gozxing.DecodeHintType_PURE_BARCODE)
			if _, err := reader.Decode(bitmap2, hints); err == nil {
				return true, nil
			}
			hints[gozxing.DecodeHintType_PURE_BARCODE] = false
		}

		// 对预处理后的图像进行多尺度缩放
		for _, scale := range scalesForPreprocessed {
			scaledProcessed := scaleGrayscaleImage(processed, width, height, scale)
			if scaledProcessed == nil {
				continue
			}
			scaledImg := createImageFromGrayscale(scaledProcessed.data, scaledProcessed.width, scaledProcessed.height)
			scaledBitmap, err := gozxing.NewBinaryBitmapFromImage(scaledImg)
			if err == nil {
				if _, err := reader.Decode(scaledBitmap, hints); err == nil {
					return true, nil
				}
				delete(hints, gozxing.DecodeHintType_PURE_BARCODE)
				if _, err := reader.Decode(scaledBitmap, hints); err == nil {
					return true, nil
				}
				hints[gozxing.DecodeHintType_PURE_BARCODE] = false
			}
		}
	}

	return false, nil
}

// ============================================================================
// ParallelQRDecoder - 并行解码器
// ============================================================================

// ParallelQRDecoder 并行解码器，同时运行 quirc 和 custom 解码器
type ParallelQRDecoder struct {
	quircDecoder  QRDecoder
	customDecoder QRDecoder
}

// NewParallelQRDecoder 创建并行解码器
func NewParallelQRDecoder(quircDecoder, customDecoder QRDecoder) *ParallelQRDecoder {
	return &ParallelQRDecoder{
		quircDecoder:  quircDecoder,
		customDecoder: customDecoder,
	}
}

func (d *ParallelQRDecoder) Name() string {
	return "parallel (quirc + custom)"
}

// Decode 并行解码：同时运行 quirc 和 custom，任一成功立即返回
func (d *ParallelQRDecoder) Decode(ctx context.Context, imagePath string, logPrefix string) (bool, error) {
	type decodeResult struct {
		hasQRCode bool
		err       error
		name      string
	}

	resultChan := make(chan decodeResult, 2)
	var wg sync.WaitGroup
	var mu sync.Mutex
	var quircErr error
	var customErr error

	// 启动Quirc解码
	if d.quircDecoder != nil {
		wg.Add(1)
		go func() {
			defer wg.Done()
			hasQRCode, err := d.quircDecoder.Decode(ctx, imagePath, logPrefix)
			mu.Lock()
			if err != nil {
				quircErr = err
			}
			mu.Unlock()
			resultChan <- decodeResult{
				hasQRCode: hasQRCode,
				err:       err,
				name:      d.quircDecoder.Name(),
			}
		}()
	}

	// 启动Custom解码
	if d.customDecoder != nil {
		wg.Add(1)
		go func() {
			defer wg.Done()
			hasQRCode, err := d.customDecoder.Decode(ctx, imagePath, logPrefix)
			mu.Lock()
			if err != nil {
				customErr = err
			}
			mu.Unlock()
			resultChan <- decodeResult{
				hasQRCode: hasQRCode,
				err:       err,
				name:      d.customDecoder.Name(),
			}
		}()
	}

	// 等待第一个结果
	var firstResult decodeResult
	var secondResult decodeResult

	firstResult = <-resultChan
	if firstResult.hasQRCode {
		// 如果检测到二维码，立即返回
		go func() {
			<-resultChan
			wg.Wait()
		}()
		return true, nil
	}

	// 等待第二个结果
	if d.quircDecoder != nil && d.customDecoder != nil {
		secondResult = <-resultChan
		if secondResult.hasQRCode {
			wg.Wait()
			return true, nil
		}
	}

	wg.Wait()

	// 如果都失败，返回错误
	if firstResult.err != nil && secondResult.err != nil {
		log.ZError(ctx, "并行解码失败，两个解码器都失败", fmt.Errorf("quirc错误=%v, custom错误=%v", quircErr, customErr),
			"quircError", quircErr,
			"customError", customErr)
		return false, fmt.Errorf("quirc 和 custom 都解码失败: quirc错误=%v, custom错误=%v", quircErr, customErr)
	}

	return false, nil
}

// ============================================================================
// 辅助函数
// ============================================================================

// convertToGrayscale 转换为灰度图
func convertToGrayscale(img image.Image, width, height int) []byte {
	grayData := make([]byte, width*height)
	bounds := img.Bounds()

	if ycbcr, ok := img.(*image.YCbCr); ok {
		for y := 0; y < height; y++ {
			for x := 0; x < width; x++ {
				yi := ycbcr.YOffset(x+bounds.Min.X, y+bounds.Min.Y)
				grayData[y*width+x] = ycbcr.Y[yi]
			}
		}
		return grayData
	}

	for y := 0; y < height; y++ {
		for x := 0; x < width; x++ {
			r, g, b, _ := img.At(x+bounds.Min.X, y+bounds.Min.Y).RGBA()
			r8 := uint8(r >> 8)
			g8 := uint8(g >> 8)
			b8 := uint8(b >> 8)
			gray := byte((uint16(r8)*299 + uint16(g8)*587 + uint16(b8)*114) / 1000)
			grayData[y*width+x] = gray
		}
	}

	return grayData
}

// enhanceImage 图像增强（标准方法）
func enhanceImage(data []byte, width, height int) []byte {
	enhanced := make([]byte, len(data))
	copy(enhanced, data)

	minVal := uint8(255)
	maxVal := uint8(0)
	for _, v := range data {
		if v < minVal {
			minVal = v
		}
		if v > maxVal {
			maxVal = v
		}
	}

	if maxVal-minVal < 50 {
		rangeVal := maxVal - minVal
		if rangeVal == 0 {
			rangeVal = 1
		}
		for i, v := range data {
			stretched := uint8((uint16(v-minVal) * 255) / uint16(rangeVal))
			enhanced[i] = stretched
		}
	}

	return enhanced
}

// enhanceImageStrong 强对比度增强
func enhanceImageStrong(data []byte, width, height int) []byte {
	enhanced := make([]byte, len(data))

	histogram := make([]int, 256)
	for _, v := range data {
		histogram[v]++
	}

	cdf := make([]int, 256)
	cdf[0] = histogram[0]
	for i := 1; i < 256; i++ {
		cdf[i] = cdf[i-1] + histogram[i]
	}

	total := len(data)
	for i, v := range data {
		if total > 0 {
			enhanced[i] = uint8((cdf[v] * 255) / total)
		}
	}

	return enhanced
}

// enhanceImageForRoundedCorners 针对圆形角的特殊处理
func enhanceImageForRoundedCorners(data []byte, width, height int) []byte {
	enhanced := make([]byte, len(data))
	copy(enhanced, data)

	minVal := uint8(255)
	maxVal := uint8(0)
	for _, v := range data {
		if v < minVal {
			minVal = v
		}
		if v > maxVal {
			maxVal = v
		}
	}

	if maxVal-minVal < 100 {
		rangeVal := maxVal - minVal
		if rangeVal == 0 {
			rangeVal = 1
		}
		for i, v := range data {
			stretched := uint8((uint16(v-minVal) * 255) / uint16(rangeVal))
			enhanced[i] = stretched
		}
	}

	// 形态学操作：先腐蚀后膨胀
	dilated := make([]byte, len(enhanced))
	kernelSize := 3
	halfKernel := kernelSize / 2

	// 腐蚀（最小值滤波）
	for y := halfKernel; y < height-halfKernel; y++ {
		for x := halfKernel; x < width-halfKernel; x++ {
			minVal := uint8(255)
			for ky := -halfKernel; ky <= halfKernel; ky++ {
				for kx := -halfKernel; kx <= halfKernel; kx++ {
					idx := (y+ky)*width + (x + kx)
					if enhanced[idx] < minVal {
						minVal = enhanced[idx]
					}
				}
			}
			dilated[y*width+x] = minVal
		}
	}

	// 膨胀（最大值滤波）
	for y := halfKernel; y < height-halfKernel; y++ {
		for x := halfKernel; x < width-halfKernel; x++ {
			maxVal := uint8(0)
			for ky := -halfKernel; ky <= halfKernel; ky++ {
				for kx := -halfKernel; kx <= halfKernel; kx++ {
					idx := (y+ky)*width + (x + kx)
					if dilated[idx] > maxVal {
						maxVal = dilated[idx]
					}
				}
			}
			enhanced[y*width+x] = maxVal
		}
	}

	// 边界保持原值
	for y := 0; y < height; y++ {
		for x := 0; x < width; x++ {
			if y < halfKernel || y >= height-halfKernel || x < halfKernel || x >= width-halfKernel {
				enhanced[y*width+x] = data[y*width+x]
			}
		}
	}

	return enhanced
}

// enhanceImageDenoiseSharpen 去噪+锐化处理
func enhanceImageDenoiseSharpen(data []byte, width, height int) []byte {
	denoised := medianFilter(data, width, height, 3)
	sharpened := sharpenImage(denoised, width, height)
	return sharpened
}

// medianFilter 中值滤波去噪
func medianFilter(data []byte, width, height, kernelSize int) []byte {
	filtered := make([]byte, len(data))
	halfKernel := kernelSize / 2
	kernelArea := kernelSize * kernelSize
	values := make([]byte, kernelArea)

	for y := halfKernel; y < height-halfKernel; y++ {
		for x := halfKernel; x < width-halfKernel; x++ {
			idx := 0
			for ky := -halfKernel; ky <= halfKernel; ky++ {
				for kx := -halfKernel; kx <= halfKernel; kx++ {
					values[idx] = data[(y+ky)*width+(x+kx)]
					idx++
				}
			}
			filtered[y*width+x] = quickSelectMedian(values)
		}
	}

	// 边界保持原值
	for y := 0; y < height; y++ {
		for x := 0; x < width; x++ {
			if y < halfKernel || y >= height-halfKernel || x < halfKernel || x >= width-halfKernel {
				filtered[y*width+x] = data[y*width+x]
			}
		}
	}

	return filtered
}

// quickSelectMedian 快速选择中值
func quickSelectMedian(arr []byte) byte {
	n := len(arr)
	if n <= 7 {
		// 小数组使用插入排序
		for i := 1; i < n; i++ {
			key := arr[i]
			j := i - 1
			for j >= 0 && arr[j] > key {
				arr[j+1] = arr[j]
				j--
			}
			arr[j+1] = key
		}
		return arr[n/2]
	}
	return quickSelect(arr, 0, n-1, n/2)
}

// quickSelect 快速选择第k小的元素
func quickSelect(arr []byte, left, right, k int) byte {
	if left == right {
		return arr[left]
	}
	pivotIndex := partition(arr, left, right)
	if k == pivotIndex {
		return arr[k]
	} else if k < pivotIndex {
		return quickSelect(arr, left, pivotIndex-1, k)
	}
	return quickSelect(arr, pivotIndex+1, right, k)
}

func partition(arr []byte, left, right int) int {
	pivot := arr[right]
	i := left
	for j := left; j < right; j++ {
		if arr[j] <= pivot {
			arr[i], arr[j] = arr[j], arr[i]
			i++
		}
	}
	arr[i], arr[right] = arr[right], arr[i]
	return i
}

// sharpenImage 锐化处理
func sharpenImage(data []byte, width, height int) []byte {
	sharpened := make([]byte, len(data))
	kernel := []int{0, -1, 0, -1, 5, -1, 0, -1, 0}

	for y := 1; y < height-1; y++ {
		for x := 1; x < width-1; x++ {
			sum := 0
			idx := 0
			for ky := -1; ky <= 1; ky++ {
				for kx := -1; kx <= 1; kx++ {
					pixelIdx := (y+ky)*width + (x + kx)
					sum += int(data[pixelIdx]) * kernel[idx]
					idx++
				}
			}
			if sum < 0 {
				sum = 0
			}
			if sum > 255 {
				sum = 255
			}
			sharpened[y*width+x] = uint8(sum)
		}
	}

	// 边界保持原值
	for y := 0; y < height; y++ {
		for x := 0; x < width; x++ {
			if y == 0 || y == height-1 || x == 0 || x == width-1 {
				sharpened[y*width+x] = data[y*width+x]
			}
		}
	}

	return sharpened
}

// enhanceImageOtsu Otsu自适应阈值二值化
func enhanceImageOtsu(data []byte, width, height int) []byte {
	threshold := calculateOtsuThreshold(data)
	binary := make([]byte, len(data))
	for i := range data {
		if data[i] > threshold {
			binary[i] = 255
		}
	}
	return binary
}

// calculateOtsuThreshold 计算Otsu自适应阈值
func calculateOtsuThreshold(data []byte) uint8 {
	histogram := make([]int, 256)
	for _, v := range data {
		histogram[v]++
	}

	total := len(data)
	if total == 0 {
		return 128
	}

	var threshold uint8
	var maxVar float64
	var sum int

	for i := 0; i < 256; i++ {
		sum += i * histogram[i]
	}

	var sum1 int
	var wB int
	for i := 0; i < 256; i++ {
		wB += histogram[i]
		if wB == 0 {
			continue
		}
		wF := total - wB
		if wF == 0 {
			break
		}

		sum1 += i * histogram[i]
		mB := float64(sum1) / float64(wB)
		mF := float64(sum-sum1) / float64(wF)

		varBetween := float64(wB) * float64(wF) * (mB - mF) * (mB - mF)

		if varBetween > maxVar {
			maxVar = varBetween
			threshold = uint8(i)
		}
	}

	return threshold
}

// enhanceImageGaussianSharpen 高斯模糊+锐化
func enhanceImageGaussianSharpen(data []byte, width, height int) []byte {
	blurred := gaussianBlur(data, width, height, 1.0)
	sharpened := sharpenImage(blurred, width, height)
	enhanced := enhanceImage(sharpened, width, height)
	return enhanced
}

// gaussianBlur 高斯模糊
func gaussianBlur(data []byte, width, height int, sigma float64) []byte {
	blurred := make([]byte, len(data))
	kernelSize := 5
	halfKernel := kernelSize / 2

	kernel := make([]float64, kernelSize*kernelSize)
	sum := 0.0
	for y := -halfKernel; y <= halfKernel; y++ {
		for x := -halfKernel; x <= halfKernel; x++ {
			idx := (y+halfKernel)*kernelSize + (x + halfKernel)
			val := math.Exp(-(float64(x*x+y*y) / (2 * sigma * sigma)))
			kernel[idx] = val
			sum += val
		}
	}

	for i := range kernel {
		kernel[i] /= sum
	}

	for y := halfKernel; y < height-halfKernel; y++ {
		for x := halfKernel; x < width-halfKernel; x++ {
			var val float64
			idx := 0
			for ky := -halfKernel; ky <= halfKernel; ky++ {
				for kx := -halfKernel; kx <= halfKernel; kx++ {
					pixelIdx := (y+ky)*width + (x + kx)
					val += float64(data[pixelIdx]) * kernel[idx]
					idx++
				}
			}
			blurred[y*width+x] = uint8(val)
		}
	}

	// 边界保持原值
	for y := 0; y < height; y++ {
		for x := 0; x < width; x++ {
			if y < halfKernel || y >= height-halfKernel || x < halfKernel || x >= width-halfKernel {
				blurred[y*width+x] = data[y*width+x]
			}
		}
	}

	return blurred
}

// createImageFromGrayscale 从灰度数据创建图像
func createImageFromGrayscale(data []byte, width, height int) image.Image {
	img := image.NewGray(image.Rect(0, 0, width, height))
	for y := 0; y < height; y++ {
		rowStart := y * width
		rowEnd := rowStart + width
		if rowEnd > len(data) {
			rowEnd = len(data)
		}
		copy(img.Pix[y*img.Stride:], data[rowStart:rowEnd])
	}
	return img
}

// scaledImage 缩放后的图像数据
type scaledImage struct {
	data   []byte
	width  int
	height int
}

// scaleImage 缩放图像
func scaleImage(img image.Image, origWidth, origHeight int, scale float64) image.Image {
	if scale == 1.0 {
		return img
	}

	newWidth := int(float64(origWidth) * scale)
	newHeight := int(float64(origHeight) * scale)

	if newWidth < 50 || newHeight < 50 {
		return nil
	}
	if newWidth > 1500 || newHeight > 1500 {
		return nil
	}

	scaled := image.NewRGBA(image.Rect(0, 0, newWidth, newHeight))
	bounds := img.Bounds()

	for y := 0; y < newHeight; y++ {
		for x := 0; x < newWidth; x++ {
			srcX := float64(x) / scale
			srcY := float64(y) / scale

			x1 := int(srcX)
			y1 := int(srcY)
			x2 := x1 + 1
			y2 := y1 + 1

			if x2 >= bounds.Dx() {
				x2 = bounds.Dx() - 1
			}
			if y2 >= bounds.Dy() {
				y2 = bounds.Dy() - 1
			}

			fx := srcX - float64(x1)
			fy := srcY - float64(y1)

			c11 := getPixelColor(img, bounds.Min.X+x1, bounds.Min.Y+y1)
			c12 := getPixelColor(img, bounds.Min.X+x1, bounds.Min.Y+y2)
			c21 := getPixelColor(img, bounds.Min.X+x2, bounds.Min.Y+y1)
			c22 := getPixelColor(img, bounds.Min.X+x2, bounds.Min.Y+y2)

			r := uint8(float64(c11.R)*(1-fx)*(1-fy) + float64(c21.R)*fx*(1-fy) + float64(c12.R)*(1-fx)*fy + float64(c22.R)*fx*fy)
			g := uint8(float64(c11.G)*(1-fx)*(1-fy) + float64(c21.G)*fx*(1-fy) + float64(c12.G)*(1-fx)*fy + float64(c22.G)*fx*fy)
			b := uint8(float64(c11.B)*(1-fx)*(1-fy) + float64(c21.B)*fx*(1-fy) + float64(c12.B)*(1-fx)*fy + float64(c22.B)*fx*fy)

			scaled.Set(x, y, color.RGBA{R: r, G: g, B: b, A: 255})
		}
	}

	return scaled
}

// getPixelColor 获取像素颜色
func getPixelColor(img image.Image, x, y int) color.RGBA {
	r, g, b, _ := img.At(x, y).RGBA()
	return color.RGBA{
		R: uint8(r >> 8),
		G: uint8(g >> 8),
		B: uint8(b >> 8),
		A: 255,
	}
}

// scaleGrayscaleImage 缩放灰度图像
func scaleGrayscaleImage(data []byte, origWidth, origHeight int, scale float64) *scaledImage {
	if scale == 1.0 {
		return &scaledImage{data: data, width: origWidth, height: origHeight}
	}

	newWidth := int(float64(origWidth) * scale)
	newHeight := int(float64(origHeight) * scale)

	if newWidth < 21 || newHeight < 21 || newWidth > 2000 || newHeight > 2000 {
		return nil
	}

	scaled := make([]byte, newWidth*newHeight)

	for y := 0; y < newHeight; y++ {
		for x := 0; x < newWidth; x++ {
			srcX := float64(x) / scale
			srcY := float64(y) / scale

			x1 := int(srcX)
			y1 := int(srcY)
			x2 := x1 + 1
			y2 := y1 + 1

			if x2 >= origWidth {
				x2 = origWidth - 1
			}
			if y2 >= origHeight {
				y2 = origHeight - 1
			}

			fx := srcX - float64(x1)
			fy := srcY - float64(y1)

			v11 := float64(data[y1*origWidth+x1])
			v12 := float64(data[y2*origWidth+x1])
			v21 := float64(data[y1*origWidth+x2])
			v22 := float64(data[y2*origWidth+x2])

			val := v11*(1-fx)*(1-fy) + v21*fx*(1-fy) + v12*(1-fx)*fy + v22*fx*fy
			scaled[y*newWidth+x] = uint8(val)
		}
	}

	return &scaledImage{data: scaled, width: newWidth, height: newHeight}
}

// Point 表示一个点
type Point struct {
	X, Y int
}

// Corner 表示检测到的定位图案角点
type Corner struct {
	Center Point
	Size   int
	Type   int
}

// detectCornersFast 快速检测定位图案
func detectCornersFast(data []byte, width, height int) []Corner {
	var corners []Corner

	scanStep := max(2, min(width, height)/80)
	if scanStep < 1 {
		scanStep = 1
	}

	for y := scanStep * 3; y < height-scanStep*3; y += scanStep {
		for x := scanStep * 3; x < width-scanStep*3; x += scanStep {
			if isFinderPatternFast(data, width, height, x, y) {
				corners = append(corners, Corner{
					Center: Point{X: x, Y: y},
					Size:   20,
				})
				if len(corners) >= 3 {
					return corners
				}
			}
		}
	}

	return corners
}

// isFinderPatternFast 快速检测定位图案
func isFinderPatternFast(data []byte, width, height, x, y int) bool {
	centerIdx := y*width + x
	if centerIdx < 0 || centerIdx >= len(data) {
		return false
	}
	if data[centerIdx] > 180 {
		return false
	}

	radius := min(width, height) / 15
	if radius < 3 {
		radius = 3
	}
	if radius > 30 {
		radius = 30
	}

	directions := []struct{ dx, dy int }{{radius, 0}, {-radius, 0}, {0, radius}, {0, -radius}}
	blackCount := 0
	whiteCount := 0

	for _, dir := range directions {
		nx := x + dir.dx
		ny := y + dir.dy
		if nx >= 0 && nx < width && ny >= 0 && ny < height {
			idx := ny*width + nx
			if idx >= 0 && idx < len(data) {
				if data[idx] < 128 {
					blackCount++
				} else {
					whiteCount++
				}
			}
		}
	}

	return blackCount >= 2 && whiteCount >= 2
}

// 辅助函数
func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}
