package handlers

import (
	"net/http"
	"strconv"
	"time"

	"github.com/breakpilot/consent-service/internal/middleware"
	"github.com/breakpilot/consent-service/internal/models"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

// ========================================
// ADMIN ENDPOINTS — CRUD & Workflow
// ========================================

// AdminListDSR returns all DSRs with filters (admin only)
func (h *DSRHandler) AdminListDSR(c *gin.Context) {
	if !middleware.IsAdmin(c) && !middleware.IsDSB(c) {
		c.JSON(http.StatusForbidden, gin.H{"error": "Admin or DSB access required"})
		return
	}

	// Parse pagination
	limit := 20
	offset := 0
	if l := c.Query("limit"); l != "" {
		if parsed, err := strconv.Atoi(l); err == nil && parsed > 0 {
			limit = parsed
		}
	}
	if o := c.Query("offset"); o != "" {
		if parsed, err := strconv.Atoi(o); err == nil && parsed >= 0 {
			offset = parsed
		}
	}

	// Parse filters
	filters := models.DSRListFilters{}
	if status := c.Query("status"); status != "" {
		filters.Status = &status
	}
	if reqType := c.Query("request_type"); reqType != "" {
		filters.RequestType = &reqType
	}
	if assignedTo := c.Query("assigned_to"); assignedTo != "" {
		filters.AssignedTo = &assignedTo
	}
	if priority := c.Query("priority"); priority != "" {
		filters.Priority = &priority
	}
	if c.Query("overdue_only") == "true" {
		filters.OverdueOnly = true
	}
	if search := c.Query("search"); search != "" {
		filters.Search = &search
	}
	if from := c.Query("from_date"); from != "" {
		if t, err := time.Parse("2006-01-02", from); err == nil {
			filters.FromDate = &t
		}
	}
	if to := c.Query("to_date"); to != "" {
		if t, err := time.Parse("2006-01-02", to); err == nil {
			filters.ToDate = &t
		}
	}

	dsrs, total, err := h.dsrService.List(c.Request.Context(), filters, limit, offset)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch requests"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"requests": dsrs,
		"total":    total,
		"limit":    limit,
		"offset":   offset,
	})
}

// AdminGetDSR returns a specific DSR (admin only)
func (h *DSRHandler) AdminGetDSR(c *gin.Context) {
	if !middleware.IsAdmin(c) && !middleware.IsDSB(c) {
		c.JSON(http.StatusForbidden, gin.H{"error": "Admin or DSB access required"})
		return
	}

	dsrID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request ID"})
		return
	}

	dsr, err := h.dsrService.GetByID(c.Request.Context(), dsrID)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Request not found"})
		return
	}

	c.JSON(http.StatusOK, dsr)
}

// AdminCreateDSR creates a DSR manually (admin only)
func (h *DSRHandler) AdminCreateDSR(c *gin.Context) {
	if !middleware.IsAdmin(c) && !middleware.IsDSB(c) {
		c.JSON(http.StatusForbidden, gin.H{"error": "Admin or DSB access required"})
		return
	}

	userID, _ := middleware.GetUserID(c)

	var req models.CreateDSRRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body", "details": err.Error()})
		return
	}

	// Set source as admin_panel
	if req.Source == "" {
		req.Source = "admin_panel"
	}

	dsr, err := h.dsrService.CreateRequest(c.Request.Context(), req, &userID)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, gin.H{
		"message":        "Anfrage wurde erstellt",
		"request_number": dsr.RequestNumber,
		"dsr":            dsr,
	})
}

// AdminUpdateDSR updates a DSR (admin only)
func (h *DSRHandler) AdminUpdateDSR(c *gin.Context) {
	if !middleware.IsAdmin(c) && !middleware.IsDSB(c) {
		c.JSON(http.StatusForbidden, gin.H{"error": "Admin or DSB access required"})
		return
	}

	dsrID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request ID"})
		return
	}

	userID, _ := middleware.GetUserID(c)

	var req models.UpdateDSRRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
		return
	}

	ctx := c.Request.Context()

	// Update status if provided
	if req.Status != nil {
		err = h.dsrService.UpdateStatus(ctx, dsrID, models.DSRStatus(*req.Status), "", &userID)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}
	}

	// Update processing notes
	if req.ProcessingNotes != nil {
		h.dsrService.GetPool().Exec(ctx, `
			UPDATE data_subject_requests SET processing_notes = $1, updated_at = NOW() WHERE id = $2
		`, *req.ProcessingNotes, dsrID)
	}

	// Update priority
	if req.Priority != nil {
		h.dsrService.GetPool().Exec(ctx, `
			UPDATE data_subject_requests SET priority = $1, updated_at = NOW() WHERE id = $2
		`, *req.Priority, dsrID)
	}

	// Get updated DSR
	dsr, _ := h.dsrService.GetByID(ctx, dsrID)

	c.JSON(http.StatusOK, gin.H{
		"message": "Anfrage wurde aktualisiert",
		"dsr":     dsr,
	})
}

// AdminGetDSRStats returns dashboard statistics
func (h *DSRHandler) AdminGetDSRStats(c *gin.Context) {
	if !middleware.IsAdmin(c) && !middleware.IsDSB(c) {
		c.JSON(http.StatusForbidden, gin.H{"error": "Admin or DSB access required"})
		return
	}

	stats, err := h.dsrService.GetDashboardStats(c.Request.Context())
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch statistics"})
		return
	}

	c.JSON(http.StatusOK, stats)
}

// AdminVerifyIdentity verifies the identity of a requester
func (h *DSRHandler) AdminVerifyIdentity(c *gin.Context) {
	if !middleware.IsAdmin(c) && !middleware.IsDSB(c) {
		c.JSON(http.StatusForbidden, gin.H{"error": "Admin or DSB access required"})
		return
	}

	dsrID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request ID"})
		return
	}

	userID, _ := middleware.GetUserID(c)

	var req models.VerifyDSRIdentityRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
		return
	}

	err = h.dsrService.VerifyIdentity(c.Request.Context(), dsrID, req.Method, userID)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Identität wurde verifiziert"})
}

// AdminAssignDSR assigns a DSR to a user
func (h *DSRHandler) AdminAssignDSR(c *gin.Context) {
	if !middleware.IsAdmin(c) && !middleware.IsDSB(c) {
		c.JSON(http.StatusForbidden, gin.H{"error": "Admin or DSB access required"})
		return
	}

	dsrID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request ID"})
		return
	}

	userID, _ := middleware.GetUserID(c)

	var req struct {
		AssigneeID string `json:"assignee_id" binding:"required"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
		return
	}

	assigneeID, err := uuid.Parse(req.AssigneeID)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid assignee ID"})
		return
	}

	err = h.dsrService.AssignRequest(c.Request.Context(), dsrID, assigneeID, userID)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Anfrage wurde zugewiesen"})
}

// AdminExtendDSRDeadline extends the deadline for a DSR
func (h *DSRHandler) AdminExtendDSRDeadline(c *gin.Context) {
	if !middleware.IsAdmin(c) && !middleware.IsDSB(c) {
		c.JSON(http.StatusForbidden, gin.H{"error": "Admin or DSB access required"})
		return
	}

	dsrID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request ID"})
		return
	}

	userID, _ := middleware.GetUserID(c)

	var req models.ExtendDSRDeadlineRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
		return
	}

	err = h.dsrService.ExtendDeadline(c.Request.Context(), dsrID, req.Reason, req.Days, userID)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Frist wurde verlängert"})
}

// AdminCompleteDSR marks a DSR as completed
func (h *DSRHandler) AdminCompleteDSR(c *gin.Context) {
	if !middleware.IsAdmin(c) && !middleware.IsDSB(c) {
		c.JSON(http.StatusForbidden, gin.H{"error": "Admin or DSB access required"})
		return
	}

	dsrID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request ID"})
		return
	}

	userID, _ := middleware.GetUserID(c)

	var req models.CompleteDSRRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
		return
	}

	err = h.dsrService.CompleteRequest(c.Request.Context(), dsrID, req.ResultSummary, req.ResultData, userID)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Anfrage wurde abgeschlossen"})
}

// AdminRejectDSR rejects a DSR
func (h *DSRHandler) AdminRejectDSR(c *gin.Context) {
	if !middleware.IsAdmin(c) && !middleware.IsDSB(c) {
		c.JSON(http.StatusForbidden, gin.H{"error": "Admin or DSB access required"})
		return
	}

	dsrID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request ID"})
		return
	}

	userID, _ := middleware.GetUserID(c)

	var req models.RejectDSRRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
		return
	}

	err = h.dsrService.RejectRequest(c.Request.Context(), dsrID, req.Reason, req.LegalBasis, userID)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Anfrage wurde abgelehnt"})
}

// AdminGetDSRHistory returns the status history for a DSR
func (h *DSRHandler) AdminGetDSRHistory(c *gin.Context) {
	if !middleware.IsAdmin(c) && !middleware.IsDSB(c) {
		c.JSON(http.StatusForbidden, gin.H{"error": "Admin or DSB access required"})
		return
	}

	dsrID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request ID"})
		return
	}

	history, err := h.dsrService.GetStatusHistory(c.Request.Context(), dsrID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch history"})
		return
	}

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