package com.gxwebsoft.common.system.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.gxwebsoft.common.core.config.ConfigProperties;
import com.gxwebsoft.common.core.exception.BusinessException;
import com.gxwebsoft.common.core.utils.CommonUtil;
import com.gxwebsoft.common.core.utils.JSONUtil;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.*;
import com.gxwebsoft.common.system.service.*;
import com.gxwebsoft.common.system.param.TenantParam;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.annotation.OperationLog;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 租户控制器
 *
 * @author 科技小王子
 * @since 2023-07-17 17:49:53
 */
@Api(tags = "系统租户")
@RestController
@RequestMapping("/api/system/tenant")
public class TenantController extends BaseController {
  @Resource
  private TenantService tenantService;
  @Resource
  private MenuService menuService;
  @Resource
  private RoleMenuService roleMenuService;
  @Resource
  private CompanyService companyService;
  @Resource
  private RedisUtil redisUtil;
  @Resource
  private UserService userService;

  @ApiOperation("分页查询租户")
  @GetMapping("/page")
  public ApiResult<PageResult<Tenant>> page(TenantParam param) {
    return success(tenantService.pageRel(param));
  }

  @PreAuthorize("hasAuthority('sys:tenant:list')")
  @ApiOperation("查询全部租户")
  @GetMapping()
  public ApiResult<List<Tenant>> list(TenantParam param) {
    // 使用关联查询
    return success(tenantService.listRel(param));
  }

  @PreAuthorize("hasAuthority('sys:tenant:list')")
  @ApiOperation("根据id查询租户")
  @GetMapping("/{id}")
  public ApiResult<Tenant> get(@PathVariable("id") Integer id) {
    Tenant tenant = tenantService.getById(id);
    // 附加企业信息
    List<Company> list = companyService.list(new LambdaQueryWrapper<Company>().eq(Company::getTenantId, tenant.getTenantId()).eq(Company::getAuthoritative, true));
    if (!CollectionUtils.isEmpty(list)) {
      final Company company = list.get(0);
      tenant.setCompany(company);
    }
    return success(tenant);
  }

  @ApiOperation("根据code搜索租户")
  @GetMapping("/getTenantId/{code}")
  public ApiResult<Integer> getTenantIdByKeywords(@PathVariable("code") String code) {
    String key = "TenantCode:".concat(code);
    // 查询缓存
    final String string = redisUtil.get(key);
    if(string != null){
      return success(JSONUtil.parseObject(string, Integer.class));
    }
    // 使用关联查询
    final Tenant tenant = tenantService.getOne(new LambdaUpdateWrapper<Tenant>().eq(Tenant::getTenantId, code).or().eq(Tenant::getTenantCode, code).last("limit 1"));
    if(tenant == null){
      return fail("应用不存在或已过期",null);
    }
    redisUtil.set(key,tenant.getTenantId().toString(),1L, TimeUnit.DAYS);
    return success(tenant.getTenantId());
  }

  @PreAuthorize("hasAuthority('sys:tenant:save')")
  @OperationLog
  @ApiOperation("添加租户")
  @PostMapping()
  public ApiResult<?> save(@RequestBody Tenant tenant) {
    if (tenantService.save(tenant)) {
      return success("添加成功");
    }
    return fail("添加失败");
  }

  @PreAuthorize("hasAuthority('sys:tenant:update')")
  @OperationLog
  @ApiOperation("修改租户")
  @PutMapping()
  public ApiResult<?> update(@RequestBody Tenant tenant) {
    if (tenantService.updateById(tenant)) {
      return success("修改成功");
    }
    return fail("修改失败");
  }

  @PreAuthorize("hasAuthority('sys:tenant:remove')")
  @OperationLog
  @ApiOperation("删除租户")
  @DeleteMapping("/{id}")
  public ApiResult<?> remove(@PathVariable("id") Integer id) {
    if (tenantService.removeById(id)) {
      return success("删除成功");
    }
    return fail("删除失败");
  }

  @PreAuthorize("hasAuthority('sys:tenant:save')")
  @OperationLog
  @ApiOperation("批量添加租户")
  @PostMapping("/batch")
  public ApiResult<?> saveBatch(@RequestBody List<Tenant> list) {
    if (tenantService.saveBatch(list)) {
      return success("添加成功");
    }
    return fail("添加失败");
  }

  @PreAuthorize("hasAuthority('sys:tenant:update')")
  @OperationLog
  @ApiOperation("批量修改租户")
  @PutMapping("/batch")
  public ApiResult<?> removeBatch(@RequestBody BatchParam<Tenant> batchParam) {
    if (batchParam.update(tenantService, "tenant_id")) {
      return success("修改成功");
    }
    return fail("修改失败");
  }

  @PreAuthorize("hasAuthority('sys:tenant:remove')")
  @OperationLog
  @ApiOperation("批量删除租户")
  @DeleteMapping("/batch")
  public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
    if (tenantService.removeByIds(ids)) {
      return success("删除成功");
    }
    return fail("删除失败");
  }

  @ApiOperation("租户角色权限初始化")
  @GetMapping("/role-menu/{id}")
  public ApiResult<List<Menu>> initialization(@PathVariable("id") Integer roleId) {
    List<Menu> menus = menuService.list(new LambdaQueryWrapper<Menu>().orderByAsc(Menu::getSortNumber));
    List<RoleMenu> roleMenus = roleMenuService.list(new LambdaQueryWrapper<RoleMenu>()
      .eq(RoleMenu::getRoleId, roleId));
    for (Menu menu : menus) {
      menu.setChecked(roleMenus.stream().anyMatch((d) -> d.getMenuId().equals(menu.getMenuId())));
    }
    List<Integer> menuIds = menus.stream().map(Menu::getMenuId).collect(Collectors.toList());
    roleMenuService.remove(new LambdaUpdateWrapper<RoleMenu>().eq(RoleMenu::getRoleId, roleId));
    if (menuIds.size() > 0) {
      List<RoleMenu> roleMenuList = new ArrayList<>();
      for (Integer menuId : menuIds) {
        RoleMenu roleMenu = new RoleMenu();
        roleMenu.setRoleId(roleId);
        roleMenu.setMenuId(menuId);
        roleMenuList.add(roleMenu);
      }
      if (!roleMenuService.saveBatch(roleMenuList)) {
        throw new BusinessException("保存失败");
      }
    }
    return success(menus);
  }

  @ApiOperation("创建租户")
  @PostMapping("/saveByPhone")
  public ApiResult<?> saveByPhone(@RequestBody Tenant tenant) {
    final String phone = tenant.getPhone();
    if(tenant.getTenantName() == null){
      return null;
    }
    if(tenant.getTenantCode() == null){
      return null;
    }
    if (tenantService.count(new LambdaQueryWrapper<Tenant>().eq(Tenant::getTenantCode, phone)) > 0) {
      return null;
    }
    if (tenantService.save(tenant)) {
      // 租户初始化
      final Company company = new Company();
      company.setDomain(tenant.getTenantId().toString().concat(".websoft.top"));
      company.setPhone(phone);
      company.setEmail(null);
      company.setPassword(userService.encodePassword(phone));
      company.setTid(tenant.getTenantId());
      company.setCompanyName(tenant.getTenantName());
      company.setShortName(tenant.getTenantName());
      company.setTenantId(tenant.getTenantId());
      tenantService.initialization(company);
      return success("创建成功",tenant);
    }
    return null;
  }
}
