// Package api mounts admin's HTTP surface.
//
// The route table is the single place scoping is guaranteed. Customer routes
// live behind RequireCustomer and every handler that names an instance calls
// ownedInstance. A new customer route that skips that helper is a scoping bug,
// so keep them together and review them together.
package api

import (
	"net/http"
	"slices"

	"github.com/gin-gonic/gin"
	"github.com/mrhid6/vantage/admin/internal/auth"
	"github.com/mrhid6/vantage/admin/internal/config"
)

func Routes(cfg config.Config) http.Handler {
	r := gin.New()
	r.Use(gin.Logger(), gin.Recovery())
	r.Use(cors(cfg.AllowedOrigins))

	if cfg.TrustProxy {
		_ = r.SetTrustedProxies(nil)
	}

	r.GET("/healthz", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"ok": true}) })

	r.POST("/auth/staff/login", auth.HandleStaffLogin)
	r.POST("/auth/login", auth.HandleCloudLogin) // falls through to customer login
	r.POST("/auth/logout", auth.HandleLogout)
	r.GET("/auth/verify", auth.HandleVerify)

	cust := r.Group("/api")
	cust.Use(auth.RequireCustomer())
	{
		cust.GET("/account", getAccount)
		cust.POST("/instances/link", linkInstance)
		cust.POST("/instances/:id/relink", relinkInstance)
		cust.GET("/instances/:id/license", getInstanceLicense)
		cust.GET("/instances/:id/license/download", downloadInstanceLicense)
		cust.GET("/subscriptions", listSubscriptions)
	}

	staff := r.Group("/api/staff")
	staff.Use(auth.RequireStaff())
	{
		staff.GET("/accounts", staffListAccounts)
		staff.POST("/accounts", staffCreateAccount)
		staff.GET("/accounts/:id", staffGetAccount)
		staff.GET("/instances", staffListInstances)
		staff.POST("/instances", staffCreateInstance)
		staff.POST("/instances/:id/issue", staffIssue)
		staff.POST("/instances/:id/relink", staffRelink)
		staff.GET("/licenses", staffListLicenses)
		staff.GET("/plans", staffListPlans)
		staff.PUT("/plans/:tier", staffUpdatePlan)
		staff.GET("/audit", staffAudit)
		staff.GET("/health/injection", staffInjectionHealth)
	}

	return r
}

func cors(allowed []string) gin.HandlerFunc {
	return func(c *gin.Context) {
		origin := c.GetHeader("Origin")
		if origin != "" && slices.Contains(allowed, origin) {
			c.Header("Access-Control-Allow-Origin", origin)
			c.Header("Access-Control-Allow-Credentials", "true")
			c.Header("Access-Control-Allow-Headers", "Content-Type")
			c.Header("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
		}
		if c.Request.Method == http.MethodOptions {
			c.AbortWithStatus(http.StatusNoContent)
			return
		}
		c.Next()
	}
}
