package org.agt.module.license.controller.admin.customer;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.agt.framework.apilog.core.annotation.ApiAccessLog;
import org.agt.framework.common.pojo.CommonResult;
import org.agt.framework.common.pojo.PageParam;
import org.agt.framework.common.pojo.PageResult;
import org.agt.framework.common.util.object.BeanUtils;
import org.agt.framework.excel.core.util.ExcelUtils;
import org.agt.framework.ip.core.utils.AreaUtils;
import org.agt.framework.security.core.service.SecurityFrameworkService;
import org.agt.module.license.controller.admin.common.vo.CommonExportReqVO;
import org.agt.module.license.controller.admin.customer.vo.CustomerImportRespVO;
import org.agt.module.license.controller.admin.customer.vo.CustomerPageReqVO;
import org.agt.module.license.controller.admin.customer.vo.CustomerRespVO;
import org.agt.module.license.controller.admin.customer.vo.CustomerSaveReqVO;
import org.agt.module.license.controller.admin.customer.vo.DashboardRespVO;
import org.agt.module.license.controller.admin.license.vo.ImportRespVO;
import org.agt.module.license.dal.dataobject.customer.CustomerDO;
import org.agt.module.license.service.customer.CustomerService;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import static org.agt.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static org.agt.framework.common.pojo.CommonResult.success;

@Tag(name = "管理后台 - 客户")
@RestController
@RequestMapping("/license/customer")
@Validated
public class CustomerController {

    @Resource
    private CustomerService customerService;

    @Resource
    private SecurityFrameworkService securityFrameworkService;

    @GetMapping("/dashboard")
    @Operation(summary = "获得首页数据")
    public CommonResult<DashboardRespVO> dashboard() {
        DashboardRespVO result = customerService.dashboard();
        return success(result);
    }

    @PostMapping("/create")
    @Operation(summary = "创建客户")
    @PreAuthorize("@ss.hasPermission('license:customer:create')")
    public CommonResult<Long> createCustomer(@Valid @RequestBody CustomerSaveReqVO createReqVO) {
        return success(customerService.createCustomer(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新客户")
    @PreAuthorize("@ss.hasPermission('license:customer:update')")
    public CommonResult<Boolean> updateCustomer(@Valid @RequestBody CustomerSaveReqVO updateReqVO) {
        customerService.updateCustomer(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除客户")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('license:customer:delete')")
    public CommonResult<Boolean> deleteCustomer(@RequestParam("id") Long id) {
        customerService.deleteCustomer(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得客户")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('license:customer:query')")
    public CommonResult<CustomerRespVO> getCustomer(@RequestParam("id") Long id) {
        CustomerDO customer = customerService.getCustomer(id);

        if (!securityFrameworkService.hasRole("business")) {
            customer.setContacts(null);
            customer.setRole(null);
            customer.setPhone(null);
        }

        return success(BeanUtils.toBean(customer, CustomerRespVO.class, customerRespVO -> {
            if (customerRespVO.getAreaId() != null) {
                customerRespVO.setAreaIds(AreaUtils.formatToIdList(customerRespVO.getAreaId().intValue()));
            }
        }));
    }

    @GetMapping("/name-unique")
    @Operation(summary = "校验客户名称是否唯一")
    public CommonResult<Boolean> validateCustomerNameUnique(@RequestParam(value = "name", required = false) String name, @RequestParam(value = "id", required = false) Long id) {
        Boolean isExists = customerService.validateCustomerNameUnique(name, id);
        return success(isExists);
    }

    @GetMapping("/code-unique")
    @Operation(summary = "校验客户编号是否唯一")
    public CommonResult<Boolean> validateCustomerCodeUnique(@RequestParam(value = "code", required = false) String code, @RequestParam(value = "id", required = false) Long id) {
        Boolean isExists = customerService.validateCustomerCodeUnique(code, id);
        return success(isExists);
    }

    @GetMapping("/max-sn")
    @Operation(summary = "返回当前最大客户sn")
    public CommonResult<Integer> selectMaxCode() {
        return success(customerService.selectMaxCode());
    }

    @GetMapping("/page")
    @Operation(summary = "获得客户分页")
    @PreAuthorize("@ss.hasPermission('license:customer:query')")
    public CommonResult<PageResult<CustomerRespVO>> getCustomerPage(@Valid CustomerPageReqVO pageReqVO) {
        PageResult<CustomerDO> pageResult = customerService.getCustomerPage(pageReqVO);

        if (!securityFrameworkService.hasRole("business")) {
            List<CustomerDO> list = pageResult.getList();
            list.forEach(customerDO -> {
                customerDO.setContacts(null);
                customerDO.setRole(null);
                customerDO.setPhone(null);
            });
        }

        return success(buildCustomerVOList(pageResult));
    }

    @GetMapping("/list")
    @Operation(summary = "获得客户列表")
//    @PreAuthorize("@ss.hasPermission('license:customer:query')")
    public CommonResult<List<CustomerRespVO>> getCustomerList() {
        List<CustomerDO> listResult = customerService.getCustomerList();

        if (!securityFrameworkService.hasRole("business")) {
            listResult.forEach(customerDO -> {
                customerDO.setContacts(null);
                customerDO.setRole(null);
                customerDO.setPhone(null);
            });
        }

        return success(BeanUtils.toBean(listResult, CustomerRespVO.class));
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出客户 Excel")
    @PreAuthorize("@ss.hasPermission('license:customer:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportCustomerExcel(@Valid CustomerPageReqVO pageReqVO,
                                    HttpServletResponse response) throws IOException {
        if ("all".equals(pageReqVO.getMode())) {
            CommonExportReqVO exportReqVO = BeanUtils.toBean(pageReqVO, CommonExportReqVO.class);
            pageReqVO = BeanUtils.toBean(exportReqVO, CustomerPageReqVO.class);
            pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        }
        PageResult<CustomerDO> pageResult = customerService.getCustomerPage(pageReqVO);

        if (!securityFrameworkService.hasRole("business")) {
            pageReqVO.setIncludeFields(pageReqVO.getIncludeFields().stream()
                    .filter(c -> !Arrays.asList("contacts", "role", "phone").contains(c)).collect(Collectors.toSet()));
        }
        // 导出 Excel
        ExcelUtils.writeSelected(response, "", pageReqVO.getSheetName(), CustomerRespVO.class,
                buildCustomerVOList(pageResult).getList(), pageReqVO.getIncludeFields());
    }

    private static PageResult<CustomerRespVO> buildCustomerVOList(PageResult<CustomerDO> pageResult) {
        return BeanUtils.toBean(pageResult, CustomerRespVO.class, customerRespVO -> {
            if (customerRespVO.getAreaId() != null) {
                customerRespVO.setAreaNames(AreaUtils.format(customerRespVO.getAreaId().intValue()));
            }
        });
    }

    @GetMapping("/get-import-template")
    @Operation(summary = "获得导入客户模板")
    public void importTemplate(HttpServletResponse response) throws IOException {
        // 手动创建导出 demo
        List<CustomerImportRespVO> list = Arrays.asList(
                CustomerImportRespVO.builder().name("测试客户").code(2000L).type(1)
                        .areaNames("北京市 北京市 东城区").contacts("小李")
                        .build(),
                CustomerImportRespVO.builder().name("测试客户2").code(2001L).type(1)
                        .areaNames("北京市").contacts("小李")
                        .build()
        );
        // 输出
        ExcelUtils.write(response, "客户导入模板.xlsx", "客户列表", CustomerImportRespVO.class, list);
    }

    @PostMapping("/import")
    @Operation(summary = "导入客户")
    @Parameters({
            @Parameter(name = "file", description = "Excel 文件", required = true),
            @Parameter(name = "updateSupport", description = "是否支持更新，默认为 false", example = "true")
    })
    @PreAuthorize("@ss.hasPermission('license:customer:export')")
    public CommonResult<ImportRespVO> importExcel(@RequestParam("file") MultipartFile file,
                                                  @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception {
        List<CustomerImportRespVO> list = ExcelUtils.read(file, CustomerImportRespVO.class);
        return success(customerService.importList(list, updateSupport));
    }

    @GetMapping("/license-list")
    @Operation(summary = "获得申请license可选择的客户列表")
    @PreAuthorize("@ss.hasPermission('license:customer:query')")
    public CommonResult<List<CustomerRespVO>> getLicenseCustomers() {
        return success(customerService.getLicenseCustomers());
    }
}