package main

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

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

const (
	UPLOAD_DIR    = "./uploads"
	MAX_FILE_SIZE = 10 << 20
)

func main() {
	if err := os.MkdirAll(UPLOAD_DIR, 0755); err != nil {
		panic(fmt.Sprintf("Failed to create upload directory: %v", err))
	}

	router := gin.Default()

	router.LoadHTMLGlob("templates/*")

	router.GET("/", homeHandler)
	router.POST("/upload", uploadHandler)

	router.Static("/static", "./static")

	router.Run(":8787")
}

func homeHandler(c *gin.Context) {
	c.HTML(http.StatusOK, "index.html", gin.H{
		"title": "town share",
	})
}

func uploadHandler(c *gin.Context) {
	file, header, err := c.Request.FormFile("image")
	if err != nil {
		renderError(c, "melancholy")
		return
	}
	defer file.Close()

	if header.Size > MAX_FILE_SIZE {
		renderError(c, "max size is 10mb")
		return
	}

	contentType := header.Header.Get("Content-Type")
	if !isValidImageType(contentType) {
		renderError(c, "only jpg, png, and gif are supported")
		return
	}

	// TODO tweak this
	extension := filepath.Ext(header.Filename)
	uniqueFilename := fmt.Sprintf("%s-%s%s",
		uuid.New().String(),
		time.Now().Format("20060102-150405"),
		extension,
	)

	destPath := filepath.Join(UPLOAD_DIR, uniqueFilename)
	dest, err := os.Create(destPath)
	if err != nil {
		renderError(c, "Failed to save file")
		return
	}
	defer dest.Close()

	if _, err := io.Copy(dest, file); err != nil {
		renderError(c, "Failed to save file")
		return
	}

	// TODO global const for title
	c.HTML(http.StatusOK, "index.html", gin.H{
		"title":   "town share",
		"success": fmt.Sprintf("file uploaded successfully as %s", uniqueFilename),
	})
}

// renderError renders the home page with an error message
func renderError(c *gin.Context, message string) {
	c.HTML(http.StatusOK, "index.html", gin.H{
		"title": "town share",
		"error": message,
	})
}

// isValidImageType checks if the content type is a supported image format
func isValidImageType(contentType string) bool {
	validTypes := map[string]bool{
		"image/jpeg": true,
		"image/jpg":  true,
		"image/png":  true,
		"image/gif":  true,
	}
	return validTypes[contentType]
}
