2025-11-23 22:49:46 +07:00

248 lines
7.0 KiB
Go

// internal/controllers/claim_controller.go
package controllers
import (
"lost-and-found/internal/models"
"lost-and-found/internal/services"
"lost-and-found/internal/utils"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type ClaimController struct {
claimService *services.ClaimService
verificationService *services.VerificationService
}
func NewClaimController(db *gorm.DB) *ClaimController {
return &ClaimController{
claimService: services.NewClaimService(db),
verificationService: services.NewVerificationService(db),
}
}
// GetAllClaims gets all claims
// GET /api/claims
func (c *ClaimController) GetAllClaims(ctx *gin.Context) {
page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10"))
status := ctx.Query("status")
var itemID, userID *uint
if itemIDStr := ctx.Query("item_id"); itemIDStr != "" {
id, _ := strconv.ParseUint(itemIDStr, 10, 32)
itemID = new(uint)
*itemID = uint(id)
}
// If regular user, only show their claims
if userObj, exists := ctx.Get("user"); exists {
user := userObj.(*models.User)
if user.IsUser() {
userID = &user.ID
}
}
claims, total, err := c.claimService.GetAllClaims(page, limit, status, itemID, userID)
if err != nil {
utils.ErrorResponse(ctx, http.StatusInternalServerError, "Failed to get claims", err.Error())
return
}
utils.SendPaginatedResponse(ctx, http.StatusOK, "Claims retrieved", claims, total, page, limit)
}
// GetClaimByID gets claim by ID
// GET /api/claims/:id
func (c *ClaimController) GetClaimByID(ctx *gin.Context) {
id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
if err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid claim ID", err.Error())
return
}
isManager := false
if userObj, exists := ctx.Get("user"); exists {
user := userObj.(*models.User)
isManager = user.IsManager() || user.IsAdmin()
}
claim, err := c.claimService.GetClaimByID(uint(id), isManager)
if err != nil {
utils.ErrorResponse(ctx, http.StatusNotFound, "Claim not found", err.Error())
return
}
utils.SuccessResponse(ctx, http.StatusOK, "Claim retrieved", claim)
}
// CreateClaim creates a new claim
// POST /api/claims
func (c *ClaimController) CreateClaim(ctx *gin.Context) {
userObj, _ := ctx.Get("user")
user := userObj.(*models.User)
var req services.CreateClaimRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid request data", err.Error())
return
}
ipAddress := ctx.ClientIP()
userAgent := ctx.Request.UserAgent()
claim, err := c.claimService.CreateClaim(user.ID, req, ipAddress, userAgent)
if err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Failed to create claim", err.Error())
return
}
utils.SuccessResponse(ctx, http.StatusCreated, "Claim created", claim.ToResponse())
}
// VerifyClaim verifies a claim (manager only)
// POST /api/claims/:id/verify
func (c *ClaimController) VerifyClaim(ctx *gin.Context) {
managerObj, _ := ctx.Get("user")
manager := managerObj.(*models.User)
claimID, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
if err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid claim ID", err.Error())
return
}
var req services.VerifyClaimRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid request data", err.Error())
return
}
// Auto-verify description similarity
verification, err := c.verificationService.VerifyClaimDescription(uint(claimID))
if err != nil {
utils.ErrorResponse(ctx, http.StatusInternalServerError, "Verification failed", err.Error())
return
}
ipAddress := ctx.ClientIP()
userAgent := ctx.Request.UserAgent()
// Verify the claim
if err := c.claimService.VerifyClaim(
manager.ID,
uint(claimID),
req,
verification.SimilarityScore,
stringSliceToString(verification.MatchedKeywords),
ipAddress,
userAgent,
); err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Failed to verify claim", err.Error())
return
}
utils.SuccessResponse(ctx, http.StatusOK, "Claim verified", gin.H{
"verification": verification,
})
}
// GetClaimVerification gets verification data for a claim
// GET /api/claims/:id/verification
func (c *ClaimController) GetClaimVerification(ctx *gin.Context) {
claimID, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
if err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid claim ID", err.Error())
return
}
verification, err := c.verificationService.VerifyClaimDescription(uint(claimID))
if err != nil {
utils.ErrorResponse(ctx, http.StatusInternalServerError, "Verification failed", err.Error())
return
}
utils.SuccessResponse(ctx, http.StatusOK, "Verification retrieved", verification)
}
// CloseClaim closes a claim (manager only)
// POST /api/claims/:id/close
func (c *ClaimController) CloseClaim(ctx *gin.Context) {
managerObj, _ := ctx.Get("user")
manager := managerObj.(*models.User)
claimID, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
if err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid claim ID", err.Error())
return
}
ipAddress := ctx.ClientIP()
userAgent := ctx.Request.UserAgent()
if err := c.claimService.CloseClaim(manager.ID, uint(claimID), ipAddress, userAgent); err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Failed to close claim", err.Error())
return
}
utils.SuccessResponse(ctx, http.StatusOK, "Claim closed and archived", nil)
}
// DeleteClaim deletes a claim
// DELETE /api/claims/:id
func (c *ClaimController) DeleteClaim(ctx *gin.Context) {
userObj, _ := ctx.Get("user")
user := userObj.(*models.User)
claimID, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
if err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid claim ID", err.Error())
return
}
ipAddress := ctx.ClientIP()
userAgent := ctx.Request.UserAgent()
if err := c.claimService.DeleteClaim(user.ID, uint(claimID), ipAddress, userAgent); err != nil {
utils.ErrorResponse(ctx, http.StatusBadRequest, "Failed to delete claim", err.Error())
return
}
utils.SuccessResponse(ctx, http.StatusOK, "Claim deleted", nil)
}
// GetClaimsByUser gets claims by user
// GET /api/user/claims
func (c *ClaimController) GetClaimsByUser(ctx *gin.Context) {
userObj, _ := ctx.Get("user")
user := userObj.(*models.User)
page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10"))
claims, total, err := c.claimService.GetClaimsByUser(user.ID, page, limit)
if err != nil {
utils.ErrorResponse(ctx, http.StatusInternalServerError, "Failed to get claims", err.Error())
return
}
utils.SendPaginatedResponse(ctx, http.StatusOK, "Claims retrieved", claims, total, page, limit)
}
// Helper function to convert string slice to string
func stringSliceToString(slice []string) string {
if len(slice) == 0 {
return ""
}
result := ""
for i, s := range slice {
if i > 0 {
result += ", "
}
result += s
}
return result
}