package media

import (
	"fmt"
	"io"
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"

	"github.com/tidbcloud/AgentTeam/internal/api"
	"github.com/tidbcloud/AgentTeam/internal/store/attachment"
)

func uploadFieldRequiredMessage(field string) string {
	if field == "files" {
		return "files are required"
	}
	return field + " is required"
}

func uploadedSingleAttachmentParam(ctx *gin.Context, field string, maxSizeBytes int, imagesOnly bool) (attachment.CreateAttachmentParams, bool) {
	files := ctx.Request.MultipartForm.File[field]
	if len(files) == 0 {
		api.Error(ctx, http.StatusBadRequest, uploadFieldRequiredMessage(field))
		return attachment.CreateAttachmentParams{}, false
	}

	header := files[0]
	opened, err := header.Open()
	if err != nil {
		api.Error(ctx, http.StatusBadRequest, "Invalid file upload")
		return attachment.CreateAttachmentParams{}, false
	}

	limited := io.LimitReader(opened, int64(maxSizeBytes)+1)
	blob, err := io.ReadAll(limited)
	_ = opened.Close()
	if err != nil {
		api.Error(ctx, http.StatusBadRequest, "Failed to read uploaded file")
		return attachment.CreateAttachmentParams{}, false
	}
	if len(blob) > maxSizeBytes {
		api.Error(ctx, http.StatusBadRequest, fmt.Sprintf("file too large (max %d bytes)", maxSizeBytes))
		return attachment.CreateAttachmentParams{}, false
	}

	contentType := strings.TrimSpace(header.Header.Get("Content-Type"))
	if contentType == "" {
		contentType = http.DetectContentType(blob)
	}
	if imagesOnly && !strings.HasPrefix(contentType, "image/") {
		api.Error(ctx, http.StatusBadRequest, "Only image files are allowed")
		return attachment.CreateAttachmentParams{}, false
	}

	return attachment.CreateAttachmentParams{
		Filename:    header.Filename,
		ContentType: contentType,
		Blob:        blob,
	}, true
}

func uploadedAttachmentParams(ctx *gin.Context, field string, maxCount int, maxSizeBytes int, imagesOnly bool) ([]attachment.CreateAttachmentParams, bool) {
	files := ctx.Request.MultipartForm.File[field]
	if len(files) == 0 {
		api.Error(ctx, http.StatusBadRequest, uploadFieldRequiredMessage(field))
		return nil, false
	}
	if maxCount > 0 && len(files) > maxCount {
		api.Error(ctx, http.StatusBadRequest, fmt.Sprintf("too many files (max %d)", maxCount))
		return nil, false
	}

	params := make([]attachment.CreateAttachmentParams, 0, len(files))
	for _, header := range files {
		opened, err := header.Open()
		if err != nil {
			api.Error(ctx, http.StatusBadRequest, "Invalid file upload")
			return nil, false
		}

		limited := io.LimitReader(opened, int64(maxSizeBytes)+1)
		blob, err := io.ReadAll(limited)
		_ = opened.Close()
		if err != nil {
			api.Error(ctx, http.StatusBadRequest, "Failed to read uploaded file")
			return nil, false
		}
		if len(blob) > maxSizeBytes {
			api.Error(ctx, http.StatusBadRequest, fmt.Sprintf("file too large (max %d bytes)", maxSizeBytes))
			return nil, false
		}

		contentType := strings.TrimSpace(header.Header.Get("Content-Type"))
		if contentType == "" {
			contentType = http.DetectContentType(blob)
		}
		if imagesOnly && !strings.HasPrefix(contentType, "image/") {
			api.Error(ctx, http.StatusBadRequest, "Only image files are allowed")
			return nil, false
		}

		params = append(params, attachment.CreateAttachmentParams{
			Filename:    header.Filename,
			ContentType: contentType,
			Blob:        blob,
		})
	}
	return params, true
}
