package utils

import (
	"bytes"
	"encoding/base64"
	"errors"
	"fmt"
	"image"
	"image/color"
	"image/draw"
	"image/jpeg"
	"image/png"
	"math/rand"
	"net/http"
	"os"
	"strconv"
	"time"

	"github.com/nfnt/resize"
)

const (
	ImgURL     = "https://cdns.fontree.cn/fonchain-main/test/image/artwork/config/slidCode_%d.jpg"
	ImgPath    = "./code/%d.jpg" //本地路径，暂不使用
	ImgPathPng = "./code/%d.png" //本地路径，暂不使用
)

// 生成指定范围内的随机数
func GetNonceByRange(start, end int) int {
	rand.Seed(time.Now().UnixNano())
	return rand.Intn(end-start+1) + start
}

// 获取缓冲图片，可能是通过URL或本地路径
func GetBufferedImage(place, canvasWidth, canvasHeight int) (draw.Image, error) {

	startTime := time.Now()
	fmt.Println("")
	fmt.Println("")
	fmt.Println("")
	fmt.Println("1---")
	nonce := GetNonceByRange(1, 10)

	fmt.Println("2", time.Now().Sub(startTime))
	var imgURL string

	//place = 0 // 注意，这边的图片现在只使用url图片
	if place == 1 {

		fmt.Println("3-1", time.Now().Sub(startTime))
		imgURL = fmt.Sprintf(ImgURL, nonce)
		resp, err := http.Get(imgURL)
		if err != nil {
			return nil, err
		}

		fmt.Println("3-2", time.Now().Sub(startTime))
		defer resp.Body.Close()
		img, ff, err := image.Decode(resp.Body)
		fmt.Println("----", ff)
		if err != nil {
			return nil, err
		}

		fmt.Println("3-3", time.Now().Sub(startTime))

		canvasImage := ImageResize(img, canvasWidth, canvasHeight).(*image.RGBA)

		return canvasImage, nil
	} else { //从redis中获取

		file, err := os.Open(fmt.Sprintf(ImgPathPng, nonce))

		fmt.Println("4-1", time.Now().Sub(startTime))
		if err != nil {
			return nil, err
		}
		defer file.Close()

		//img, format, err := image.Decode(file)
		img, err := png.Decode(file)
		format := "1"
		fmt.Println("", err)
		//img, err := jpeg.Decode(file)
		fmt.Println("4-1-1", time.Now().Sub(startTime), err)

		fmt.Println("4-2", time.Now().Sub(startTime), format)
		if err != nil {
			return nil, err
		}

		ss := ImageResize(img, canvasWidth, canvasHeight)
		canvasImage := ss.(*image.RGBA)

		return canvasImage, nil
	}

	return nil, errors.New("类型错误")
}

// 将 image.YCbCr 转换为 *image.RGBA
func convertYCbCrToRGBA(yCbCrImage *image.YCbCr) *image.RGBA {
	bounds := yCbCrImage.Bounds()
	rgba := image.NewRGBA(bounds)

	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
		for x := bounds.Min.X; x < bounds.Max.X; x++ {
			// 获取 (x, y) 点的颜色
			ycbcrColor := yCbCrImage.At(x, y)

			// 使用 color.RGBAModel 转换为 RGBA 颜色
			rgbaColor := color.RGBAModel.Convert(ycbcrColor).(color.RGBA)

			// 设置到 RGBA 图像中
			rgba.SetRGBA(x, y, rgbaColor)
		}
	}

	return rgba
}

// 调整图片大小
func ImageResize(bufferedImage image.Image, width, height int) image.Image {
	return resize.Resize(uint(width), uint(height), bufferedImage, resize.Bilinear)
}

// CutByTemplate 根据模板裁剪图像  // 生成圆角正方形的滑块图像
func CutByTemplate(canvasImage, blockImage draw.Image, blockWidth, blockHeight, blockX, blockY int) {
	// 创建水印图像
	waterImage := image.NewRGBA(image.Rect(0, 0, blockWidth, blockHeight))
	blockData := getRoundedSquareData(blockWidth, blockHeight)

	// 遍历滑块区域，将滑块图案从背景中裁剪出来，并生成水印
	for i := 0; i < blockWidth; i++ {
		for j := 0; j < blockHeight; j++ {
			switch blockData[i][j] {
			case 1: // 实心区域
				blockImage.Set(i, j, canvasImage.At(blockX+i, blockY+j))
				waterImage.Set(i, j, color.Black)
			case 2: // 半透明边缘（不再需要）
				origColor := canvasImage.At(blockX+i, blockY+j)
				r, g, b, _ := origColor.RGBA()
				alpha := uint8(180)
				blockImage.Set(i, j, color.NRGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), alpha})
				waterImage.Set(i, j, color.NRGBA{0, 0, 0, alpha})
			case 3: // 纯白边框区域
				blockImage.Set(i, j, color.White) // 设置纯白色
				waterImage.Set(i, j, color.White)
			default: // 透明区域
				blockImage.Set(i, j, color.Transparent)
				waterImage.Set(i, j, color.Transparent)
			}
		}
	}

	// 在原始画布上清除滑块区域并设置透明背景
	clearCanvasArea(canvasImage, blockData, blockX, blockY, blockWidth, blockHeight)
}

// 获取带纯白边框的平滑圆角正方形的块数据
func getRoundedSquareData(blockWidth, blockHeight int) [][]int {
	data := make([][]int, blockWidth)
	for i := range data {
		data[i] = make([]int, blockHeight)
	}

	// 设置圆角半径为正方形边长的 20%
	cornerRadius := float64(blockWidth) * 0.2
	cornerRadiusSquared := cornerRadius * cornerRadius

	// 设置边框厚度为 1 像素
	borderThickness := 1.0 // 纯白边框宽度为 1 像素
	borderRadiusSquared := (cornerRadius - borderThickness) * (cornerRadius - borderThickness)

	for i := 0; i < blockWidth; i++ {
		for j := 0; j < blockHeight; j++ {
			// 处理四个角的圆角
			if (i < int(cornerRadius) && j < int(cornerRadius)) || // 左上角
				(i >= blockWidth-int(cornerRadius) && j < int(cornerRadius)) || // 右上角
				(i < int(cornerRadius) && j >= blockHeight-int(cornerRadius)) || // 左下角
				(i >= blockWidth-int(cornerRadius) && j >= blockHeight-int(cornerRadius)) { // 右下角

				// 计算距离的平方，判断是否在圆角内
				var dx, dy float64
				if i < int(cornerRadius) {
					dx = float64(i) - cornerRadius
				} else {
					dx = float64(i) - float64(blockWidth) + cornerRadius
				}
				if j < int(cornerRadius) {
					dy = float64(j) - cornerRadius
				} else {
					dy = float64(j) - float64(blockHeight) + cornerRadius
				}

				distanceSquared := dx*dx + dy*dy
				if distanceSquared > cornerRadiusSquared {
					data[i][j] = 0 // 圆角外部区域
				} else if distanceSquared > borderRadiusSquared {
					data[i][j] = 3 // 纯白边框区域
				} else {
					data[i][j] = 1 // 实心区域
				}
			} else {
				// 非圆角区域
				if (i < int(borderThickness) || i >= blockWidth-int(borderThickness)) || // 左右边缘
					(j < int(borderThickness) || j >= blockHeight-int(borderThickness)) { // 上下边缘
					data[i][j] = 3 // 纯白边框区域
				} else {
					data[i][j] = 1 // 实心区域
				}
			}
		}
	}

	return data
}

// 随机生成一个不重叠的滑块区域
func generateNonOverlappingArea(canvasWidth, canvasHeight, blockX, blockY, blockWidth, blockHeight int) (int, int) {
	rand.Seed(time.Now().UnixNano())
	var newX, newY int

	for {
		// 随机生成新区域的位置
		newX = rand.Intn(canvasWidth - blockWidth)
		newY = rand.Intn(canvasHeight - blockHeight)

		// 检查新区域是否与原始区域重叠
		if (newX+blockWidth <= blockX || newX >= blockX+blockWidth) &&
			(newY+blockHeight <= blockY || newY >= blockY+blockHeight) {
			break
		}
	}

	return newX, newY
}

// 将滑块区域设为半透明，并生成不重叠的额外区域
func clearCanvasArea(canvasImage draw.Image, blockData [][]int, blockX, blockY, blockWidth, blockHeight int) {
	alpha := uint8(128) // 50% 透明度

	// 设置原始滑块区域为半透明
	for i := 0; i < blockWidth; i++ {
		for j := 0; j < blockHeight; j++ {
			if blockData[i][j] > 0 {
				// 获取原始像素的 RGB 值，并统一设置 Alpha 通道
				originalColor := canvasImage.At(blockX+i, blockY+j)
				r, g, b, _ := originalColor.RGBA()

				// 设置新的颜色并固定透明度
				semiTransparentColor := color.NRGBA{
					R: uint8(r >> 8),
					G: uint8(g >> 8),
					B: uint8(b >> 8),
					A: alpha, // 固定透明度
				}

				// 应用半透明效果
				canvasImage.Set(blockX+i, blockY+j, semiTransparentColor)
			}
		}
	}

	// 生成不重叠的新区域位置
	canvasBounds := canvasImage.Bounds()
	newBlockX, newBlockY := generateNonOverlappingArea(canvasBounds.Max.X, canvasBounds.Max.Y, blockX, blockY, blockWidth, blockHeight)

	// 可以在新区域执行与原始区域相同的操作，或根据需求自定义
	for i := 0; i < blockWidth; i++ {
		for j := 0; j < blockHeight; j++ {
			if blockData[i][j] > 0 {
				// 获取原始像素的 RGB 值，并统一设置 Alpha 通道
				originalColor := canvasImage.At(newBlockX+i, newBlockY+j)
				r, g, b, _ := originalColor.RGBA()

				// 设置新的颜色并固定透明度
				semiTransparentColor := color.NRGBA{
					R: uint8(r >> 8),
					G: uint8(g >> 8),
					B: uint8(b >> 8),
					A: alpha, // 固定透明度
				}

				// 应用半透明效果
				canvasImage.Set(newBlockX+i, newBlockY+j, semiTransparentColor)
			}
		}
	}
}

//// 清除画布上的滑块区域，使其为黑色背景
//func clearCanvasArea(canvasImage draw.Image, blockData [][]int, blockX, blockY, blockWidth, blockHeight int) {
//	alpha := uint8(128) // 50% 透明度
//
//	for i := 0; i < blockWidth; i++ {
//		for j := 0; j < blockHeight; j++ {
//			if blockData[i][j] > 0 {
//				// 获取原始像素的 RGB 值，并统一设置 Alpha 通道
//				originalColor := canvasImage.At(blockX+i, blockY+j)
//				r, g, b, _ := originalColor.RGBA()
//
//				// 设置新的颜色并固定透明度
//				semiTransparentColor := color.NRGBA{
//					R: uint8(r >> 8),
//					G: uint8(g >> 8),
//					B: uint8(b >> 8),
//					A: alpha, // 固定透明度
//				}
//
//				// 应用半透明效果
//				canvasImage.Set(blockX+i, blockY+j, semiTransparentColor)
//			}
//		}
//	}
//}

//// 根据模板裁剪图像 // 生成拼图类型的滑块图像 有需要打开
//func CutByTemplate(canvasImage, blockImage draw.Image, blockWidth, blockHeight, blockRadius, blockX, blockY int) (faceY int) {
//	waterImage := image.NewRGBA(image.Rect(0, 0, blockWidth, blockHeight))
//	var blockData [][]int
//	blockData, faceY = getBlockData(blockWidth, blockHeight, blockRadius, blockY)
//
//	for i := 0; i < blockWidth; i++ {
//		for j := 0; j < blockHeight; j++ {
//			if blockData[i][j] == 1 {
//				// 设置水印背景为黑色
//				waterImage.Set(i, j, color.Black)
//				// 从原始图像中获取像素
//				blockImage.Set(i, j, canvasImage.At(blockX+i, blockY+j))
//
//				// 设置轮廓为白色
//				if (i+1 < blockWidth && blockData[i+1][j] == 0) ||
//					(j+1 < blockHeight && blockData[i][j+1] == 0) ||
//					(i-1 >= 0 && blockData[i-1][j] == 0) ||
//					(j-1 >= 0 && blockData[i][j-1] == 0) {
//					blockImage.Set(i, j, color.White)
//					waterImage.Set(i, j, color.White)
//				}
//			} else {
//				// 背景设为透明
//				blockImage.Set(i, j, color.Transparent)
//				waterImage.Set(i, j, color.Transparent)
//			}
//		}
//	}
//	addBlockWatermark(canvasImage, waterImage, blockX, blockY)
//	return
//}
//
//// 获取块数据，用以确定块的形状
//func getBlockData(blockWidth, blockHeight, blockRadius, blockY int) (blockData [][]int, faceY int) {
//	data := make([][]int, blockWidth)
//	for i := range data {
//		data[i] = make([]int, blockHeight)
//	}
//	rand.Seed(time.Now().UnixNano())
//
//	// 确定两个随机方向和凸/凹形状
//	face1, face2 := rand.Intn(4), rand.Intn(4)
//	for face1 == face2 {
//		face2 = rand.Intn(4)
//	}
//
//	shape := rand.Intn(2) // 0: 凸，1: 凹
//	circle1 := getCircleCoords(face1, blockWidth, blockHeight, blockRadius)
//	circle2 := getCircleCoords(face2, blockWidth, blockHeight, blockRadius)
//
//	if (face1 == 2 || face2 == 2) && shape == 1 {
//		faceY = blockY - blockRadius
//	} else {
//		faceY = blockY
//	}
//	// 计算轮廓
//	radiusSquared := float64(blockRadius * blockRadius)
//	for i := 0; i < blockWidth; i++ {
//		for j := 0; j < blockHeight; j++ {
//			if i >= blockRadius && i < blockWidth-blockRadius && j >= blockRadius && j < blockHeight-blockRadius {
//				data[i][j] = 1
//			}
//			if circle1 != nil && math.Pow(float64(i-circle1[0]), 2)+math.Pow(float64(j-circle1[1]), 2) <= radiusSquared {
//				data[i][j] = shape
//			}
//			if circle2 != nil && math.Pow(float64(i-circle2[0]), 2)+math.Pow(float64(j-circle2[1]), 2) <= radiusSquared {
//				data[i][j] = shape
//			}
//		}
//	}
//	return data, faceY
//}
//
//// 根据方向获取圆心坐标
//func getCircleCoords(face, blockWidth, blockHeight, blockRadius int) []int {
//	switch face {
//	case 0:
//		return []int{blockWidth / 2, blockRadius} // 上
//	case 1:
//		return []int{blockRadius, blockHeight / 2} // 左
//	case 2:
//		return []int{blockWidth / 2, blockHeight - blockRadius - 1} // 下
//	case 3:
//		return []int{blockWidth - blockRadius - 1, blockHeight / 2} // 右
//	default:
//		return nil
//	}
//}
//
//// 在画布图像上添加水印
//func addBlockWatermark(canvasImage, waterImage draw.Image, blockX, blockY int) {
//	for i := 0; i < waterImage.Bounds().Dx(); i++ {
//		for j := 0; j < waterImage.Bounds().Dy(); j++ {
//			if _, _, _, alpha := waterImage.At(i, j).RGBA(); alpha > 0 {
//				canvasImage.Set(blockX+i, blockY+j, waterImage.At(i, j))
//			}
//		}
//	}
//}

// 将图像转换为Base64编码
func ToBase64(img image.Image, format string) string {
	buf := new(bytes.Buffer)
	switch format {
	case "png":
		png.Encode(buf, img)
	case "jpeg":
		jpeg.Encode(buf, img, &jpeg.Options{Quality: 80})

	}
	return base64.StdEncoding.EncodeToString(buf.Bytes())
}

// ToBase64Jpeg 将图像转换为Base64编码
func ToBase64Jpeg(img image.Image, format string) string {
	buf := new(bytes.Buffer)
	switch format {
	case "png":
		jpeg.Encode(buf, img, &jpeg.Options{Quality: 100})
	}
	return base64.StdEncoding.EncodeToString(buf.Bytes())
}

// 计算绝对值
func Abs(a int) int {
	if a < 0 {
		return -a
	}
	return a
}

// 将字符串转换为整数
func ParseInt(s string) int {
	i, _ := strconv.Atoi(s)
	return i
}
