package prediction

import (
	"bytes"
	"fmt"
	"net/url"
	"path"
	"strings"
)

func imageFilenameFromURL(raw string, data []byte) string {
	name := ""
	if u, err := url.Parse(raw); err == nil {
		if base := path.Base(u.Path); base != "" && base != "." && base != "/" {
			name = base
		}
	}
	if name == "" {
		name = "input"
	}
	name = sanitizeUploadFilename(name)
	if path.Ext(name) == "" {
		name += sniffImageExt(data)
	}
	return name
}

func imageFilenameFromStored(filename, mime string, data []byte) string {
	name := filename
	if name == "" {
		name = "input"
	}
	name = sanitizeUploadFilename(name)
	if path.Ext(name) == "" {
		if ext := extFromMime(mime); ext != "" {
			name += ext
		} else {
			name += sniffImageExt(data)
		}
	}
	return name
}

func sanitizeUploadFilename(name string) string {
	name = path.Base(name)
	replacer := strings.NewReplacer(
		"?", "_",
		"&", "_",
		"=", "_",
		"#", "_",
		"%", "_",
		"\\", "_",
		":", "_",
		"*", "_",
		"\"", "_",
		"<", "_",
		">", "_",
		"|", "_",
	)
	name = replacer.Replace(name)
	name = strings.TrimSpace(name)
	if name == "" || name == "." {
		return "input"
	}
	return name
}

func sniffImageExt(data []byte) string {
	switch {
	case len(data) >= 3 && data[0] == 0xFF && data[1] == 0xD8 && data[2] == 0xFF:
		return ".jpg"
	case len(data) >= 8 && bytes.Equal(data[:8], []byte{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}):
		return ".png"
	case len(data) >= 12 && bytes.Equal(data[:4], []byte("RIFF")) && bytes.Equal(data[8:12], []byte("WEBP")):
		return ".webp"
	case len(data) >= 6 && (bytes.Equal(data[:6], []byte("GIF87a")) || bytes.Equal(data[:6], []byte("GIF89a"))):
		return ".gif"
	default:
		return ".png"
	}
}

func extFromMime(mime string) string {
	switch strings.ToLower(strings.TrimSpace(mime)) {
	case "image/jpeg", "image/jpg":
		return ".jpg"
	case "image/png":
		return ".png"
	case "image/webp":
		return ".webp"
	case "image/gif":
		return ".gif"
	default:
		return ""
	}
}

func parseGatewayFileID(raw string) (string, bool) {
	u, err := url.Parse(raw)
	if err != nil {
		return "", false
	}
	segments := strings.Split(strings.Trim(u.Path, "/"), "/")
	if len(segments) == 2 && segments[0] == "files" && segments[1] != "" {
		return segments[1], true
	}
	return "", false
}

func validateImageBytes(data []byte) error {
	if len(data) == 0 {
		return fmt.Errorf("empty image payload")
	}
	if !looksLikeImage(data) {
		return fmt.Errorf("unrecognized image format")
	}
	return nil
}

func looksLikeImage(data []byte) bool {
	switch {
	case len(data) >= 3 && data[0] == 0xFF && data[1] == 0xD8 && data[2] == 0xFF:
		return true
	case len(data) >= 8 && bytes.Equal(data[:8], []byte{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}):
		return true
	case len(data) >= 12 && bytes.Equal(data[:4], []byte("RIFF")) && bytes.Equal(data[8:12], []byte("WEBP")):
		return true
	case len(data) >= 6 && (bytes.Equal(data[:6], []byte("GIF87a")) || bytes.Equal(data[:6], []byte("GIF89a"))):
		return true
	default:
		return false
	}
}
