package web

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

	"ymhut-box/server/unified-management/internal/notices"
	"ymhut-box/server/unified-management/internal/releases"
)

func (r *router) handleAdminReleases(w http.ResponseWriter, req *http.Request) {
	path := cleanPath(req.URL.Path)
	if strings.HasPrefix(path, "/api/admin/releases/notices") {
		r.handleAdminReleaseNotices(w, req)
		return
	}
	switch path {
	case "/api/admin/releases/packages":
		if req.Method != http.MethodPost {
			writeError(w, http.StatusMethodNotAllowed, "METHOD_NOT_ALLOWED", errors.New("POST required"))
			return
		}
		if err := req.ParseMultipartForm(256 << 20); err != nil {
			writeError(w, http.StatusBadRequest, "INVALID_UPLOAD", err)
			return
		}
		file, header, err := req.FormFile("file")
		if err != nil {
			writeError(w, http.StatusBadRequest, "FILE_REQUIRED", err)
			return
		}
		defer file.Close()
		pkg, err := r.releases.SaveUploadedPackage(req, file, releases.UploadOptions{
			FileName:       firstNonEmpty(req.FormValue("fileName"), header.Filename),
			Version:        req.FormValue("version"),
			Platform:       req.FormValue("platform"),
			Arch:           req.FormValue("arch"),
			Channel:        req.FormValue("channel"),
			Notes:          req.FormValue("notes"),
			UpdateManifest: req.FormValue("updateManifest") == "true" || req.FormValue("updateManifest") == "1",
		}, "admin")
		if err != nil {
			writeError(w, http.StatusBadRequest, "PACKAGE_UPLOAD_FAILED", err)
			return
		}
		writeJSON(w, http.StatusOK, map[string]any{"ok": true, "package": pkg})
	case "/api/admin/releases":
		writeJSON(w, http.StatusOK, map[string]any{"ok": true, "manifest": r.releases.Manifest(req)})
	case "/api/admin/releases/legacy-preview":
		writeJSON(w, http.StatusOK, map[string]any{"ok": true, "updateInfo": r.releases.LegacyUpdateInfo(req), "toolStatus": r.releases.StaticJSON("tool-status.json")})
	default:
		http.NotFound(w, req)
	}
}

func (r *router) handleAdminReleaseNotices(w http.ResponseWriter, req *http.Request) {
	if r.notices == nil {
		writeError(w, http.StatusNotFound, "NOTICES_DISABLED", errors.New("release notices are not configured"))
		return
	}
	path := cleanPath(req.URL.Path)
	if req.Method == http.MethodPost && path == "/api/admin/releases/notices/import" {
		if err := r.notices.Import(req.Context()); err != nil {
			writeError(w, http.StatusInternalServerError, "NOTICE_IMPORT_FAILED", err)
			return
		}
		items, _ := r.notices.List(100)
		writeJSON(w, http.StatusOK, map[string]any{"ok": true, "items": items})
		return
	}
	if req.Method == http.MethodGet && path == "/api/admin/releases/notices" {
		items, err := r.notices.List(100)
		if err != nil {
			writeError(w, http.StatusInternalServerError, "NOTICE_LIST_FAILED", err)
			return
		}
		writeJSON(w, http.StatusOK, map[string]any{"ok": true, "items": items})
		return
	}
	rest := strings.TrimPrefix(path, "/api/admin/releases/notices/")
	if rest == "" || rest == path {
		http.NotFound(w, req)
		return
	}
	parts := strings.Split(rest, "/")
	version := parts[0]
	if req.Method == http.MethodGet && len(parts) == 1 {
		doc, err := r.notices.Get(version)
		if err != nil {
			writeError(w, http.StatusNotFound, "NOTICE_NOT_FOUND", err)
			return
		}
		writeJSON(w, http.StatusOK, map[string]any{"ok": true, "document": doc})
		return
	}
	if req.Method == http.MethodPut && len(parts) == 1 {
		var body notices.SaveRequest
		if err := json.NewDecoder(req.Body).Decode(&body); err != nil {
			writeError(w, http.StatusBadRequest, "INVALID_PAYLOAD", err)
			return
		}
		doc, err := r.notices.Save(req.Context(), version, body, "admin")
		if err != nil {
			writeError(w, http.StatusBadRequest, "NOTICE_SAVE_FAILED", err)
			return
		}
		writeJSON(w, http.StatusOK, map[string]any{"ok": true, "document": doc})
		return
	}
	if req.Method == http.MethodPost && len(parts) == 2 && parts[1] == "validate" {
		var body notices.SaveRequest
		if err := json.NewDecoder(req.Body).Decode(&body); err != nil {
			writeError(w, http.StatusBadRequest, "INVALID_PAYLOAD", err)
			return
		}
		doc, err := r.notices.Validate(req.Context(), version, body)
		if err != nil {
			writeError(w, http.StatusBadRequest, "NOTICE_VALIDATE_FAILED", err)
			return
		}
		writeJSON(w, http.StatusOK, map[string]any{"ok": true, "document": doc})
		return
	}
	if req.Method == http.MethodPost && len(parts) == 2 && parts[1] == "restore" {
		var body struct {
			RevisionID int64 `json:"revisionId"`
		}
		if err := json.NewDecoder(req.Body).Decode(&body); err != nil || body.RevisionID <= 0 {
			writeError(w, http.StatusBadRequest, "INVALID_PAYLOAD", errors.New("revisionId is required"))
			return
		}
		doc, err := r.notices.Restore(req.Context(), version, body.RevisionID, "admin")
		if err != nil {
			writeError(w, http.StatusBadRequest, "NOTICE_RESTORE_FAILED", err)
			return
		}
		writeJSON(w, http.StatusOK, map[string]any{"ok": true, "document": doc})
		return
	}
	http.NotFound(w, req)
}
