package daemon

import (
	"encoding/json"
	"fmt"
	"strings"
)

type ImageMimeType string

const (
	ImagePNG  ImageMimeType = "image/png"
	ImageJPEG ImageMimeType = "image/jpeg"
	ImageWEBP ImageMimeType = "image/webp"
)

type ImageMetadata struct {
	MimeType ImageMimeType `json:"mimeType"`
	Width    int           `json:"width"`
	Height   int           `json:"height"`
	Bytes    int           `json:"bytes"`
}

type ImageAttachment struct {
	Data string `json:"data"`
	ImageMetadata
}

var validMimeTypes = map[ImageMimeType]bool{
	ImagePNG:  true,
	ImageJPEG: true,
	ImageWEBP: true,
}

// ParseImageMetadata validates raw image metadata fields and returns nil if invalid.
func ParseImageMetadata(val any) *ImageMetadata {
	if val == nil {
		return nil
	}

	data, err := json.Marshal(val)
	if err != nil {
		return nil
	}

	var meta ImageMetadata
	if err := json.Unmarshal(data, &meta); err != nil {
		return nil
	}

	if !validMimeTypes[meta.MimeType] {
		return nil
	}

	if meta.Width < 1 || meta.Width > 16384 {
		return nil
	}
	if meta.Height < 1 || meta.Height > 16384 {
		return nil
	}
	if int64(meta.Width)*int64(meta.Height) > 40_000_000 {
		return nil
	}
	if meta.Bytes < 1 || meta.Bytes > 5*1024*1024 {
		return nil
	}

	return &meta
}

// ImageLabel returns human-readable label for image metadata.
func ImageLabel(meta ImageMetadata) string {
	var size string
	if meta.Bytes >= 1024*1024 {
		size = fmt.Sprintf("%.1f MB", float64(meta.Bytes)/1024.0/1024.0)
	} else if meta.Bytes >= 1024 {
		size = fmt.Sprintf("%d KB", (meta.Bytes+1023)/1024)
	} else {
		size = fmt.Sprintf("%d B", meta.Bytes)
	}

	prefix := strings.ToUpper(strings.TrimPrefix(string(meta.MimeType), "image/"))

	return fmt.Sprintf("%s %d×%d · %s", prefix, meta.Width, meta.Height, size)
}
