package img

import (
	"image"
	"image/color"
	"math"
	"math/rand"
	"path/filepath"
	"runtime"
	"strings"
	"sync"

	"github.com/flopp/go-findfont"
	"github.com/ssgo/u"
	"golang.org/x/image/font"
	"golang.org/x/image/font/opentype"
	"golang.org/x/image/font/sfnt"
	"golang.org/x/image/math/fixed"
)

// 各操作系统默认字体文件列表
var defaultFontFiles = map[string]map[string][]string{
	"windows": {
		"serif":      {"simsun.ttc", "times.ttf"},
		"sans-serif": {"msyh.ttc", "arial.ttf"},
		"monospace":  {"consola.ttf", "simsun.ttc"},
	},
	"darwin": {
		"serif":      {"Songti.ttc", "Times New Roman.ttf"},
		"sans-serif": {"Hiragino Sans GB.ttc", "PingFang.ttc", "Helvetica.ttf"},
		"monospace":  {"Menlo.ttc", "Courier New.ttf", "Hiragino Sans GB.ttc"},
	},
	"linux": {
		"serif":      {"dejavu/DejaVuSerif.ttf", "wqy-microhei.ttc", "noto/NotoSerifCJK-Regular.ttc"},
		"sans-serif": {"dejavu/DejaVuSans.ttf", "wqy-microhei.ttc", "noto/NotoSansCJK-Regular.ttc"},
		"monospace":  {"dejavu/DejaVuSansMono.ttf", "wqy-microhei_mono.ttc", "droid/DroidSansMono.ttf"},
	},
}

var defaultFontNames = map[string]map[string][]string{
	"windows": {
		"serif":      {"SimSun", "Times New Roman"},
		"sans-serif": {"Microsoft YaHei", "Arial"},
		"monospace":  {"Consolas", "SimSun"},
	},
	"darwin": {
		"serif":      {"Songti SC", "Times New Roman"},
		"sans-serif": {"Hiragino Sans GB", "PingFang SC", "Helvetica"},
		"monospace":  {"Menlo", "Courier New", "Hiragino Sans GB"},
	},
	"linux": {
		"serif":      {"DejaVu Serif", "WenQuanYi Micro Hei", "Noto Serif CJK SC"},
		"sans-serif": {"DejaVu Sans", "WenQuanYi Micro Hei", "Noto Sans CJK SC"},
		"monospace":  {"DejaVu Sans Mono", "WenQuanYi Micro Hei Mono", "Droid Sans Mono"},
	},
}

var defaultFontLoaded = map[string]bool{}
var fontLoaded = map[string]bool{}
var fontCache = map[string]*sfnt.Font{}
var fontLock = sync.RWMutex{}

type CompositeFace struct {
	Names []string
	Faces []font.Face
}

// 获取字体 - 支持TTF, OTF, TTC格式
func saveFontCache(buf *sfnt.Buffer, f *sfnt.Font) {
	fullName, _ := f.Name(buf, sfnt.NameIDFull)
	enFamily, _ := f.Name(buf, sfnt.NameIDFamily)
	enStyle, _ := f.Name(buf, sfnt.NameIDSubfamily)
	cnFamily, _ := f.Name(buf, sfnt.NameIDTypographicFamily)
	cnStyle, _ := f.Name(buf, sfnt.NameIDTypographicSubfamily)
	fullName = strings.TrimSpace(fullName)
	enFamily = strings.TrimSpace(enFamily)
	cnFamily = strings.TrimSpace(cnFamily)
	enStyle = strings.TrimSpace(enStyle)
	cnStyle = strings.TrimSpace(cnStyle)
	enName := enFamily + " " + enStyle
	cnName := cnFamily + " " + cnStyle
	enName = strings.TrimSpace(enName)
	cnName = strings.TrimSpace(cnName)

	fontLock.Lock()
	if enName != "" && fontCache[enName] == nil {
		fontCache[enName] = f
	}
	if cnName != "" && fontCache[cnName] == nil {
		fontCache[cnName] = f
	}
	if fullName != "" && fullName != enName && fontCache[fullName] == nil {
		fontCache[fullName] = f
	}
	if enFamily != "" && fontCache[enFamily] == nil {
		fontCache[enFamily] = f
	}
	if cnFamily != "" && fontCache[cnFamily] == nil {
		fontCache[cnFamily] = f
	}
	fontLock.Unlock()
}

func ListFont() []string {
	fonts := []string{}
	fontLock.RLock()
	defer fontLock.RUnlock()
	for k := range fontCache {
		fonts = append(fonts, k)
	}
	return fonts
}

var hasFontLoaded = false

func LoadFont(fontFiles ...string) {
	fontLock.Lock()
	if !hasFontLoaded {
		hasFontLoaded = true
	}
	fontLock.Unlock()
	if len(fontFiles) == 0 {
		// fontFiles = findfont.List()
		if osFFs, ok := defaultFontFiles[runtime.GOOS]; ok {
			if ffs, ok := osFFs["serif"]; ok {
				fontFiles = append(fontFiles, ffs...)
			}
			if ffs, ok := osFFs["sans-serif"]; ok {
				fontFiles = append(fontFiles, ffs...)
			}
			if ffs, ok := osFFs["monospace"]; ok {
				fontFiles = append(fontFiles, ffs...)
			}
		}
	}

	buf := &sfnt.Buffer{}
	for _, fontFile := range fontFiles {
		fontLock.RLock()
		loaded := fontLoaded[fontFile]
		fontLock.RUnlock()
		if loaded {
			continue
		}
		if !filepath.IsAbs(fontFile) {
			if f, err := findfont.Find(fontFile); err == nil {
				fontFile = f
			}
		}
		if fontData, err := u.ReadFileBytes(fontFile); err == nil {
			if strings.HasSuffix(fontFile, ".ttc") {
				if c, err := sfnt.ParseCollection(fontData); err == nil {
					for i := c.NumFonts() - 1; i >= 0; i-- {
						if f, err := c.Font(i); err == nil {
							saveFontCache(buf, f)
						}
					}
				}
			} else {
				if f, err := sfnt.Parse(fontData); err == nil {
					saveFontCache(buf, f)
				}
			}
		}
		fontLock.Lock()
		fontLoaded[fontFile] = true
		fontLock.Unlock()
	}
}

// 获取字体 - 支持TTF, OTF, TTC格式
func makeFont(size float64, fontNames ...string) *CompositeFace {
	fontLock.RLock()
	hasFontLoaded1 := hasFontLoaded
	fontLock.RUnlock()

	if !hasFontLoaded1 {
		LoadFont()
	}

	cf := &CompositeFace{Faces: []font.Face{}, Names: fontNames}
	for _, name := range fontNames {
		fontLock.RLock()
		f := fontCache[name]
		fontLock.RUnlock()
		if f != nil {
			if fc, err := opentype.NewFace(f, &opentype.FaceOptions{Size: size, DPI: 72}); err == nil {
				cf.Faces = append(cf.Faces, fc)
				// fmt.Println(u.BGreen("font"), name)
				// return fc
			}
		}
	}
	return cf
	// // fmt.Println(u.BRed("no font"))
	// return nil
}

func loadDefaultFonts(typ string) {
	fontLock.RLock()
	loaded := defaultFontLoaded[runtime.GOOS+typ]
	fontLock.RUnlock()
	if loaded {
		return
	}
	if osFFs, ok := defaultFontFiles[runtime.GOOS]; ok {
		if ffs, ok := osFFs[typ]; ok {
			LoadFont(ffs...)
		}
	}
	fontLock.Lock()
	defaultFontLoaded[runtime.GOOS+typ] = true
	fontLock.Unlock()

}

func getDefaultFonts(typ string) []string {
	if osFNs, ok := defaultFontNames[runtime.GOOS]; ok {
		if fns, ok := osFNs[typ]; ok {
			return fns
		}
	}
	return []string{}
}

// 设置预设字体
func (g *Graphics) SetSerifFont(size float64) {
	loadDefaultFonts("serif")
	g.SetFont(size, getDefaultFonts("serif")...)
}
func (g *Graphics) SetSansSerifFont(size float64) {
	loadDefaultFonts("sans-serif")
	g.SetFont(size, getDefaultFonts("sans-serif")...)
}
func (g *Graphics) SetMonospaceFont(size float64) {
	loadDefaultFonts("monospace")
	g.SetFont(size, getDefaultFonts("monospace")...)
}

func (g *Graphics) SetFont(size float64, fontNames ...string) {
	if len(fontNames) == 0 && g.lastFont != nil {
		if ff, ok := g.lastFont.(*CompositeFace); ok {
			fontNames = ff.Names
		}
	}
	g.lastFont = makeFont(size, fontNames...)
	g.dc.SetFontFace(g.lastFont)
}

func (c *CompositeFace) Glyph(dot fixed.Point26_6, r rune) (
	dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) {

	// fmt.Println(u.BCyan("Glyph"), len(c.Faces))
	for _, face := range c.Faces {
		dr, mask, maskp, advance, ok = face.Glyph(dot, r)
		// fmt.Println(u.BCyan("Glyph >>> "), i, ok)
		if ok {
			return
		}
	}
	return
}

func (c *CompositeFace) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) {
	for _, face := range c.Faces {
		bounds, advance, ok = face.GlyphBounds(r)
		if ok {
			return
		}
	}
	return
}

func (c *CompositeFace) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) {
	for _, face := range c.Faces {
		advance, ok := face.GlyphAdvance(r)
		if ok {
			// fmt.Printf("字符 '%c' 使用字体%d 宽度=%d\n", r, i, advance)
			return advance, true
		}
	}
	// 找不到支持的字体
	return fixed.I(1000), true // 返回默认宽度防止错误
}

func (c *CompositeFace) Kern(r0, r1 rune) fixed.Int26_6 {
	for _, face := range c.Faces {
		if kern := face.Kern(r0, r1); kern != 0 {
			return kern
		}
	}
	return 0
}

func (c *CompositeFace) Metrics() font.Metrics {
	if len(c.Faces) == 0 {
		return font.Metrics{}
	}
	return c.Faces[0].Metrics()
}

// 获取实际字符渲染用的字体的 Metrics
// func (c *CompositeFace) ActualMetrics(r rune) font.Metrics {
// 	// 查找实际渲染该字符的字体
// 	for _, f := range c.Faces {
// 		if _, _, ok := f.GlyphBounds(r); ok {
// 			return f.Metrics()
// 		}
// 	}
// 	// 找不到支持字符的字体时返回第一个的 Metrics
// 	return c.Faces[0].Metrics()
// }

func (c *CompositeFace) Close() error {
	var err error
	// for _, face := range c.Faces {
	// 	if closer, ok := face.(io.Closer); ok {
	// 		if e := closer.Close(); e != nil {
	// 			err = e
	// 		}
	// 	}
	// }
	return err
}

type TextOption struct {
	Width        float64
	Height       float64
	LineHeight   float64
	PaddingX     float64
	PaddingY     float64
	NoWrap       bool
	Color        string
	BgColor      string
	BorderColor  string
	BorderWidth  float64
	BorderRadius float64
	Align        string // left center right
	VAlign       string // top middle bottom
	ShadowColor  string // default #333333
	ShadowOffset int
}

// 绘制文本
func (g *Graphics) Text(x, y float64, text string, opt *TextOption) {
	if opt == nil {
		opt = &TextOption{}
	}
	if opt.LineHeight <= 0.01 {
		opt.LineHeight = 1.0
	}

	// 设置文本颜色
	if opt.Color != "" {
		g.dc.SetColor(hexToRGBA(opt.Color))
	}

	if g.lastFont == nil {
		g.SetSansSerifFont(14)
	}

	// 处理换行符
	paragraphs := strings.Split(text, "\n")
	if strings.Contains(text, "\r\n") {
		paragraphs = strings.Split(text, "\r\n")
	}

	// 准备文本行
	var lines []string
	hasWrap := !opt.NoWrap && opt.Width > 0
	for _, para := range paragraphs {
		if para == "" {
			lines = append(lines, "") // 保留空行
		} else if hasWrap {
			// 使用drawWidth计算换行
			lines = append(lines, g.wrapParagraph(para, opt.Width-2*opt.PaddingX)...)
		} else if opt.Width > 0 {
			// NoWrap模式但指定了宽度：使用相同的换行逻辑但只取第一行
			wrappedLines := g.wrapParagraph(para, opt.Width-2*opt.PaddingX)
			if len(wrappedLines) > 0 {
				lines = append(lines, wrappedLines[0])
			} else {
				lines = append(lines, "")
			}
		} else {
			lines = append(lines, para)
		}
	}

	// 计算文本总高度
	lineHeight := g.calcLineHeight(opt.LineHeight)
	totalHeight := float64(len(lines)) * lineHeight

	// 计算字体的上升和下降部分
	ascent := 0.0
	descent := 0.0
	if g.lastFont != nil {
		metrics := g.lastFont.Metrics()
		ascent = float64(metrics.Ascent) / 64
		descent = float64(metrics.Descent) / 64
	} else {
		// 默认估算
		ascent = g.dc.FontHeight() * 0.7
		descent = g.dc.FontHeight() * 0.3
	}

	// 计算文本内容尺寸
	textWidth := opt.Width
	textHeight := opt.Height

	// 计算最大行宽
	maxWidth := 0.0
	for _, line := range lines {
		w, _ := g.dc.MeasureString(line)
		if w > maxWidth {
			maxWidth = w
		}
	}

	// 如果未指定宽度，计算所需宽度
	if textWidth == 0 {
		textWidth = maxWidth + 2*opt.PaddingX
	}

	// 如果未指定高度，计算所需高度
	if textHeight == 0 {
		textHeight = totalHeight + 2*opt.PaddingY
	}

	var halfOffset float64
	if opt.ShadowOffset != 0 {
		if opt.ShadowColor == "" {
			opt.ShadowColor = "#333333"
		}
		halfOffset = float64(opt.ShadowOffset) / 2
	}

	// 绘制背景和边框（在文本之前）
	if opt.BgColor != "" || opt.BorderColor != "" {

		if opt.ShadowOffset != 0 {
			g.dc.SetColor(hexToRGBA(opt.ShadowColor))
			if opt.BorderRadius > 0 {
				g.dc.DrawRoundedRectangle(x+halfOffset*2, y+halfOffset*2, textWidth, textHeight, opt.BorderRadius)
			} else {
				g.dc.DrawRectangle(x+halfOffset*2, y+halfOffset*2, textWidth, textHeight)
			}
			if opt.BgColor != "" {
				g.dc.Fill()
			} else {
				g.dc.Stroke()
			}
		}

		// 绘制背景
		if opt.BgColor != "" {
			g.dc.SetColor(hexToRGBA(opt.BgColor))
			if opt.BorderRadius > 0 {
				g.dc.DrawRoundedRectangle(x, y, textWidth, textHeight, opt.BorderRadius)
			} else {
				g.dc.DrawRectangle(x, y, textWidth, textHeight)
			}
			g.dc.Fill()
		}

		// 绘制边框
		if opt.BorderWidth < 0.01 {
			opt.BorderWidth = 1
		}
		if opt.BorderColor != "" {
			g.dc.SetColor(hexToRGBA(opt.BorderColor))
			g.dc.SetLineWidth(opt.BorderWidth)
			if opt.BorderRadius > 0 {
				g.dc.DrawRoundedRectangle(x, y, textWidth, textHeight, opt.BorderRadius)
			} else {
				g.dc.DrawRectangle(x, y, textWidth, textHeight)
			}
			g.dc.Stroke()
		}
	}

	// 计算实际内容和绘制区域
	contentX := x + opt.PaddingX
	contentY := y + opt.PaddingY
	drawWidth := textWidth - 2*opt.PaddingX
	drawHeight := textHeight - 2*opt.PaddingY

	// 修正垂直对齐计算
	// startY := contentY + ascent + descent // 基线位置
	startY := contentY + ascent + (lineHeight-ascent-descent)/2 // 基线位置
	if drawHeight > 0 {
		// 计算文本块的实际高度
		textBlockHeight := totalHeight + descent

		switch opt.VAlign {
		case "top":
			// 顶部对齐：从顶部开始绘制
		case "middle":
			// 中间对齐：居中位置减去文本块高度的一半
			startY += (drawHeight - textBlockHeight) / 2
		case "bottom":
			// 底部对齐：从底部减去文本块高度
			startY += drawHeight - textBlockHeight
		}
	}

	// 创建阴影效果（如果有）
	if opt.ShadowOffset != 0 {
		g.dc.SetColor(hexToRGBA(opt.ShadowColor))
		for i, line := range lines {
			// 计算行位置
			lineY := startY + float64(i)*lineHeight
			// 检查行是否在可见区域内
			if drawHeight > 0 && (lineY < contentY || lineY > contentY+drawHeight) {
				continue
			}
			lineX := g.calcLineX(contentX, drawWidth, line, opt.Align)
			g.dc.DrawString(line, lineX+halfOffset, lineY+halfOffset)
		}
	}

	// 设置文本颜色
	if opt.Color != "" {
		g.dc.SetColor(hexToRGBA(opt.Color))
	}

	// 绘制文本
	for i, line := range lines {
		if line == "" {
			continue
		}

		// 计算行位置
		lineY := startY + float64(i)*lineHeight

		// 检查行是否在可见区域内
		if drawHeight > 0 && (lineY < contentY || lineY > contentY+drawHeight) {
			continue
		}

		lineX := g.calcLineX(contentX, drawWidth, line, opt.Align)
		g.dc.DrawString(line, lineX-halfOffset, lineY-halfOffset)
	}
}

// 计算行水平位置
func (g *Graphics) calcLineX(x, w float64, text, align string) float64 {
	if w <= 0 {
		return x
	}

	switch align {
	case "center":
		textW, _ := g.dc.MeasureString(text)
		return x + (w-textW)/2
	case "right":
		textW, _ := g.dc.MeasureString(text)
		return x + w - textW
	default: // left
		return x
	}
}

// 段落换行算法
func (g *Graphics) wrapParagraph(para string, maxWidth float64) []string {
	var lines []string
	currentLine := ""
	currentWidth := 0.0

	for _, r := range para {
		char := string(r)

		// 快速估算字符宽度
		charWidth := g.estimateCharWidth(r)
		if currentWidth+charWidth <= maxWidth {
			currentLine += char
			currentWidth += charWidth
			continue
		}

		// 精确测量（必要时）
		if measuredWidth, _ := g.dc.MeasureString(currentLine + char); measuredWidth <= maxWidth {
			currentLine += char
			currentWidth = measuredWidth
			continue
		}

		// 需要换行处理
		if currentLine != "" {
			lines = append(lines, currentLine)
		}

		currentLine = char
		currentWidth = g.estimateCharWidth(r)
	}

	if currentLine != "" {
		lines = append(lines, currentLine)
	}

	return lines
}

// 字符宽度估算（比实际测量高效）
func (g *Graphics) estimateCharWidth(r rune) float64 {
	if g.lastFont != nil {
		advance, ok := g.lastFont.GlyphAdvance(r)
		if ok {
			return float64(advance) / 64 // fixed.Int26_6 转像素值
		}
	}
	return g.dc.FontHeight() * 0.6 // 默认比例估算
}

// 行高计算
func (g *Graphics) calcLineHeight(multiplier float64) float64 {
	if multiplier <= 0 {
		multiplier = 1.0 // 默认行高
	}

	if g.lastFont != nil {
		metrics := g.lastFont.Metrics()
		return float64(metrics.Height) / 64 * multiplier
	}

	return g.dc.FontHeight() * multiplier
}

// MeasureText 测量文本尺寸
func (g *Graphics) MeasureText(text string) (width, height float64) {
	return g.dc.MeasureString(text)
}

// RandText 绘制随机文本并返回每个字符的位置信息
// 返回: 每个字符的位置数组 [x, y, width, height]
func (g *Graphics) RandText(text string) [][4]float64 {
	if text == "" {
		return nil
	}

	bounds := g.dc.Image().Bounds()
	w, h := bounds.Dx(), bounds.Dy()

	// 智能字体大小计算：确保字体足够大
	fontSize := math.Max(32, float64(h)*0.6) // 最小32px，高度60%
	if len(text) > 4 {
		fontSize = math.Max(28, fontSize*0.9) // 长文本适当减小
	}
	g.SetFont(fontSize)

	metrics := g.lastFont.Metrics()
	ascent := float64(metrics.Ascent) / 64
	descent := float64(metrics.Descent) / 64
	charHeight := ascent + descent
	// height := float64(metrics.Height) / 64
	fullWidth, _ := g.dc.MeasureString(text)

	// 计算初始位置（水平居中，但留出随机偏移空间）
	startX := (float64(w) - fullWidth) / 2
	startY := float64(h)/2 + ascent - charHeight/2 // 基于文本高度的垂直居中

	// 保存初始状态
	g.dc.Push()
	defer g.dc.Pop()

	// 存储每个字符的位置信息
	charPositions := make([][4]float64, 0, len(text))

	// 字符处理
	x := startX
	for _, char := range text {
		charStr := string(char)

		// 准确测量中文字符
		charWidth, _ := g.dc.MeasureString(charStr)
		// charWidth, charHeight := g.dc.MeasureString(charStr)

		// 随机Y偏移（不超过字体高度的20%）
		maxYOffset := fontSize * 0.2
		yOffset := rand.Float64()*(2*maxYOffset) - maxYOffset

		// 随机旋转（-15°到15°）
		angle := rand.Float64()*0.52 - 0.26 // ±15°弧度值

		// 记录字符位置（旋转前的原始位置）
		charPositions = append(charPositions, [4]float64{
			x,                                       // X位置
			startY + yOffset - charHeight + descent, // Y位置
			charWidth,                               // 字符宽度
			charHeight,                              // 字符高度
		})

		g.dc.Push()

		// 应用变换
		g.dc.RotateAbout(angle, x, startY+yOffset)
		g.dc.SetColor(color.Gray{Y: 50})
		g.dc.DrawString(charStr, x+1, startY+yOffset+1)
		g.dc.SetColor(generateLightTextColor())
		g.dc.DrawString(charStr, x, startY+yOffset)
		g.dc.Pop()

		// 优化间距：确保足够的字符间距
		// 基础间距为字符宽度的80%
		baseSpace := charWidth * 0.8

		// 添加随机间距（0-20%）
		randomSpace := rand.Float64() * charWidth * 0.2

		// 长文本适当减少间距
		if len(text) > 6 {
			baseSpace *= 0.9
		}

		// 根据角度调整实际水平移动
		effectiveSpace := (baseSpace + randomSpace) * math.Cos(math.Abs(angle))
		x += effectiveSpace * 1.2
	}

	return charPositions
}

// 生成浅色系文字颜色
func generateLightTextColor() color.RGBA {
	return color.RGBA{
		R: 150 + uint8(rand.Intn(106)),
		G: 150 + uint8(rand.Intn(106)),
		B: 150 + uint8(rand.Intn(106)),
		A: 190 + uint8(rand.Intn(66)),
	}
}
