package infra

import "bytes"

// fileSignature describe el magic byte signature de un tipo de archivo.
type fileSignature struct {
	mime   string
	prefix []byte
	// Para WebP: el prefix son los primeros 4 bytes "RIFF", luego 4 bytes de tamaño,
	// luego suffix en offset 8: "WEBP".
	suffix       []byte
	suffixOffset int
}

// fileSignatures es la tabla interna de magic bytes soportados.
var fileSignatures = []fileSignature{
	{mime: "image/jpeg", prefix: []byte{0xFF, 0xD8, 0xFF}},
	{mime: "image/png", prefix: []byte{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}},
	{mime: "image/gif", prefix: []byte{0x47, 0x49, 0x46, 0x38}},
	{mime: "application/pdf", prefix: []byte{0x25, 0x50, 0x44, 0x46}},
	{mime: "image/webp", prefix: []byte{0x52, 0x49, 0x46, 0x46}, suffix: []byte{0x57, 0x45, 0x42, 0x50}, suffixOffset: 8},
	{mime: "application/zip", prefix: []byte{0x50, 0x4B, 0x03, 0x04}},
}

// FileValidateType detecta el MIME type real de un archivo a partir de sus primeros
// bytes (magic bytes / file signature) y verifica que esta en la lista permitida.
//
// Retorna el MIME type detectado y true si esta permitido. Si no se puede detectar
// el tipo o no esta en allowedTypes, retorna "" y false.
//
// Funcion pura — no hace I/O. La validacion por magic bytes es mas segura que confiar
// en el header Content-Type del request, que puede ser falsificado.
func FileValidateType(header []byte, allowedTypes []string) (string, bool) {
	mime := detectMimeType(header)
	if mime == "" {
		return "", false
	}
	for _, allowed := range allowedTypes {
		if allowed == mime {
			return mime, true
		}
	}
	return mime, false
}

// detectMimeType busca el primer signature que matchee header.
func detectMimeType(header []byte) string {
	for _, sig := range fileSignatures {
		if len(header) < len(sig.prefix) {
			continue
		}
		if !bytes.Equal(header[:len(sig.prefix)], sig.prefix) {
			continue
		}
		if len(sig.suffix) > 0 {
			end := sig.suffixOffset + len(sig.suffix)
			if len(header) < end {
				continue
			}
			if !bytes.Equal(header[sig.suffixOffset:end], sig.suffix) {
				continue
			}
		}
		return sig.mime
	}
	return ""
}
