package api

import (
	"embed"
	"io/fs"

	"gitlab.global.bsf.tools/esv/bsf/bsf-integration/orchard/orchard-mvp/internal/storage"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

//go:embed static/*
var staticFiles embed.FS

// SetupRouter configures all API routes
func SetupRouter(db *storage.Database, s3 *storage.S3Storage, logger *zap.Logger) *gin.Engine {
	router := gin.New()
	router.Use(gin.Recovery())
	router.Use(LoggerMiddleware(logger))

	handler := NewHandler(db, s3, logger)

	// Serve static files from embedded FS
	staticFS, _ := fs.Sub(staticFiles, "static")

	// Root - serve index.html
	router.GET("/", func(c *gin.Context) {
		data, err := fs.ReadFile(staticFS, "index.html")
		if err != nil {
			c.String(500, "Error loading page: "+err.Error())
			return
		}
		c.Data(200, "text/html; charset=utf-8", data)
	})

	// CSS file
	router.GET("/static/style.css", func(c *gin.Context) {
		data, err := fs.ReadFile(staticFS, "style.css")
		if err != nil {
			c.String(404, "Not found: "+err.Error())
			return
		}
		c.Data(200, "text/css; charset=utf-8", data)
	})

	// JS file
	router.GET("/static/app.js", func(c *gin.Context) {
		data, err := fs.ReadFile(staticFS, "app.js")
		if err != nil {
			c.String(404, "Not found: "+err.Error())
			return
		}
		c.Data(200, "application/javascript; charset=utf-8", data)
	})

	// Health check
	router.GET("/health", handler.Health)

	// API v1
	v1 := router.Group("/api/v1")
	{
		// Authentication middleware
		v1.Use(AuthMiddleware(db))

		// Grove routes
		groves := v1.Group("/groves")
		{
			groves.GET("", handler.ListGroves)
			groves.POST("", handler.CreateGrove)
			groves.GET("/:grove", handler.GetGrove)
		}

		// Tree routes
		trees := v1.Group("/grove/:grove/trees")
		{
			trees.GET("", handler.ListTrees)
			trees.POST("", handler.CreateTree)
		}

		// Fruit routes (content-addressable storage)
		fruits := v1.Group("/grove/:grove/:tree")
		{
			// Upload artifact (cultivate)
			fruits.POST("/cultivate", handler.Cultivate)

			// Download artifact (harvest)
			fruits.GET("/+/:ref", handler.Harvest)

			// List grafts (tags/versions)
			fruits.GET("/grafts", handler.ListGrafts)

			// Create graft (tag)
			fruits.POST("/graft", handler.CreateGraft)

			// Get consumers
			fruits.GET("/consumers", handler.GetConsumers)
		}

		// Direct fruit access by hash
		v1.GET("/fruit/:fruit", handler.GetFruit)

		// Search
		v1.GET("/search", handler.Search)
	}

	// Compatibility endpoint matching the URL pattern from spec
	// /grove/{project}/{tree}/+/{ref}
	router.GET("/grove/:grove/:tree/+/:ref", AuthMiddleware(db), handler.Harvest)

	return router
}

// LoggerMiddleware logs requests
func LoggerMiddleware(logger *zap.Logger) gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Next()

		logger.Info("request",
			zap.String("method", c.Request.Method),
			zap.String("path", c.Request.URL.Path),
			zap.Int("status", c.Writer.Status()),
			zap.String("client_ip", c.ClientIP()),
		)
	}
}

// AuthMiddleware handles authentication
func AuthMiddleware(db *storage.Database) gin.HandlerFunc {
	return func(c *gin.Context) {
		// Check for API key in header
		apiKey := c.GetHeader("X-Orchard-API-Key")
		if apiKey != "" {
			// TODO: Validate API key against database
			// For now, extract user ID from key
			c.Set("user_id", "api-user")
			c.Next()
			return
		}

		// Check for Bearer token
		authHeader := c.GetHeader("Authorization")
		if authHeader != "" {
			// TODO: Implement OIDC/SAML validation
			c.Set("user_id", "bearer-user")
			c.Next()
			return
		}

		// Allow anonymous access for public groves (read only)
		c.Set("user_id", "anonymous")
		c.Next()
	}
}
