package handlers

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"strings"

	"aggios-app/backend/internal/config"

	"github.com/gorilla/mux"
	"github.com/minio/minio-go/v7"
	"github.com/minio/minio-go/v7/pkg/credentials"
)

type FilesHandler struct {
	config *config.Config
}

func NewFilesHandler(cfg *config.Config) *FilesHandler {
	return &FilesHandler{
		config: cfg,
	}
}

// ServeFile serves files from MinIO through the API
func (h *FilesHandler) ServeFile(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	bucket := vars["bucket"]
	
	// Get the file path (everything after /api/files/{bucket}/)
	prefix := fmt.Sprintf("/api/files/%s/", bucket)
	filePath := strings.TrimPrefix(r.URL.Path, prefix)
	
	if filePath == "" {
		http.Error(w, "File path is required", http.StatusBadRequest)
		return
	}

	// Whitelist de buckets públicos permitidos
	allowedBuckets := map[string]bool{
		"aggios-logos": true,
	}
	if !allowedBuckets[bucket] {
		log.Printf("🚫 Access denied to bucket: %s", bucket)
		http.Error(w, "Access denied", http.StatusForbidden)
		return
	}

	// Proteção contra path traversal
	if strings.Contains(filePath, "..") {
		log.Printf("🚫 Path traversal attempt detected: %s", filePath)
		http.Error(w, "Invalid path", http.StatusBadRequest)
		return
	}

	log.Printf("📁 Serving file: bucket=%s, path=%s", bucket, filePath)

	// Initialize MinIO client
	minioClient, err := minio.New("aggios-minio:9000", &minio.Options{
		Creds:  credentials.NewStaticV4("minioadmin", "M1n10_S3cur3_P@ss_2025!", ""),
		Secure: false,
	})
	if err != nil {
		log.Printf("Failed to create MinIO client: %v", err)
		http.Error(w, "Storage service unavailable", http.StatusInternalServerError)
		return
	}

	// Get object from MinIO
	ctx := context.Background()
	object, err := minioClient.GetObject(ctx, bucket, filePath, minio.GetObjectOptions{})
	if err != nil {
		log.Printf("Failed to get object: %v", err)
		http.Error(w, "File not found", http.StatusNotFound)
		return
	}
	defer object.Close()

	// Get object info for content type and size
	objInfo, err := object.Stat()
	if err != nil {
		log.Printf("Failed to stat object: %v", err)
		http.Error(w, "File not found", http.StatusNotFound)
		return
	}

	// Set appropriate headers
	w.Header().Set("Content-Type", objInfo.ContentType)
	w.Header().Set("Content-Length", fmt.Sprintf("%d", objInfo.Size))
	w.Header().Set("Cache-Control", "public, max-age=31536000") // Cache for 1 year
	w.Header().Set("Access-Control-Allow-Origin", "*")

	// Copy file content to response
	_, err = io.Copy(w, object)
	if err != nil {
		log.Printf("Failed to copy object content: %v", err)
		return
	}

	log.Printf("✅ File served successfully: %s", filePath)
}
