// Upload 模块：图片上传（支持上传到微信服务器和 MinIO，公开接口，无需权限）
package upload

import (
	"context"
	"io"
	"net/http"
	"path/filepath"
	"strings"
	"time"

	"com.sclktx/m/v2/internal/common/response"
	"com.sclktx/m/v2/internal/pkg/minio"
	"com.sclktx/m/v2/internal/pkg/wechat"

	"github.com/gin-gonic/gin"
)

// UploadHandler 上传处理器
type UploadHandler struct {
	wxClient    *wechat.MiniProgramClient
	minioClient *minio.Client
}

// NewUploadHandler 创建上传处理器
func NewUploadHandler(wxClient *wechat.MiniProgramClient, minioClient *minio.Client) *UploadHandler {
	return &UploadHandler{
		wxClient:    wxClient,
		minioClient: minioClient,
	}
}

// UploadImgResponse 上传图片返回
type UploadImgResponse struct {
	URL string `json:"url"` // 微信返回的图片 URL
}

// @Summary      上传图片到微信服务器
// @Description  上传图片文件到微信服务器（公开接口，无需权限）
// @Tags         文件上传
// @Accept       multipart/form-data
// @Produce      json
// @Param        file  formData  file  true  "图片文件"
// @Success      200  {object}  response.Response{data=upload.UploadImgResponse}  "success"
// @Router       /api/v1/upload/image [post]
// UploadImage 上传图片文件到微信服务器（公开接口，无需权限）
// POST /api/v1/upload/image
func (h *UploadHandler) UploadImage(c *gin.Context) {
	// 获取上传的文件
	file, header, err := c.Request.FormFile("file")
	if err != nil {
		response.BadRequest(c, "请选择要上传的图片文件")
		return
	}
	defer file.Close()

	// 读取文件内容
	imageData, err := io.ReadAll(file)
	if err != nil {
		response.InternalError(c, "读取文件失败")
		return
	}

	// 获取文件名，如果没有则生成一个
	filename := header.Filename
	if filename == "" {
		filename = "image_" + time.Now().Format("20060102150405") + ".jpg"
	}

	// 确保文件名有扩展名
	ext := strings.ToLower(filepath.Ext(filename))
	if ext == "" {
		// 根据 Content-Type 猜测扩展名
		contentType := header.Header.Get("Content-Type")
		switch contentType {
		case "image/png":
			filename += ".png"
		case "image/gif":
			filename += ".gif"
		case "image/webp":
			filename += ".webp"
		default:
			filename += ".jpg"
		}
	}

	// 上传到微信服务器
	result, err := h.wxClient.UploadImg(imageData, filename)
	if err != nil {
		response.InternalError(c, "上传到微信失败: "+err.Error())
		return
	}

	response.Success(c, &UploadImgResponse{URL: result.URL})
}

// UploadImageByURLRequest 通过链接上传请求
type UploadImageByURLRequest struct {
	URL string `json:"url" binding:"required"` // 图片链接
}

// @Summary      通过链接上传图片到微信服务器
// @Description  通过图片链接下载后上传到微信服务器（公开接口，无需权限）
// @Tags         文件上传
// @Accept       json
// @Produce      json
// @Param        body  body  upload.UploadImageByURLRequest  true  "图片链接信息"
// @Success      200  {object}  response.Response{data=upload.UploadImgResponse}  "success"
// @Router       /api/v1/upload/image-by-url [post]
// UploadImageByURL 通过图片链接下载后上传到微信服务器（公开接口，无需权限）
// POST /api/v1/upload/image-by-url
func (h *UploadHandler) UploadImageByURL(c *gin.Context) {
	var req UploadImageByURLRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "请提供图片链接(url)")
		return
	}

	// 下载图片（使用自定义请求，添加 User-Agent 避免被反爬拦截）
	httpReq, err := http.NewRequest("GET", req.URL, nil)
	if err != nil {
		response.InternalError(c, "创建请求失败: "+err.Error())
		return
	}
	httpReq.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")

	client := &http.Client{Timeout: 30 * time.Second}
	resp, err := client.Do(httpReq)
	if err != nil {
		response.InternalError(c, "下载图片失败: "+err.Error())
		return
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		response.InternalError(c, "下载图片失败，HTTP状态码: "+http.StatusText(resp.StatusCode))
		return
	}

	imageData, err := io.ReadAll(resp.Body)
	if err != nil {
		response.InternalError(c, "读取图片数据失败")
		return
	}

	// 从 URL 中提取文件名
	filename := extractFilenameFromURL(req.URL)
	contentType := resp.Header.Get("Content-Type")
	ext := getExtByContentType(contentType)
	if !strings.HasSuffix(strings.ToLower(filename), ext) && ext != "" {
		filename += ext
	}

	// 上传到微信服务器
	result, err := h.wxClient.UploadImg(imageData, filename)
	if err != nil {
		response.InternalError(c, "上传到微信失败: "+err.Error())
		return
	}

	response.Success(c, &UploadImgResponse{URL: result.URL})
}

// extractFilenameFromURL 从 URL 中提取文件名
func extractFilenameFromURL(rawURL string) string {
	// 去掉查询参数
	if idx := strings.Index(rawURL, "?"); idx != -1 {
		rawURL = rawURL[:idx]
	}
	// 取最后一段作为文件名
	base := filepath.Base(rawURL)
	if base == "." || base == "/" || base == "" {
		return "image_" + time.Now().Format("20060102150405") + ".jpg"
	}
	return base
}

// getExtByContentType 根据 Content-Type 获取文件扩展名
func getExtByContentType(contentType string) string {
	switch {
	case strings.Contains(contentType, "image/png"):
		return ".png"
	case strings.Contains(contentType, "image/gif"):
		return ".gif"
	case strings.Contains(contentType, "image/webp"):
		return ".webp"
	case strings.Contains(contentType, "image/svg"):
		return ".svg"
	case strings.Contains(contentType, "image/jpeg"):
		return ".jpg"
	default:
		return ".jpg"
	}
}

// UploadToMinioResponse 上传到 MinIO 返回
type UploadToMinioResponse struct {
	URL string `json:"url"` // MinIO 中的图片 URL
}

// @Summary      上传图片到MinIO对象存储
// @Description  上传图片到 MinIO 对象存储（公开接口，无需权限）
// @Tags         文件上传
// @Accept       multipart/form-data
// @Produce      json
// @Param        file  formData  file  true  "图片文件"
// @Success      200  {object}  response.Response{data=upload.UploadToMinioResponse}  "success"
// @Router       /api/v1/upload/minio [post]
// UploadImageToMinio 上传图片到 MinIO 对象存储（公开接口，无需权限）
// POST /api/v1/upload/minio
func (h *UploadHandler) UploadImageToMinio(c *gin.Context) {
	// 获取上传的文件
	file, header, err := c.Request.FormFile("file")
	if err != nil {
		response.BadRequest(c, "请选择要上传的图片文件")
		return
	}
	defer file.Close()

	// 读取文件内容
	imageData, err := io.ReadAll(file)
	if err != nil {
		response.InternalError(c, "读取文件失败")
		return
	}

	// 获取文件名，如果没有则生成一个
	filename := header.Filename
	if filename == "" {
		filename = "image_" + time.Now().Format("20060102150405") + ".jpg"
	}

	// 确保文件名有扩展名
	ext := strings.ToLower(filepath.Ext(filename))
	if ext == "" {
		// 根据 Content-Type 猜测扩展名
		contentType := header.Header.Get("Content-Type")
		switch contentType {
		case "image/png":
			filename += ".png"
		case "image/gif":
			filename += ".gif"
		case "image/webp":
			filename += ".webp"
		default:
			filename += ".jpg"
		}
	}

	// 上传到 MinIO
	ctx := context.Background()
	url, err := h.minioClient.UploadImage(ctx, imageData, filename)
	if err != nil {
		response.InternalError(c, "上传到 MinIO 失败："+err.Error())
		return
	}

	response.Success(c, &UploadToMinioResponse{URL: url})
}

// RegisterRoutes 注册上传路由（公开接口，无需认证和权限）
func (h *UploadHandler) RegisterRoutes(r *gin.RouterGroup) {
	r.POST("/upload/image", h.UploadImage)
	r.POST("/upload/image-by-url", h.UploadImageByURL)
	r.POST("/upload/minio", h.UploadImageToMinio)
}
