package com.red.circle.console.app.service.app.activity;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.red.circle.console.app.dto.clienobject.app.activity.cp.ResidentCpConfigCO;
import com.red.circle.console.app.dto.clienobject.app.activity.cp.ResidentCpLevelConfigCO;
import com.red.circle.console.app.dto.cmd.app.activity.cp.ResidentCpConfigSaveCmd;
import com.red.circle.console.app.dto.cmd.app.activity.cp.ResidentCpLevelConfigSaveCmd;
import com.red.circle.console.app.service.app.sys.CpCabinConfigService;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.other.inner.model.cmd.sys.SysCpCabinConfigQryCmd;
import com.red.circle.other.inner.model.dto.sys.SysCpCabinConfigDTO;
import java.util.List;
import org.junit.jupiter.api.Test;

class ResidentCpActivityServiceImplTest {

  @Test
  void getConfigShouldReturnCpLevelsFromZeroToFive() {
    CpCabinConfigService cpCabinConfigService = mock(CpCabinConfigService.class);
    ResidentCpActivityServiceImpl service = new ResidentCpActivityServiceImpl(
        cpCabinConfigService);
    PageResult<SysCpCabinConfigDTO> page = new PageResult<>();
    page.setRecords(List.of(
        config(100L, 1L, 100L),
        config(101L, 2L, 200L),
        config(102L, 3L, 300L),
        config(103L, 4L, 400L),
        config(104L, 5L, 500L)
    ));
    when(cpCabinConfigService.getCpCabin(any(SysCpCabinConfigQryCmd.class))).thenReturn(page);

    ResidentCpConfigCO result = service.getConfig("likei");

    assertEquals("LIKEI", result.getSysOrigin());
    assertEquals(List.of(0, 1, 2, 3, 4, 5),
        result.getLevels().stream().map(ResidentCpLevelConfigCO::getLevel).toList());
    assertEquals(100L, result.getLevels().get(0).getRequiredIntimacyValue());
    assertEquals(100L, result.getLevels().get(0).getCabinConfigId());
    assertEquals(0L, result.getLevels().get(5).getRequiredIntimacyValue());
  }

  @Test
  void saveConfigShouldNotRequireExactLevelCount() {
    CpCabinConfigService cpCabinConfigService = mock(CpCabinConfigService.class);
    ResidentCpActivityServiceImpl service = new ResidentCpActivityServiceImpl(
        cpCabinConfigService);
    PageResult<SysCpCabinConfigDTO> page = new PageResult<>();
    page.setRecords(List.of());
    when(cpCabinConfigService.getCpCabin(any(SysCpCabinConfigQryCmd.class))).thenReturn(page);

    ResidentCpConfigSaveCmd cmd = new ResidentCpConfigSaveCmd()
        .setSysOrigin("likei")
        .setLevels(List.of(
            level(0, 0L),
            level(1, 100L),
            level(2, 200L),
            level(3, 300L),
            level(4, 400L)
        ));

    assertDoesNotThrow(() -> service.saveConfig(cmd));
    verify(cpCabinConfigService, times(5)).addCpCabin(any(SysCpCabinConfigDTO.class));
  }

  private static SysCpCabinConfigDTO config(Long id, Long sort, Long unlockValue) {
    return new SysCpCabinConfigDTO()
        .setId(id)
        .setName("CP " + sort + "级")
        .setCabinUnlockValue(unlockValue)
        .setSort(sort);
  }

  private static ResidentCpLevelConfigSaveCmd level(Integer level, Long requiredValue) {
    return new ResidentCpLevelConfigSaveCmd()
        .setLevel(level)
        .setLevelName("CP " + level + "级")
        .setRequiredIntimacyValue(requiredValue);
  }
}
