package profilepicture

import (
	"bytes"
	"fmt"
	"image"
	"image/color"
	"io"

	"github.com/disintegration/imageorient"
	"github.com/disintegration/imaging"
	"golang.org/x/image/font"
	"golang.org/x/image/font/opentype"
	"golang.org/x/image/math/fixed"
	"golang.org/x/image/webp"

	"github.com/pocket-id/pocket-id/backend/resources"
)

const profilePictureSize = 300

// CreateProfilePicture resizes the profile picture to a square and encodes it as PNG
func CreateProfilePicture(file io.ReadSeeker) (io.ReadSeeker, error) {
	// Attempt standard formats first
	img, _, err := imageorient.Decode(file)
	if err != nil {
		if _, seekErr := file.Seek(0, io.SeekStart); seekErr != nil {
			return nil, fmt.Errorf("failed to seek file: %w", seekErr)
		}
		// Try WebP
		webpImg, webpErr := webp.Decode(file)
		if webpErr != nil {
			return nil, fmt.Errorf("failed to decode image: %w", err)
		}

		img = webpImg
	}

	// Resize to square
	img = imaging.Fill(img, profilePictureSize, profilePictureSize, imaging.Center, imaging.Lanczos)

	// Encode back to PNG
	var buf bytes.Buffer
	if err := imaging.Encode(&buf, img, imaging.PNG); err != nil {
		return nil, fmt.Errorf("failed to encode image: %w", err)
	}

	return bytes.NewReader(buf.Bytes()), nil
}

// CreateDefaultProfilePicture creates a profile picture with the initials
func CreateDefaultProfilePicture(initials string) (*bytes.Buffer, error) {
	// Create a blank image with a white background
	img := imaging.New(profilePictureSize, profilePictureSize, color.RGBA{R: 255, G: 255, B: 255, A: 255})

	// Load the font
	fontBytes, err := resources.FS.ReadFile("fonts/Gloock.ttf")
	if err != nil {
		return nil, fmt.Errorf("failed to read font file: %w", err)
	}

	// Parse the font
	fontFace, err := opentype.Parse(fontBytes)
	if err != nil {
		return nil, fmt.Errorf("failed to parse font: %w", err)
	}

	// Create a font.Face with a specific size
	fontSize := 160.0
	face, err := opentype.NewFace(fontFace, &opentype.FaceOptions{
		Size: fontSize,
		DPI:  72,
	})
	if err != nil {
		return nil, fmt.Errorf("failed to create font face: %w", err)
	}

	// Create a drawer for the image
	drawer := &font.Drawer{
		Dst:  img,
		Src:  image.NewUniform(color.RGBA{R: 0, G: 0, B: 0, A: 255}), // Black text color
		Face: face,
	}

	// Center the initials
	x := (profilePictureSize - font.MeasureString(face, initials).Ceil()) / 2
	y := (profilePictureSize-face.Metrics().Height.Ceil())/2 + face.Metrics().Ascent.Ceil()
	drawer.Dot = fixed.P(x, y)

	// Draw the initials
	drawer.DrawString(initials)

	var buf bytes.Buffer
	err = imaging.Encode(&buf, img, imaging.PNG)
	if err != nil {
		return nil, fmt.Errorf("failed to encode image: %w", err)
	}

	return &buf, nil
}
