package util

import (
	"bytes"
	"image"
	"image/color"
	"image/jpeg"
	"image/png"
	"os"
	"path/filepath"
	"strings"

	"github.com/fogleman/gg"
	"github.com/yuin/goldmark"
	"golang.org/x/net/html"
)

const (
	defaultWidth   = 800
	defaultMargin  = 20
	lineHeight     = 1.5
	fontSize       = 14
	maxImageWidth  = 600
	maxImageHeight = 400
)

type ContentBlock struct {
	Type      string      // "text" or "image"
	Content   string      // text content or image path
	ImgWidth  float64     // image width after resize
	ImgHeight float64     // image height after resize
	Image     image.Image // loaded image
}

// TextToPicture 将文本转换为图片
func TextToPicture(text string, isMarkdown bool) (image.Image, error) {
	var htmlContent string
	if isMarkdown {
		// 将Markdown转换为HTML
		md := goldmark.New()
		var buf bytes.Buffer
		if err := md.Convert([]byte(text), &buf); err != nil {
			return nil, err
		}
		htmlContent = buf.String()
	} else {
		htmlContent = text
	}

	// 解析HTML并提取内容块
	doc, err := html.Parse(strings.NewReader(htmlContent))
	if err != nil {
		return nil, err
	}

	var blocks []ContentBlock
	var extractContent func(*html.Node)
	extractContent = func(n *html.Node) {
		if n.Type == html.TextNode {
			text := strings.TrimSpace(n.Data)
			if text != "" {
				blocks = append(blocks, ContentBlock{
					Type:    "text",
					Content: text,
				})
			}
		} else if n.Type == html.ElementNode && n.Data == "img" {
			// 处理图片节点
			var src string
			for _, attr := range n.Attr {
				if attr.Key == "src" {
					src = attr.Val
					break
				}
			}
			if src != "" && !strings.HasPrefix(src, "http") {
				// 处理本地图片
				img, w, h, err := loadAndResizeImage(src)
				if err == nil {
					blocks = append(blocks, ContentBlock{
						Type:      "image",
						Content:   src,
						Image:     img,
						ImgWidth:  w,
						ImgHeight: h,
					})
				}
			}
		}
		for c := n.FirstChild; c != nil; c = c.NextSibling {
			extractContent(c)
		}
	}
	extractContent(doc)

	// 计算总高度
	totalHeight := calculateTotalHeight(blocks)

	// 创建图片上下文
	dc := gg.NewContext(defaultWidth, totalHeight)
	dc.SetRGB(1, 1, 1) // 设置白色背景
	dc.Clear()

	// 设置字体和颜色
	if err := dc.LoadFontFace("./resource/fonts/SourceHanSansCN-Regular.otf", fontSize); err != nil {
		return nil, err
	}
	dc.SetColor(color.Black)

	// 绘制内容
	y := float64(defaultMargin)
	for _, block := range blocks {
		if block.Type == "text" {
			wrapped := dc.WordWrap(block.Content, float64(defaultWidth-2*defaultMargin))
			for _, wrappedLine := range wrapped {
				dc.DrawString(wrappedLine, float64(defaultMargin), y+fontSize)
				y += fontSize * lineHeight
			}
			y += fontSize // 段落间额外间距
		} else if block.Type == "image" {
			// 居中绘制图片
			x := (float64(defaultWidth) - block.ImgWidth) / 2
			dc.DrawImage(block.Image, int(x), int(y))
			y += block.ImgHeight + float64(defaultMargin) // 图片后添加间距
		}
	}

	return dc.Image(), nil
}

// loadAndResizeImage 加载并调整图片大小
func loadAndResizeImage(path string) (image.Image, float64, float64, error) {
	// 确保路径是绝对路径
	if !filepath.IsAbs(path) {
		path = filepath.Join(".", path)
	}

	file, err := os.Open(path)
	if err != nil {
		return nil, 0, 0, err
	}
	defer file.Close()

	// 解码图片
	var img image.Image
	if strings.HasSuffix(strings.ToLower(path), ".png") {
		img, err = png.Decode(file)
	} else {
		img, err = jpeg.Decode(file)
	}
	if err != nil {
		return nil, 0, 0, err
	}

	// 计算调整后的尺寸
	bounds := img.Bounds()
	origWidth := float64(bounds.Dx())
	origHeight := float64(bounds.Dy())

	var newWidth, newHeight float64
	if origWidth > maxImageWidth {
		ratio := maxImageWidth / origWidth
		newWidth = maxImageWidth
		newHeight = origHeight * ratio
	} else {
		newWidth = origWidth
		newHeight = origHeight
	}

	if newHeight > maxImageHeight {
		ratio := maxImageHeight / newHeight
		newHeight = maxImageHeight
		newWidth = newWidth * ratio
	}

	// 创建新的图片上下文并调整大小
	dc := gg.NewContext(int(newWidth), int(newHeight))
	dc.DrawImage(img, 0, 0)

	return dc.Image(), newWidth, newHeight, nil
}

// calculateTotalHeight 计算总高度
func calculateTotalHeight(blocks []ContentBlock) int {
	var totalHeight float64 = float64(2 * defaultMargin) // 上下边距

	for _, block := range blocks {
		if block.Type == "text" {
			// 估算文本高度
			estimatedLines := (len(block.Content)*fontSize)/(defaultWidth-2*defaultMargin) + 1
			totalHeight += float64(estimatedLines) * fontSize * lineHeight
			totalHeight += fontSize // 段落间距
		} else if block.Type == "image" {
			totalHeight += block.ImgHeight + float64(defaultMargin) // 图片高度加间距
		}
	}

	return int(totalHeight)
}
