package agencyopening

import (
	"context"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"testing"

	"hyapp-admin-server/internal/appctx"
	"hyapp-admin-server/internal/integration/activityclient"
	"hyapp-admin-server/internal/middleware"
	activityv1 "hyapp.local/api/proto/activity/v1"

	"github.com/gin-gonic/gin"
)

func TestApproveApplicationForwardsReviewRequest(t *testing.T) {
	activity := &fakeAgencyOpeningActivityClient{}
	router := newAgencyOpeningHandlerTestRouter(New(activity, nil))
	request := httptest.NewRequest(http.MethodPost, "/admin/activity/agency-opening/applications/application-1/approve", nil)
	recorder := httptest.NewRecorder()

	router.ServeHTTP(recorder, request)

	if recorder.Code != http.StatusOK {
		t.Fatalf("status mismatch: got=%d body=%s", recorder.Code, recorder.Body.String())
	}
	if activity.lastReview == nil ||
		activity.lastReview.GetApplicationId() != "application-1" ||
		activity.lastReview.GetAction() != "approve" ||
		activity.lastReview.GetOperatorAdminId() != 7 ||
		activity.lastReview.GetMeta().GetAppCode() != "lalu" ||
		activity.lastReview.GetMeta().GetCaller() != "admin-server" {
		t.Fatalf("review request mismatch: %+v", activity.lastReview)
	}

	var envelope struct {
		Code int `json:"code"`
		Data struct {
			ApplicationID     string `json:"application_id"`
			Status            string `json:"status"`
			ApprovedAtMS      int64  `json:"approved_at_ms"`
			ScoreStartMS      int64  `json:"score_start_ms"`
			ScoreEndMS        int64  `json:"score_end_ms"`
			ReviewedByAdminID int64  `json:"reviewed_by_admin_id"`
		} `json:"data"`
	}
	if err := json.Unmarshal(recorder.Body.Bytes(), &envelope); err != nil {
		t.Fatalf("decode response: %v", err)
	}
	if envelope.Code != 0 ||
		envelope.Data.ApplicationID != "application-1" ||
		envelope.Data.Status != "approved" ||
		envelope.Data.ApprovedAtMS != 2000 ||
		envelope.Data.ScoreStartMS != 2000 ||
		envelope.Data.ScoreEndMS != 2000+24*60*60*1000 ||
		envelope.Data.ReviewedByAdminID != 7 {
		t.Fatalf("approve response mismatch: %+v", envelope)
	}
}

func newAgencyOpeningHandlerTestRouter(handler *Handler) *gin.Engine {
	gin.SetMode(gin.TestMode)
	router := gin.New()
	router.Use(func(c *gin.Context) {
		// 这里模拟后台鉴权中间件已经把 app_code、request_id 和操作者写入上下文，测试只关注接口参数透传。
		c.Request = c.Request.WithContext(appctx.WithContext(c.Request.Context(), "lalu"))
		c.Set(middleware.ContextRequestID, "agency-opening-handler-test")
		c.Set(middleware.ContextUserID, uint(7))
		c.Set(middleware.ContextUsername, "tester")
		c.Next()
	})
	router.POST("/admin/activity/agency-opening/applications/:application_id/approve", handler.ApproveApplication)
	return router
}

type fakeAgencyOpeningActivityClient struct {
	activityclient.Client

	lastReview *activityv1.ReviewAgencyOpeningApplicationRequest
}

func (f *fakeAgencyOpeningActivityClient) ReviewAgencyOpeningApplication(_ context.Context, req *activityv1.ReviewAgencyOpeningApplicationRequest) (*activityv1.ReviewAgencyOpeningApplicationResponse, error) {
	f.lastReview = req
	return &activityv1.ReviewAgencyOpeningApplicationResponse{
		Application: &activityv1.AgencyOpeningApplication{
			ApplicationId:     req.GetApplicationId(),
			CycleId:           "cycle-1",
			AgencyId:          8001,
			AgencyOwnerUserId: 42001,
			AgencyName:        "Window Agency",
			HostCount:         12,
			Status:            "approved",
			AppliedAtMs:       1000,
			ApprovedAtMs:      2000,
			ScoreStartMs:      2000,
			ScoreEndMs:        2000 + int64((24 * 60 * 60 * 1000)),
			ReviewedByAdminId: req.GetOperatorAdminId(),
		},
	}, nil
}
