package responses import ( "fmt" "time" "github.com/shopspring/decimal" "github.com/treytartt/honeydue-api/internal/models" ) // DocumentUserResponse represents a user in document context type DocumentUserResponse struct { ID uint `json:"id"` Username string `json:"username"` FirstName string `json:"first_name"` LastName string `json:"last_name"` } // DocumentImageResponse represents an image in a document type DocumentImageResponse struct { ID uint `json:"id"` ImageURL string `json:"image_url"` MediaURL string `json:"media_url"` // Authenticated endpoint: /api/media/document-image/{id} Caption string `json:"caption"` Error string `json:"error,omitempty"` // Non-empty when the image could not be resolved } // DocumentResponse represents a document in the API response type DocumentResponse struct { ID uint `json:"id"` ResidenceID uint `json:"residence_id"` Residence uint `json:"residence"` // Alias for residence_id (KMM compatibility) CreatedByID uint `json:"created_by_id"` CreatedBy *DocumentUserResponse `json:"created_by,omitempty"` Title string `json:"title"` Description string `json:"description"` DocumentType models.DocumentType `json:"document_type"` MediaURL string `json:"media_url"` // Authenticated endpoint: /api/media/document/{id} FileName string `json:"file_name"` FileSize *int64 `json:"file_size"` MimeType string `json:"mime_type"` PurchaseDate *time.Time `json:"purchase_date"` ExpiryDate *time.Time `json:"expiry_date"` PurchasePrice *decimal.Decimal `json:"purchase_price"` Vendor string `json:"vendor"` SerialNumber string `json:"serial_number"` ModelNumber string `json:"model_number"` TaskID *uint `json:"task_id"` IsActive bool `json:"is_active"` Images []DocumentImageResponse `json:"images"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // Note: Pagination removed - list endpoints now return arrays directly // === Factory Functions === // NewDocumentUserResponse creates a DocumentUserResponse from a User model func NewDocumentUserResponse(u *models.User) *DocumentUserResponse { if u == nil { return nil } return &DocumentUserResponse{ ID: u.ID, Username: u.Username, FirstName: u.FirstName, LastName: u.LastName, } } // NewDocumentResponse creates a DocumentResponse from a Document model func NewDocumentResponse(d *models.Document) DocumentResponse { resp := DocumentResponse{ ID: d.ID, ResidenceID: d.ResidenceID, Residence: d.ResidenceID, // Alias for KMM compatibility CreatedByID: d.CreatedByID, Title: d.Title, Description: d.Description, DocumentType: d.DocumentType, MediaURL: fmt.Sprintf("/api/media/document/%d", d.ID), // Authenticated endpoint FileName: d.FileName, FileSize: d.FileSize, MimeType: d.MimeType, PurchaseDate: d.PurchaseDate, ExpiryDate: d.ExpiryDate, PurchasePrice: d.PurchasePrice, Vendor: d.Vendor, SerialNumber: d.SerialNumber, ModelNumber: d.ModelNumber, TaskID: d.TaskID, IsActive: d.IsActive, Images: make([]DocumentImageResponse, 0), CreatedAt: d.CreatedAt, UpdatedAt: d.UpdatedAt, } if d.CreatedBy.ID != 0 { resp.CreatedBy = NewDocumentUserResponse(&d.CreatedBy) } // Convert images with authenticated media URLs for _, img := range d.Images { imgResp := DocumentImageResponse{ ID: img.ID, ImageURL: img.ImageURL, MediaURL: fmt.Sprintf("/api/media/document-image/%d", img.ID), // Authenticated endpoint Caption: img.Caption, } if img.ImageURL == "" { imgResp.Error = "image source URL is missing" } resp.Images = append(resp.Images, imgResp) } return resp } // NewDocumentListResponse creates a list of document responses func NewDocumentListResponse(documents []models.Document) []DocumentResponse { results := make([]DocumentResponse, len(documents)) for i, d := range documents { results[i] = NewDocumentResponse(&d) } return results }