package router

import (
	"encoding/json"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/gofiber/fiber/v3"

	"goimgApi/accounts"
	"goimgApi/images"
)

func SetupRoutes(app *fiber.App) {
	app.Get("/", func(c fiber.Ctx) error {
		return c.SendString("Go Image API Running")
	})

	app.Get("/uploads/*", func(c fiber.Ctx) error {
		relPath := strings.TrimPrefix(c.Params("*"), "/")
		if relPath == "" {
			return fiber.ErrNotFound
		}

		cleanPath := filepath.Clean(relPath)
		if cleanPath == "." || strings.HasPrefix(cleanPath, "..") {
			return fiber.ErrForbidden
		}

		return c.SendFile(filepath.Join("uploads", cleanPath))
	})

	// Swagger setup
	app.Get("/docs/swagger.json", func(c fiber.Ctx) error {
		raw, err := loadSwaggerSpec()
		if err != nil {
			return fiber.NewError(fiber.StatusInternalServerError, "Swagger spec could not be loaded")
		}

		var spec map[string]any
		if err := json.Unmarshal(raw, &spec); err != nil {
			return fiber.NewError(fiber.StatusInternalServerError, "Swagger spec is invalid")
		}

		delete(spec, "host")
		delete(spec, "schemes")

		return c.JSON(spec)
	})
	app.Get("/swagger", func(c fiber.Ctx) error {
		c.Set("Content-Type", "text/html")
		return c.SendString(`<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Swagger UI</title>
    <link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5.3.0/swagger-ui.css" />
</head>
<body style="margin:0;">
    <div id="swagger-ui"></div>
    <script src="https://unpkg.com/swagger-ui-dist@5.3.0/swagger-ui-bundle.js"></script>
    <script>
        window.onload = () => {
            window.ui = SwaggerUIBundle({
                url: '/docs/swagger.json',
                dom_id: '#swagger-ui',
            });
        };
    </script>
</body>
</html>`)
	})

	authGroup := app.Group("/auth")
	authGroup.Post("/register", accounts.Register)
	authGroup.Post("/login", accounts.Login)
	authGroup.Post("/refresh", accounts.Refresh)

	adminGroup := app.Group("/admin", accounts.JWTMiddleware, accounts.AdminMiddleware)
	adminGroup.Post("/users/:id/api-token", accounts.CreateApiToken)
	adminGroup.Get("/images", images.AdminListImages)

	imagesGroup := app.Group("/images", accounts.JWTMiddleware)
	imagesGroup.Post("/", images.Upload)
	imagesGroup.Get("/", images.ListImages)
	imagesGroup.Get("/:id", images.GetImage)

	// Process endpoint uses API token authentication (not JWT); keep it outside the JWT group
	app.Get("/images/:id/process", images.Process)
}

func loadSwaggerSpec() ([]byte, error) {
	if raw, err := os.ReadFile("./docs/swagger.json"); err == nil {
		return raw, nil
	}

	_, currentFile, _, ok := runtime.Caller(0)
	if !ok {
		return nil, os.ErrNotExist
	}

	projectRoot := filepath.Dir(filepath.Dir(currentFile))
	return os.ReadFile(filepath.Join(projectRoot, "docs", "swagger.json"))
}
