package handlers

import (
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"github.com/jackc/pgx/v5/pgxpool"

	"github.com/breakpilot/ai-compliance-sdk/internal/dsms"
	"github.com/breakpilot/ai-compliance-sdk/internal/gap"
)

// GapHandler handles regulatory gap analysis endpoints.
type GapHandler struct {
	engine *gap.Engine
	store  *gap.Store
}

// NewGapHandler creates a new GapHandler.
func NewGapHandler(pool *pgxpool.Pool) *GapHandler {
	store := gap.NewStore(pool)
	return &GapHandler{
		engine: gap.NewEngine(store),
		store:  store,
	}
}

// CreateProject creates a new gap analysis project.
// POST /sdk/v1/gap/projects
func (h *GapHandler) CreateProject(c *gin.Context) {
	var profile gap.ProductProfile
	if err := c.ShouldBindJSON(&profile); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	tenantID := c.GetHeader("X-Tenant-ID")
	if tenantID != "" {
		profile.TenantID, _ = uuid.Parse(tenantID)
	}

	if err := h.store.CreateProfile(&profile); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to create project"})
		return
	}

	c.JSON(http.StatusCreated, gin.H{"project": profile})
}

// GetProject returns a gap project by ID.
// GET /sdk/v1/gap/projects/:id
func (h *GapHandler) GetProject(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project ID"})
		return
	}

	profile, err := h.store.GetProfile(id)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "project not found"})
		return
	}

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

// ListProjects lists gap projects for a tenant.
// GET /sdk/v1/gap/projects
func (h *GapHandler) ListProjects(c *gin.Context) {
	tenantID, err := uuid.Parse(c.GetHeader("X-Tenant-ID"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "X-Tenant-ID required"})
		return
	}

	profiles, err := h.store.ListProfiles(tenantID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list projects"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"projects": profiles, "total": len(profiles)})
}

// AnalyzeProject runs the full gap analysis.
// POST /sdk/v1/gap/projects/:id/analyze
func (h *GapHandler) AnalyzeProject(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project ID"})
		return
	}

	profile, err := h.store.GetProfile(id)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "project not found"})
		return
	}

	report, err := h.engine.Analyze(profile)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// Archive gap report to DSMS (non-blocking, best-effort)
	var dsmsCID string
	reportJSON, _ := json.Marshal(report)
	filename := fmt.Sprintf("gap-report-%s-%s.json", id.String()[:8], time.Now().Format("2006-01-02"))
	if result := dsms.Archive(reportJSON, filename, "gap_report", id.String(), "1"); result != nil {
		dsmsCID = result.CID
	}

	// Return report with DSMS CID appended
	response := gin.H{
		"profile_id":   report.ProfileID,
		"profile_name": report.ProfileName,
		"regulations":  report.Regulations,
		"summary":      report.Summary,
		"gaps":         report.Gaps,
		"created_at":   report.CreatedAt,
	}
	if dsmsCID != "" {
		response["dsms_cid"] = dsmsCID
	}
	c.JSON(http.StatusOK, response)
}

// QuickAnalyze runs gap analysis without saving a project.
// POST /sdk/v1/gap/analyze
func (h *GapHandler) QuickAnalyze(c *gin.Context) {
	var profile gap.ProductProfile
	if err := c.ShouldBindJSON(&profile); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	profile.ID = uuid.New()
	report, err := h.engine.Analyze(&profile)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, report)
}

// GetTemplates returns available industry templates.
// GET /sdk/v1/gap/templates
func (h *GapHandler) GetTemplates(c *gin.Context) {
	templates := make([]gin.H, 0, len(gap.IndustryTemplates))
	for key, tmpl := range gap.IndustryTemplates {
		templates = append(templates, gin.H{
			"key":          key,
			"name":         tmpl.Name,
			"description":  tmpl.Description,
			"product_type": tmpl.ProductType,
		})
	}
	c.JSON(http.StatusOK, gin.H{"templates": templates})
}

// GetTemplate returns a specific template by key.
// GET /sdk/v1/gap/templates/:key
func (h *GapHandler) GetTemplate(c *gin.Context) {
	key := c.Param("key")
	tmpl, ok := gap.IndustryTemplates[key]
	if !ok {
		c.JSON(http.StatusNotFound, gin.H{"error": "template not found"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"template": tmpl})
}

// GetRegulations returns all supported regulations with deadlines.
// GET /sdk/v1/gap/regulations
func (h *GapHandler) GetRegulations(c *gin.Context) {
	regs := make([]gin.H, 0, len(gap.RegulationNames))
	for id, name := range gap.RegulationNames {
		entry := gin.H{"id": id, "name": name}
		if dl, ok := gap.RegulationDeadlines[id]; ok {
			entry["deadline"] = dl
		}
		regs = append(regs, entry)
	}
	c.JSON(http.StatusOK, gin.H{"regulations": regs})
}
