package handlers

import (
	"net/http"

	"github.com/breakpilot/ai-compliance-sdk/internal/rbac"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

// RBACHandlers handles RBAC-related API endpoints
type RBACHandlers struct {
	store        *rbac.Store
	service      *rbac.Service
	policyEngine *rbac.PolicyEngine
}

// NewRBACHandlers creates new RBAC handlers
func NewRBACHandlers(store *rbac.Store, service *rbac.Service, policyEngine *rbac.PolicyEngine) *RBACHandlers {
	return &RBACHandlers{
		store:        store,
		service:      service,
		policyEngine: policyEngine,
	}
}

// ============================================================================
// Tenant Endpoints
// ============================================================================

// ListTenants returns all tenants
func (h *RBACHandlers) ListTenants(c *gin.Context) {
	tenants, err := h.store.ListTenants(c.Request.Context())
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"tenants": tenants})
}

// GetTenant returns a tenant by ID
func (h *RBACHandlers) GetTenant(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid tenant ID"})
		return
	}

	tenant, err := h.store.GetTenant(c.Request.Context(), id)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "tenant not found"})
		return
	}

	c.JSON(http.StatusOK, tenant)
}

// CreateTenant creates a new tenant
func (h *RBACHandlers) CreateTenant(c *gin.Context) {
	var tenant rbac.Tenant
	if err := c.ShouldBindJSON(&tenant); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	if err := h.store.CreateTenant(c.Request.Context(), &tenant); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, tenant)
}

// UpdateTenant updates a tenant
func (h *RBACHandlers) UpdateTenant(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid tenant ID"})
		return
	}

	var tenant rbac.Tenant
	if err := c.ShouldBindJSON(&tenant); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	tenant.ID = id
	if err := h.store.UpdateTenant(c.Request.Context(), &tenant); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, tenant)
}

// ============================================================================
// Namespace Endpoints
// ============================================================================

// ListNamespaces returns namespaces for a tenant
func (h *RBACHandlers) ListNamespaces(c *gin.Context) {
	tenantID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		tenantID = rbac.GetTenantID(c)
	}

	if tenantID == uuid.Nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "tenant ID required"})
		return
	}

	namespaces, err := h.store.ListNamespaces(c.Request.Context(), tenantID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"namespaces": namespaces})
}

// GetNamespace returns a namespace by ID
func (h *RBACHandlers) GetNamespace(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid namespace ID"})
		return
	}

	namespace, err := h.store.GetNamespace(c.Request.Context(), id)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "namespace not found"})
		return
	}

	c.JSON(http.StatusOK, namespace)
}

// CreateNamespace creates a new namespace
func (h *RBACHandlers) CreateNamespace(c *gin.Context) {
	tenantID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		tenantID = rbac.GetTenantID(c)
	}

	if tenantID == uuid.Nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "tenant ID required"})
		return
	}

	var namespace rbac.Namespace
	if err := c.ShouldBindJSON(&namespace); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	namespace.TenantID = tenantID
	if err := h.store.CreateNamespace(c.Request.Context(), &namespace); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, namespace)
}
