package handlers import ( "bookhoard/internal/database" "net/http" "time" "github.com/google/uuid" "github.com/jackc/pgx/v5/pgtype" "github.com/labstack/echo/v5" ) type ProcessingIssuesHandler struct { db *database.Queries } func NewProcessingIssuesHandler(db *database.Queries) *ProcessingIssuesHandler { return &ProcessingIssuesHandler{db: db} } type ProcessingIssueResponse struct { ID string `json:"id"` MediaItemID string `json:"media_item_id"` Title string `json:"title"` FilePath string `json:"file_path"` FormatGroup string `json:"format_group"` LibraryTypeName string `json:"library_type_name"` IssueType string `json:"issue_type"` IssueDescription string `json:"issue_description"` Severity string `json:"severity"` CreatedAt time.Time `json:"created_at"` } type ProcessingIssueStats struct { ErrorCount int64 `json:"error_count"` WarningCount int64 `json:"warning_count"` InfoCount int64 `json:"info_count"` } // ListProcessingIssues returns all processing issues for a library func (h *ProcessingIssuesHandler) ListProcessingIssues(c *echo.Context) error { libraryID, err := uuid.Parse(c.Param("libraryId")) if err != nil { return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid library ID"}) } issues, err := h.db.ListProcessingIssuesByLibrary( c.Request().Context(), pgtype.UUID{Bytes: libraryID, Valid: true}, ) if err != nil { return c.JSON(http.StatusInternalServerError, map[string]string{"error": "Failed to fetch issues"}) } response := make([]ProcessingIssueResponse, len(issues)) for i, issue := range issues { response[i] = ProcessingIssueResponse{ ID: issue.ID.String(), MediaItemID: issue.MediaItemID.String(), Title: issue.Title, FilePath: issue.FilePath, FormatGroup: issue.FormatGroup, LibraryTypeName: issue.LibraryTypeName, IssueType: issue.IssueType, IssueDescription: issue.IssueDescription, Severity: issue.Severity, CreatedAt: issue.CreatedAt.Time, } } return c.JSON(http.StatusOK, response) } // GetProcessingIssueStats returns statistics about processing issues func (h *ProcessingIssuesHandler) GetProcessingIssueStats(c *echo.Context) error { libraryID, err := uuid.Parse(c.Param("libraryId")) if err != nil { return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid library ID"}) } stats, err := h.db.GetProcessingIssueStats( c.Request().Context(), pgtype.UUID{Bytes: libraryID, Valid: true}, ) if err != nil { return c.JSON(http.StatusInternalServerError, map[string]string{"error": "Failed to fetch stats"}) } return c.JSON(http.StatusOK, ProcessingIssueStats{ ErrorCount: stats.ErrorCount, WarningCount: stats.WarningCount, InfoCount: stats.InfoCount, }) } // ResolveProcessingIssue marks an issue as resolved func (h *ProcessingIssuesHandler) ResolveProcessingIssue(c *echo.Context) error { issueID, err := uuid.Parse(c.Param("issueId")) if err != nil { return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid issue ID"}) } mediaItemID, err := uuid.Parse(c.Param("mediaItemId")) if err != nil { return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid media item ID"}) } _, err = h.db.ResolveProcessingIssue( c.Request().Context(), database.ResolveProcessingIssueParams{ ID: pgtype.UUID{Bytes: issueID, Valid: true}, MediaItemID: pgtype.UUID{Bytes: mediaItemID, Valid: true}, }, ) if err != nil { return c.JSON(http.StatusInternalServerError, map[string]string{"error": "Failed to resolve issue"}) } return c.JSON(http.StatusOK, map[string]interface{}{ "success": true, "message": "Issue marked as resolved", }) } // DeleteProcessingIssue permanently deletes an issue record func (h *ProcessingIssuesHandler) DeleteProcessingIssue(c *echo.Context) error { issueID, err := uuid.Parse(c.Param("issueId")) if err != nil { return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid issue ID"}) } _, err = h.db.DeleteProcessingIssue(c.Request().Context(), pgtype.UUID{Bytes: issueID, Valid: true}) if err != nil { return c.JSON(http.StatusInternalServerError, map[string]string{"error": "Failed to delete issue"}) } return c.JSON(http.StatusOK, map[string]any{ "success": true, "message": "Issue deleted", }) }