package web

import (
	"encoding/json"
	"errors"
	"net/http"
	"strings"

	"ymhut-box/server/unified-management/internal/db"
)

func (r *router) handleAdminSources(w http.ResponseWriter, req *http.Request) {
	path := cleanPath(req.URL.Path)
	switch {
	case req.Method == http.MethodGet && path == "/api/admin/sources":
		catalog, err := r.sources.Catalog(true)
		if err != nil {
			writeError(w, http.StatusInternalServerError, "SOURCES_FAILED", err)
			return
		}
		writeJSON(w, http.StatusOK, map[string]any{"ok": true, "catalog": catalog})
	case req.Method == http.MethodPost && path == "/api/admin/sources/import-media-types":
		if err := r.sources.ImportLegacyMediaTypes(req.Context()); err != nil {
			writeError(w, http.StatusInternalServerError, "IMPORT_FAILED", err)
			return
		}
		writeJSON(w, http.StatusOK, map[string]any{"ok": true})
	case req.Method == http.MethodPost && path == "/api/admin/sources/check":
		job := r.sources.QueueCheckAll()
		writeJSON(w, http.StatusOK, map[string]any{"ok": true, "queued": true, "jobId": job.ID, "job": job})
	case req.Method == http.MethodGet && path == "/api/admin/sources/check/status":
		writeJSON(w, http.StatusOK, map[string]any{"ok": true, "items": r.sources.CheckJobs()})
	case req.Method == http.MethodGet && strings.HasPrefix(path, "/api/admin/sources/check/status/"):
		jobID := strings.TrimPrefix(path, "/api/admin/sources/check/status/")
		if job, ok := r.sources.CheckJob(jobID); ok {
			writeJSON(w, http.StatusOK, map[string]any{"ok": true, "job": job})
			return
		}
		writeError(w, http.StatusNotFound, "CHECK_JOB_NOT_FOUND", errors.New("check job not found"))
	case req.Method == http.MethodPost && strings.HasPrefix(path, "/api/admin/sources/") && strings.HasSuffix(path, "/check"):
		sourceID := strings.TrimSuffix(strings.TrimPrefix(path, "/api/admin/sources/"), "/check")
		item, err := r.sources.CheckSourceID(req.Context(), sourceID)
		if err != nil {
			writeError(w, http.StatusBadRequest, "CHECK_FAILED", err)
			return
		}
		writeJSON(w, http.StatusOK, map[string]any{"ok": true, "source": item})
	case (req.Method == http.MethodPost || req.Method == http.MethodPut) && path == "/api/admin/sources":
		var item db.Source
		if err := json.NewDecoder(req.Body).Decode(&item); err != nil {
			writeError(w, http.StatusBadRequest, "INVALID_PAYLOAD", err)
			return
		}
		saved, err := r.store.UpsertSource(item)
		if err != nil {
			writeError(w, http.StatusInternalServerError, "SOURCE_SAVE_FAILED", err)
			return
		}
		_ = r.sources.PublishLegacyMediaTypes(req.Context(), "admin")
		_ = r.releases.PublishLegacyUpdateInfo(req, "admin")
		_ = r.store.InsertAudit(db.AuditLog{Actor: "admin", Type: "source.saved", Target: saved.SourceID, Message: "客户端接口已保存并同步兼容 media-types.json", IP: req.RemoteAddr, UserAgent: req.UserAgent()})
		writeJSON(w, http.StatusOK, map[string]any{"ok": true, "source": saved})
	case req.Method == http.MethodDelete && strings.HasPrefix(path, "/api/admin/sources/"):
		sourceID := strings.TrimPrefix(path, "/api/admin/sources/")
		if err := r.sources.DeleteSourceAndPublishCompatibility(req.Context(), sourceID, "admin"); err != nil {
			writeError(w, http.StatusInternalServerError, "SOURCE_DELETE_FAILED", err)
			return
		}
		_ = r.releases.PublishLegacyUpdateInfo(req, "admin")
		writeJSON(w, http.StatusOK, map[string]any{"ok": true})
	default:
		http.NotFound(w, req)
	}
}
