package com.xyw.console.asset.controller;

import static org.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xyw.console.asset.entity.AssetDeviceEntity;
import com.xyw.console.asset.entity.CompanyPersonEntity;
import com.xyw.console.asset.entity.CompanyProfileEntity;
import com.xyw.console.asset.entity.PhoneAssetEntity;
import com.xyw.console.asset.entity.WecomAccountEntity;
import com.xyw.console.asset.mapper.AssetDeviceMapper;
import com.xyw.console.asset.mapper.CompanyPersonMapper;
import com.xyw.console.asset.mapper.CompanyProfileMapper;
import com.xyw.console.asset.mapper.PhoneAssetMapper;
import com.xyw.console.asset.mapper.WecomAccountMapper;
import com.xyw.console.asset.service.WecomAccountService;
import com.xyw.console.auth.PagePermissionService;
import java.time.LocalDateTime;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

class WecomAccountControllerTest {

  /**
   * 代码作用（白话）：证明浏览器请求企微列表会得到统一成功响应、关联名称和不含删除标记的记录。
   * 关联文件：WecomAccountController.java、WecomAccountService.java、WecomAccountView.js。
   * 关联逻辑（调用链/数据流）：GET /api/wecom-accounts -> Controller -> Service -> Mapper -> JSON 表格数据。
   */
  @Test
  void returnsWecomAccountPageWithoutDeleteTime() throws Exception {
    MockMvc mockMvc = MockMvcBuilders.standaloneSetup(controller()).build();

    mockMvc.perform(get("/api/wecom-accounts"))
        .andExpect(status().isOk())
        .andExpect(jsonPath("$.code", is(200)))
        .andExpect(jsonPath("$.data.page", is(1)))
        .andExpect(jsonPath("$.data.size", is(20)))
        .andExpect(jsonPath("$.data.records[0].companyProfileName", is("示例科技有限公司")))
        .andExpect(jsonPath("$.data.records[0].phoneNumber", is("13812345678")))
        .andExpect(jsonPath("$.data.records[0].deviceName", is("iPhone 15")))
        .andExpect(jsonPath("$.data.records[0].operatorPersonName", is("王五")))
        .andExpect(jsonPath("$.data.records[0].deleteTime").doesNotExist());
  }

  /**
   * 代码作用（白话）：构造使用真实 Service 的 Controller，避免只验证模拟返回值。
   * 关联文件：WecomAccountController.java、WecomAccountService.java、各资产 Mapper。
   * 关联逻辑（调用链/数据流）：测试 HTTP 请求 -> Controller -> Service -> Mapper 模拟数据库结果。
   */
  private WecomAccountController controller() {
    WecomAccountMapper wecomMapper = org.mockito.Mockito.mock(WecomAccountMapper.class);
    CompanyProfileMapper companyProfileMapper = org.mockito.Mockito.mock(CompanyProfileMapper.class);
    PhoneAssetMapper phoneAssetMapper = org.mockito.Mockito.mock(PhoneAssetMapper.class);
    AssetDeviceMapper assetDeviceMapper = org.mockito.Mockito.mock(AssetDeviceMapper.class);
    CompanyPersonMapper companyPersonMapper = org.mockito.Mockito.mock(CompanyPersonMapper.class);
    Page<WecomAccountEntity> page = new Page<>(1, 20);
    page.setRecords(List.of(wecomAccount()));
    page.setTotal(1L);
    org.mockito.Mockito.when(wecomMapper.selectPage(org.mockito.ArgumentMatchers.any(), org.mockito.ArgumentMatchers.any())).thenReturn(page);
    org.mockito.Mockito.when(companyProfileMapper.selectList(org.mockito.ArgumentMatchers.any())).thenReturn(List.of(companyProfile()));
    org.mockito.Mockito.when(phoneAssetMapper.selectList(org.mockito.ArgumentMatchers.any())).thenReturn(List.of(phoneAsset()));
    org.mockito.Mockito.when(assetDeviceMapper.selectList(org.mockito.ArgumentMatchers.any())).thenReturn(List.of(device()));
    org.mockito.Mockito.when(companyPersonMapper.selectList(org.mockito.ArgumentMatchers.any())).thenReturn(List.of(operatorPerson()));
    return new WecomAccountController(new WecomAccountService(
        wecomMapper, companyProfileMapper, phoneAssetMapper, assetDeviceMapper, companyPersonMapper), org.mockito.Mockito.mock(PagePermissionService.class));
  }

  /**
   * 代码作用（白话）：构造接口测试的企微主记录。
   * 关联文件：WecomAccountEntity.java、WecomAccountService.java。
   * 关联逻辑（调用链/数据流）：企微主记录 -> Service 关联名称填充 -> Controller JSON。
   */
  private WecomAccountEntity wecomAccount() {
    WecomAccountEntity entity = new WecomAccountEntity();
    entity.setId(1L);
    entity.setWecomName("张三");
    entity.setWecomAlias("销售一组");
    entity.setWecomAccount("zhangsan");
    entity.setCompanyProfileId(10L);
    entity.setPhoneAssetId(20L);
    entity.setRealNameOwner("张三");
    entity.setRealNameOwnerStatus("已实名");
    entity.setGender("男");
    entity.setDeviceId(30L);
    entity.setOperatorPersonId(40L);
    entity.setCreateTime(LocalDateTime.of(2026, 7, 31, 10, 0));
    entity.setUpdateTime(LocalDateTime.of(2026, 7, 31, 11, 0));
    entity.setDeleteTime(0L);
    return entity;
  }

  /**
   * 代码作用（白话）：构造公司档案关联测试数据。
   * 关联文件：CompanyProfileEntity.java、WecomAccountService.java。
   * 关联逻辑（调用链/数据流）：公司 ID -> 公司名称 -> JSON 字段 companyProfileName。
   */
  private CompanyProfileEntity companyProfile() {
    CompanyProfileEntity entity = new CompanyProfileEntity();
    entity.setId(10L);
    entity.setCompanyName("示例科技有限公司");
    return entity;
  }

  /**
   * 代码作用（白话）：构造手机号资产关联测试数据。
   * 关联文件：PhoneAssetEntity.java、WecomAccountService.java。
   * 关联逻辑（调用链/数据流）：手机号资产 ID -> 手机号 -> JSON 字段 phoneNumber。
   */
  private PhoneAssetEntity phoneAsset() {
    PhoneAssetEntity entity = new PhoneAssetEntity();
    entity.setId(20L);
    entity.setPhoneNumber("13812345678");
    return entity;
  }

  /**
   * 代码作用（白话）：构造设备关联测试数据。
   * 关联文件：AssetDeviceEntity.java、WecomAccountService.java。
   * 关联逻辑（调用链/数据流）：设备 ID -> 设备名称 -> JSON 字段 deviceName。
   */
  private AssetDeviceEntity device() {
    AssetDeviceEntity entity = new AssetDeviceEntity();
    entity.setId(30L);
    entity.setDeviceName("iPhone 15");
    return entity;
  }

  /**
   * 代码作用（白话）：构造经办人关联测试数据。
   * 关联文件：CompanyPersonEntity.java、WecomAccountService.java。
   * 关联逻辑（调用链/数据流）：人员 ID -> 人员名称 -> JSON 字段 operatorPersonName。
   */
  private CompanyPersonEntity operatorPerson() {
    CompanyPersonEntity entity = new CompanyPersonEntity();
    entity.setId(40L);
    entity.setPersonName("王五");
    return entity;
  }
}
