package handlers

import (
	"net/http"
	"time"

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

// AcknowledgeReport acknowledges a report (within 7-day HinSchG deadline)
// POST /sdk/v1/whistleblower/reports/:id/acknowledge
func (h *WhistleblowerHandlers) AcknowledgeReport(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid report ID"})
		return
	}

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

	if report.AcknowledgedAt != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "report already acknowledged"})
		return
	}

	userID := rbac.GetUserID(c)

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

	var req whistleblower.AcknowledgeRequest
	if err := c.ShouldBindJSON(&req); err == nil && req.Message != "" {
		msg := &whistleblower.AnonymousMessage{
			ReportID:  id,
			Direction: whistleblower.MessageDirectionAdminToReporter,
			Content:   req.Message,
		}
		h.store.AddMessage(c.Request.Context(), msg)
	}

	isOverdue := time.Now().UTC().After(report.DeadlineAcknowledgment)

	c.JSON(http.StatusOK, gin.H{
		"message":    "report acknowledged",
		"is_overdue": isOverdue,
	})
}

// StartInvestigation changes the report status to investigation
// POST /sdk/v1/whistleblower/reports/:id/investigate
func (h *WhistleblowerHandlers) StartInvestigation(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid report ID"})
		return
	}

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

	userID := rbac.GetUserID(c)

	report.Status = whistleblower.ReportStatusInvestigation
	report.AuditTrail = append(report.AuditTrail, whistleblower.AuditEntry{
		Timestamp: time.Now().UTC(),
		Action:    "investigation_started",
		UserID:    userID.String(),
		Details:   "Investigation started",
	})

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

	c.JSON(http.StatusOK, gin.H{
		"message": "investigation started",
		"report":  report,
	})
}

// AddMeasure adds a corrective measure to a report
// POST /sdk/v1/whistleblower/reports/:id/measures
func (h *WhistleblowerHandlers) AddMeasure(c *gin.Context) {
	reportID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid report ID"})
		return
	}

	report, err := h.store.GetReport(c.Request.Context(), reportID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	if report == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "report not found"})
		return
	}

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

	userID := rbac.GetUserID(c)

	measure := &whistleblower.Measure{
		ReportID:    reportID,
		Title:       req.Title,
		Description: req.Description,
		Responsible: req.Responsible,
		DueDate:     req.DueDate,
	}

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

	if report.Status != whistleblower.ReportStatusMeasuresTaken &&
		report.Status != whistleblower.ReportStatusClosed {
		report.Status = whistleblower.ReportStatusMeasuresTaken
		report.AuditTrail = append(report.AuditTrail, whistleblower.AuditEntry{
			Timestamp: time.Now().UTC(),
			Action:    "measure_added",
			UserID:    userID.String(),
			Details:   "Corrective measure added: " + req.Title,
		})
		h.store.UpdateReport(c.Request.Context(), report)
	}

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

// CloseReport closes a report with a resolution
// POST /sdk/v1/whistleblower/reports/:id/close
func (h *WhistleblowerHandlers) CloseReport(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid report ID"})
		return
	}

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

	userID := rbac.GetUserID(c)

	if err := h.store.CloseReport(c.Request.Context(), id, userID, req.Resolution); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "report closed"})
}

// SendAdminMessage sends a message from admin to reporter
// POST /sdk/v1/whistleblower/reports/:id/messages
func (h *WhistleblowerHandlers) SendAdminMessage(c *gin.Context) {
	reportID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid report ID"})
		return
	}

	report, err := h.store.GetReport(c.Request.Context(), reportID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	if report == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "report not found"})
		return
	}

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

	msg := &whistleblower.AnonymousMessage{
		ReportID:  reportID,
		Direction: whistleblower.MessageDirectionAdminToReporter,
		Content:   req.Content,
	}

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

	c.JSON(http.StatusCreated, gin.H{"message": msg})
}

// ListMessages lists messages for a report
// GET /sdk/v1/whistleblower/reports/:id/messages
func (h *WhistleblowerHandlers) ListMessages(c *gin.Context) {
	reportID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid report ID"})
		return
	}

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

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

// GetStatistics returns whistleblower statistics for the tenant
// GET /sdk/v1/whistleblower/statistics
func (h *WhistleblowerHandlers) GetStatistics(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)

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

	c.JSON(http.StatusOK, stats)
}
