package matrix

import (
	"context"
	"fmt"
	"mime"
	"os"
	"path/filepath"

	"maunium.net/go/mautrix"
	"maunium.net/go/mautrix/id"
)

// UploadMedia uploads the file at filePath to the Matrix media repository
// and returns its mxc:// URI. Does NOT set the avatar — use SetAvatarURL
// or SetAvatar for that.
func (c *Client) UploadMedia(ctx context.Context, filePath string) (string, error) {
	f, err := os.Open(filePath)
	if err != nil {
		return "", fmt.Errorf("open %s: %w", filePath, err)
	}
	defer f.Close()

	info, err := f.Stat()
	if err != nil {
		return "", fmt.Errorf("stat %s: %w", filePath, err)
	}

	mimeType := mime.TypeByExtension(filepath.Ext(filePath))
	if mimeType == "" {
		mimeType = "application/octet-stream"
	}

	resp, err := c.raw.UploadMedia(ctx, mautrix.ReqUploadMedia{
		Content:       f,
		ContentLength: info.Size(),
		ContentType:   mimeType,
		FileName:      filepath.Base(filePath),
	})
	if err != nil {
		return "", fmt.Errorf("upload media: %w", err)
	}

	return resp.ContentURI.String(), nil
}

// SetAvatarURL sets the bot's avatar to an already-uploaded mxc:// URI.
func (c *Client) SetAvatarURL(ctx context.Context, mxcURI string) error {
	parsed, err := id.ParseContentURI(mxcURI)
	if err != nil {
		return fmt.Errorf("parse mxc URI %q: %w", mxcURI, err)
	}
	if err := c.raw.SetAvatarURL(ctx, parsed); err != nil {
		return fmt.Errorf("set avatar URL: %w", err)
	}
	return nil
}

// SetAvatar uploads the image at filePath and sets it as the bot's avatar.
// Convenience wrapper: calls UploadMedia then SetAvatarURL.
func (c *Client) SetAvatar(ctx context.Context, filePath string) (string, error) {
	uri, err := c.UploadMedia(ctx, filePath)
	if err != nil {
		return "", err
	}
	if err := c.SetAvatarURL(ctx, uri); err != nil {
		return "", err
	}
	return uri, nil
}

// SetDisplayName sets the bot's display name on the Matrix homeserver.
func (c *Client) SetDisplayName(ctx context.Context, name string) error {
	if err := c.raw.SetDisplayName(ctx, name); err != nil {
		return fmt.Errorf("set display name: %w", err)
	}
	return nil
}
