package controller import ( "butterfliu/internal/service" "encoding/json" "log" "net/http" "strconv" "sync" "github.com/go-chi/chi/v5" ) type LibraryController struct { service *service.LibraryService scanMutex sync.Mutex isScanning bool } func NewLibraryController(service *service.LibraryService) *LibraryController { return &LibraryController{service: service} } func (c *LibraryController) GetAll(w http.ResponseWriter, r *http.Request) { libraries, err := c.service.GetAll() if err != nil { jsonError(w, err.Error(), http.StatusInternalServerError) return } jsonResponse(w, libraries, http.StatusOK) } func (c *LibraryController) Create(w http.ResponseWriter, r *http.Request) { var req struct { Name string `json:"name"` Path string `json:"path"` } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { jsonError(w, err.Error(), http.StatusBadRequest) return } if req.Name == "" || req.Path == "" { jsonError(w, "name and path are required", http.StatusBadRequest) return } _, err := c.service.Create(req.Name, req.Path) if err != nil { jsonError(w, err.Error(), http.StatusInternalServerError) return } jsonMsg(w, "Add library successfully.") } func (c *LibraryController) GetByID(w http.ResponseWriter, r *http.Request) { idParam := chi.URLParam(r, "id") id, err := strconv.Atoi(idParam) if err != nil { jsonError(w, err.Error(), http.StatusBadRequest) return } l, err := c.service.GetByID(id) if err != nil { jsonError(w, err.Error(), http.StatusInternalServerError) return } jsonResponse(w, l, http.StatusOK) } func (c *LibraryController) UpdateName(w http.ResponseWriter, r *http.Request) { idParam := chi.URLParam(r, "id") id, err := strconv.Atoi(idParam) if err != nil { jsonError(w, err.Error(), http.StatusBadRequest) return } var name string if err := json.NewDecoder(r.Body).Decode(&name); err != nil { jsonError(w, err.Error(), http.StatusBadRequest) return } err = c.service.UpdateName(id, name) if err != nil { jsonError(w, err.Error(), http.StatusInternalServerError) return } jsonMsg(w, "Updated library name.") } func (c *LibraryController) UpdatePath(w http.ResponseWriter, r *http.Request) { idParam := chi.URLParam(r, "id") id, err := strconv.Atoi(idParam) if err != nil { jsonError(w, err.Error(), http.StatusBadRequest) return } var path string if err := json.NewDecoder(r.Body).Decode(&path); err != nil { jsonError(w, err.Error(), http.StatusBadRequest) return } err = c.service.UpdatePath(id, path) if err != nil { jsonError(w, err.Error(), http.StatusInternalServerError) return } jsonMsg(w, "Updated library path.") } func (c *LibraryController) Scan(w http.ResponseWriter, r *http.Request) { c.scanMutex.Lock() if c.isScanning { c.scanMutex.Unlock() jsonError(w, "Another scan is already in progress", http.StatusConflict) return } c.isScanning = true c.scanMutex.Unlock() idParam := chi.URLParam(r, "id") id, err := strconv.Atoi(idParam) if err != nil { c.scanMutex.Lock() c.isScanning = false c.scanMutex.Unlock() jsonError(w, err.Error(), http.StatusBadRequest) return } go func() { defer func() { c.scanMutex.Lock() c.isScanning = false c.scanMutex.Unlock() }() report, err := c.service.Scan(id) if err != nil { log.Printf("Scan failed for library %d: %v", id, err) return } log.Printf("Scan completed for library %d: %+v", id, report) }() jsonMsg(w, "Library scan started.") } func (c *LibraryController) GetScanStatus(w http.ResponseWriter, r *http.Request) { c.scanMutex.Lock() scanning := c.isScanning c.scanMutex.Unlock() jsonResponse(w, map[string]bool{"scanning": scanning}, http.StatusOK) } func (c *LibraryController) Delete(w http.ResponseWriter, r *http.Request) { idParam := chi.URLParam(r, "id") id, err := strconv.Atoi(idParam) if err != nil { jsonError(w, err.Error(), http.StatusBadRequest) return } err = c.service.Delete(id) if err != nil { jsonError(w, err.Error(), http.StatusInternalServerError) return } jsonMsg(w, "Deleted library.") } func (c *LibraryController) GetSongs(w http.ResponseWriter, r *http.Request) { idParam := chi.URLParam(r, "id") id, err := strconv.Atoi(idParam) if err != nil { jsonError(w, err.Error(), http.StatusBadRequest) return } songs, err := c.service.GetSongs(id) if err != nil { jsonError(w, err.Error(), http.StatusInternalServerError) return } jsonResponse(w, songs, http.StatusOK) } func (c *LibraryController) GetArtists(w http.ResponseWriter, r *http.Request) { artists, err := c.service.GetArtists() if err != nil { jsonError(w, err.Error(), http.StatusInternalServerError) return } jsonResponse(w, artists, http.StatusOK) } func (c *LibraryController) GetAlbums(w http.ResponseWriter, r *http.Request) { albums, err := c.service.GetAlbums() if err != nil { jsonError(w, err.Error(), http.StatusInternalServerError) return } jsonResponse(w, albums, http.StatusOK) }