package service_test

import (
	"context"
	"testing"
	"time"

	roomv1 "hyapp.local/api/proto/room/v1"
	"hyapp/pkg/appcode"
	"hyapp/pkg/xerr"
	"hyapp/services/room-service/internal/integration"
	roomservice "hyapp/services/room-service/internal/room/service"
	"hyapp/services/room-service/internal/router"
	"hyapp/services/room-service/internal/testutil/mysqltest"
)

func TestRoomBackgroundSaveListSetFlow(t *testing.T) {
	ctx := context.Background()
	repository := mysqltest.NewRepository(t)
	svc := roomservice.New(roomservice.Config{
		NodeID:         "node-room-background-test",
		LeaseTTL:       10 * time.Second,
		RankLimit:      20,
		SnapshotEveryN: 1,
	}, router.NewMemoryDirectory(), repository, followTestWallet{}, integration.NewNoopRoomEventPublisher(), integration.NewNoopOutboxPublisher())

	roomID := "room-background-flow"
	ownerID := int64(7101)
	if _, err := svc.CreateRoom(ctx, &roomv1.CreateRoomRequest{
		Meta:            roomservice.NewRequestMeta(roomID, ownerID),
		SeatCount:       10,
		Mode:            "voice",
		VisibleRegionId: 1001,
		RoomName:        "Background Flow",
		RoomAvatar:      testRoomCoverURL,
		RoomShortId:     "bg-flow",
	}); err != nil {
		t.Fatalf("create room failed: %v", err)
	}

	saveResp, err := svc.SaveRoomBackground(ctx, &roomv1.SaveRoomBackgroundRequest{
		Meta:     &roomv1.RequestMeta{AppCode: appcode.Default, RoomId: roomID, ActorUserId: ownerID},
		RoomId:   roomID,
		ImageUrl: " https://cdn.example.com/room-bg.png ",
	})
	if err != nil {
		t.Fatalf("save background failed: %v", err)
	}
	if saveResp.GetBackground().GetBackgroundId() <= 0 || saveResp.GetBackground().GetImageUrl() != "https://cdn.example.com/room-bg.png" {
		t.Fatalf("save response mismatch: %+v", saveResp.GetBackground())
	}

	listResp, err := svc.ListRoomBackgrounds(ctx, &roomv1.ListRoomBackgroundsRequest{
		Meta:         &roomv1.RequestMeta{AppCode: appcode.Default, RoomId: roomID},
		RoomId:       roomID,
		ViewerUserId: ownerID,
	})
	if err != nil {
		t.Fatalf("list backgrounds failed: %v", err)
	}
	if len(listResp.GetBackgrounds()) != 1 || listResp.GetSelectedBackgroundUrl() != "" {
		t.Fatalf("list response before set mismatch: %+v", listResp)
	}

	setResp, err := svc.SetRoomBackground(ctx, &roomv1.SetRoomBackgroundRequest{
		Meta:         &roomv1.RequestMeta{AppCode: appcode.Default, RoomId: roomID, ActorUserId: ownerID, CommandId: "cmd-room-bg-set"},
		BackgroundId: saveResp.GetBackground().GetBackgroundId(),
	})
	if err != nil {
		t.Fatalf("set background failed: %v", err)
	}
	if !setResp.GetResult().GetApplied() || setResp.GetRoom().GetRoomExt()["background_url"] != "https://cdn.example.com/room-bg.png" {
		t.Fatalf("set response mismatch: %+v", setResp)
	}

	snapshotResp, err := svc.GetRoomSnapshot(ctx, &roomv1.GetRoomSnapshotRequest{
		Meta:         &roomv1.RequestMeta{AppCode: appcode.Default, RoomId: roomID},
		RoomId:       roomID,
		ViewerUserId: ownerID,
	})
	if err != nil {
		t.Fatalf("snapshot after set failed: %v", err)
	}
	if snapshotResp.GetRoom().GetRoomExt()["background_url"] != "https://cdn.example.com/room-bg.png" {
		t.Fatalf("snapshot must expose selected background_url: %+v", snapshotResp.GetRoom().GetRoomExt())
	}
}

func TestRoomBackgroundOnlyOwnerCanEdit(t *testing.T) {
	ctx := context.Background()
	repository := mysqltest.NewRepository(t)
	svc := roomservice.New(roomservice.Config{
		NodeID:         "node-room-background-owner-test",
		LeaseTTL:       10 * time.Second,
		RankLimit:      20,
		SnapshotEveryN: 1,
	}, router.NewMemoryDirectory(), repository, followTestWallet{}, integration.NewNoopRoomEventPublisher(), integration.NewNoopOutboxPublisher())

	roomID := "room-background-owner"
	ownerID := int64(7201)
	otherID := int64(7202)
	if _, err := svc.CreateRoom(ctx, &roomv1.CreateRoomRequest{
		Meta:            roomservice.NewRequestMeta(roomID, ownerID),
		SeatCount:       10,
		Mode:            "voice",
		VisibleRegionId: 1001,
		RoomName:        "Background Owner",
		RoomAvatar:      testRoomCoverURL,
		RoomShortId:     "bg-owner",
	}); err != nil {
		t.Fatalf("create room failed: %v", err)
	}

	if _, err := svc.SaveRoomBackground(ctx, &roomv1.SaveRoomBackgroundRequest{
		Meta:     &roomv1.RequestMeta{AppCode: appcode.Default, RoomId: roomID, ActorUserId: otherID},
		RoomId:   roomID,
		ImageUrl: "https://cdn.example.com/other-bg.png",
	}); !xerr.IsCode(err, xerr.PermissionDenied) {
		t.Fatalf("non-owner save must be denied: %v", err)
	}

	saveResp, err := svc.SaveRoomBackground(ctx, &roomv1.SaveRoomBackgroundRequest{
		Meta:     &roomv1.RequestMeta{AppCode: appcode.Default, RoomId: roomID, ActorUserId: ownerID},
		RoomId:   roomID,
		ImageUrl: "https://cdn.example.com/owner-bg.png",
	})
	if err != nil {
		t.Fatalf("owner save background failed: %v", err)
	}

	if _, err := svc.SetRoomBackground(ctx, &roomv1.SetRoomBackgroundRequest{
		Meta:         &roomv1.RequestMeta{AppCode: appcode.Default, RoomId: roomID, ActorUserId: otherID, CommandId: "cmd-room-bg-other"},
		BackgroundId: saveResp.GetBackground().GetBackgroundId(),
	}); !xerr.IsCode(err, xerr.PermissionDenied) {
		t.Fatalf("non-owner set must be denied: %v", err)
	}
}
