package admin

import (
	"fmt"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
)

var allowedCategories = map[string]bool{
	"reports": true,
	"custody": true,
	"links":   true,
}

var allowedExts = map[string]bool{
	".pdf":  true,
	".png":  true,
	".jpg":  true,
	".jpeg": true,
	".doc":  true,
	".docx": true,
	".txt":  true,
	".xls":  true,
	".xlsx": true,
}

// UploadFile handles multipart file uploads, saves to ./uploads/{category}/, returns accessible URL.
// Query param: category (reports|custody), defaults to "reports".
func UploadFile(c *gin.Context) {
	file, err := c.FormFile("file")
	if err != nil {
		Fail(c, http.StatusBadRequest, "No file provided")
		return
	}

	ext := strings.ToLower(filepath.Ext(file.Filename))
	if !allowedExts[ext] {
		Fail(c, http.StatusBadRequest, "File type not allowed")
		return
	}

	category := c.DefaultQuery("category", "reports")
	if !allowedCategories[category] {
		Fail(c, http.StatusBadRequest, "Invalid category")
		return
	}

	dir := "uploads/" + category
	if err := os.MkdirAll(dir, 0755); err != nil {
		Fail(c, http.StatusInternalServerError, "Failed to create upload directory")
		return
	}

	filename := fmt.Sprintf("%d_%s", time.Now().UnixNano(), filepath.Base(file.Filename))
	dst := filepath.Join(dir, filename)

	if err := c.SaveUploadedFile(file, dst); err != nil {
		Fail(c, http.StatusInternalServerError, "Failed to save file")
		return
	}

	url := "/uploads/" + category + "/" + filename
	OK(c, gin.H{"url": url})
}

// DeleteUploadedFile deletes a previously uploaded file by its URL path.
func DeleteUploadedFile(c *gin.Context) {
	urlPath := c.Query("path") // e.g. /uploads/reports/xxx.pdf or /uploads/custody/xxx.pdf
	if !strings.HasPrefix(urlPath, "/uploads/") {
		Fail(c, http.StatusBadRequest, "Invalid file path")
		return
	}
	if strings.Contains(urlPath, "..") {
		Fail(c, http.StatusBadRequest, "Invalid file path")
		return
	}
	// Verify the second segment is a known category
	parts := strings.SplitN(strings.TrimPrefix(urlPath, "/uploads/"), "/", 2)
	if len(parts) != 2 || !allowedCategories[parts[0]] {
		Fail(c, http.StatusBadRequest, "Invalid file path")
		return
	}

	localPath := strings.TrimPrefix(urlPath, "/")
	if err := os.Remove(localPath); err != nil {
		if os.IsNotExist(err) {
			OK(c, gin.H{"message": "file not found, skipped"})
			return
		}
		Fail(c, http.StatusInternalServerError, "Failed to delete file")
		return
	}
	OK(c, gin.H{"message": "deleted"})
}
