package handlers

import (
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"path/filepath"
	"testing"
	"time"

	"git.mchus.pro/mchus/quoteforge/internal/localdb"
	syncsvc "git.mchus.pro/mchus/quoteforge/internal/services/sync"
	"github.com/gin-gonic/gin"
)

func TestSyncReadinessOfflineBlocked(t *testing.T) {
	gin.SetMode(gin.TestMode)

	dir := t.TempDir()
	local, err := localdb.New(filepath.Join(dir, "qfs.db"))
	if err != nil {
		t.Fatalf("init local db: %v", err)
	}

	service := syncsvc.NewService(nil, local)
	h, err := NewSyncHandler(local, service, nil, filepath.Join("web", "templates"), 5*time.Minute)
	if err != nil {
		t.Fatalf("new sync handler: %v", err)
	}

	router := gin.New()
	router.GET("/api/sync/readiness", h.GetReadiness)
	router.POST("/api/sync/push", h.PushPendingChanges)

	readinessResp := httptest.NewRecorder()
	readinessReq, _ := http.NewRequest(http.MethodGet, "/api/sync/readiness", nil)
	router.ServeHTTP(readinessResp, readinessReq)
	if readinessResp.Code != http.StatusOK {
		t.Fatalf("unexpected readiness status: %d", readinessResp.Code)
	}

	var readinessBody map[string]any
	if err := json.Unmarshal(readinessResp.Body.Bytes(), &readinessBody); err != nil {
		t.Fatalf("decode readiness body: %v", err)
	}
	if blocked, _ := readinessBody["blocked"].(bool); !blocked {
		t.Fatalf("expected blocked readiness, got %v", readinessBody["blocked"])
	}

	pushResp := httptest.NewRecorder()
	pushReq, _ := http.NewRequest(http.MethodPost, "/api/sync/push", nil)
	router.ServeHTTP(pushResp, pushReq)
	if pushResp.Code != http.StatusLocked {
		t.Fatalf("expected 423 for blocked sync push, got %d body=%s", pushResp.Code, pushResp.Body.String())
	}

	var pushBody map[string]any
	if err := json.Unmarshal(pushResp.Body.Bytes(), &pushBody); err != nil {
		t.Fatalf("decode push body: %v", err)
	}
	if pushBody["reason_text"] == nil || pushBody["reason_text"] == "" {
		t.Fatalf("expected reason_text in blocked response, got %v", pushBody)
	}
}
