package app

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

	"bindbox-game/internal/pkg/core"
	"bindbox-game/internal/pkg/logger"
	"bindbox-game/internal/proposal"
	"bindbox-game/internal/repository/mysql"
	// no dao in logger
)

func Test_ListUserCouponUsage_App(t *testing.T) {
	repo, err := mysql.NewSQLiteRepoForTest()
	if err != nil {
		t.Fatal(err)
	}
	// create ledger table for sqlite
	ddl := `CREATE TABLE user_coupon_ledger (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        user_id BIGINT NOT NULL,
        user_coupon_id BIGINT NOT NULL,
        change_amount BIGINT NOT NULL,
        balance_after BIGINT NOT NULL,
        order_id BIGINT,
        action TEXT NOT NULL,
        created_at TEXT NOT NULL
    );`
	if err := repo.GetDbW().Exec(ddl).Error; err != nil {
		t.Fatal(err)
	}
	// seed rows
	if err := repo.GetDbW().Exec(`INSERT INTO user_coupon_ledger (user_id,user_coupon_id,change_amount,balance_after,order_id,action,created_at) VALUES (1,10,-100,900,0,'apply','2025-01-01 10:00:00')`).Error; err != nil {
		t.Fatal(err)
	}
	if err := repo.GetDbW().Exec(`INSERT INTO user_coupon_ledger (user_id,user_coupon_id,change_amount,balance_after,order_id,action,created_at) VALUES (1,10,-200,700,0,'apply','2025-01-01 11:00:00')`).Error; err != nil {
		t.Fatal(err)
	}

	lg, err := logger.NewCustomLogger(nil, logger.WithOutputInConsole())
	if err != nil {
		t.Fatal(err)
	}
	mux, err := core.New(lg)
	if err != nil {
		t.Fatal(err)
	}

	// stub auth that sets session user id=1
	dummyAuth := func(ctx core.Context) (proposal.SessionUserInfo, core.BusinessError) {
		return proposal.SessionUserInfo{Id: 1}, nil
	}
	app := mux.Group("/api/app", core.WrapAuthHandler(dummyAuth))
	app.GET("/users/:user_id/coupons/:user_coupon_id/usage", New(lg, repo).ListUserCouponUsage())

	rr := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/api/app/users/1/coupons/10/usage?page=1&page_size=20", bytes.NewBufferString(""))
	mux.ServeHTTP(rr, req)
	if rr.Code != http.StatusOK {
		t.Fatalf("code=%d body=%s", rr.Code, rr.Body.String())
	}
	var rsp map[string]interface{}
	if err := json.Unmarshal([]byte(rr.Body.String()), &rsp); err != nil {
		t.Fatal(err)
	}
	if int(rsp["total"].(float64)) != 2 {
		t.Fatalf("expect total=2 got %v", rsp["total"])
	}
}
