package postgres

import (
	"context"
	"fmt"
	"testing"
	"time"

	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/break/junhong_cmp_fiber/tests/testutils"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func uniqueDeviceNoPrefix() string {
	return fmt.Sprintf("D%d", time.Now().UnixNano()%1000000000)
}

func TestDeviceStore_BatchUpdateSeriesID(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	rdb := testutils.GetTestRedis(t)
	testutils.CleanTestRedisKeys(t, rdb)

	s := NewDeviceStore(tx, rdb)
	ctx := context.Background()

	prefix := uniqueDeviceNoPrefix()
	devices := []*model.Device{
		{DeviceNo: prefix + "001", DeviceName: "测试设备1", Status: 1},
		{DeviceNo: prefix + "002", DeviceName: "测试设备2", Status: 1},
	}
	require.NoError(t, s.CreateBatch(ctx, devices))

	t.Run("设置系列ID", func(t *testing.T) {
		seriesID := uint(100)
		deviceIDs := []uint{devices[0].ID, devices[1].ID}

		err := s.BatchUpdateSeriesID(ctx, deviceIDs, &seriesID)
		require.NoError(t, err)

		var updatedDevices []*model.Device
		require.NoError(t, tx.Where("id IN ?", deviceIDs).Find(&updatedDevices).Error)
		for _, device := range updatedDevices {
			require.NotNil(t, device.SeriesID)
			assert.Equal(t, seriesID, *device.SeriesID)
		}
	})

	t.Run("清除系列ID", func(t *testing.T) {
		deviceIDs := []uint{devices[0].ID}

		err := s.BatchUpdateSeriesID(ctx, deviceIDs, nil)
		require.NoError(t, err)

		var updatedDevice model.Device
		require.NoError(t, tx.First(&updatedDevice, devices[0].ID).Error)
		assert.Nil(t, updatedDevice.SeriesID)
	})

	t.Run("空列表不报错", func(t *testing.T) {
		err := s.BatchUpdateSeriesID(ctx, []uint{}, nil)
		require.NoError(t, err)
	})
}

func TestDeviceStore_ListBySeriesID(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	rdb := testutils.GetTestRedis(t)
	testutils.CleanTestRedisKeys(t, rdb)

	s := NewDeviceStore(tx, rdb)
	ctx := context.Background()

	prefix := uniqueDeviceNoPrefix()
	seriesID := uint(200)
	devices := []*model.Device{
		{DeviceNo: prefix + "001", DeviceName: "测试设备1", Status: 1, SeriesID: &seriesID},
		{DeviceNo: prefix + "002", DeviceName: "测试设备2", Status: 1, SeriesID: &seriesID},
		{DeviceNo: prefix + "003", DeviceName: "测试设备3", Status: 1, SeriesID: nil},
	}
	require.NoError(t, s.CreateBatch(ctx, devices))

	result, err := s.ListBySeriesID(ctx, seriesID)
	require.NoError(t, err)
	assert.Len(t, result, 2)
	for _, device := range result {
		assert.Equal(t, seriesID, *device.SeriesID)
	}
}

func TestDeviceStore_List_SeriesIDFilter(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	rdb := testutils.GetTestRedis(t)
	testutils.CleanTestRedisKeys(t, rdb)

	s := NewDeviceStore(tx, rdb)
	ctx := context.Background()

	prefix := uniqueDeviceNoPrefix()
	seriesID := uint(300)
	devices := []*model.Device{
		{DeviceNo: prefix + "001", DeviceName: "测试设备1", Status: 1, SeriesID: &seriesID},
		{DeviceNo: prefix + "002", DeviceName: "测试设备2", Status: 1, SeriesID: &seriesID},
		{DeviceNo: prefix + "003", DeviceName: "测试设备3", Status: 1, SeriesID: nil},
	}
	require.NoError(t, s.CreateBatch(ctx, devices))

	filters := map[string]interface{}{
		"series_id": seriesID,
		"device_no": prefix,
	}
	result, total, err := s.List(ctx, nil, filters)
	require.NoError(t, err)
	assert.Equal(t, int64(2), total)
	assert.Len(t, result, 2)
	for _, device := range result {
		assert.Equal(t, seriesID, *device.SeriesID)
	}
}
