package com.cf.imes.module.report.controller.admin.datasource;

import com.bstek.common.utils.MultipleJdbcTemplate;
import com.bstek.datasource.bean.DataSourceInfo;
import com.bstek.datasource.service.DataSourceService;
import com.bstek.ureport.definition.dataset.Field;
import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.operatelog.core.annotations.OperateLog;
import com.cf.imes.module.report.controller.admin.datasource.vo.*;
import com.cf.imes.module.report.dal.dataobject.datasource.ReportDatasourceDO;
import com.cf.imes.module.report.service.datasource.ReportDatasourceService;
import com.cf.imes.module.report.utils.TenantParamsUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Size;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.cf.imes.framework.common.pojo.CommonResult.error;
import static com.cf.imes.framework.common.pojo.CommonResult.success;
import static com.cf.imes.framework.operatelog.core.enums.OperateTypeEnum.CREATE;
import static com.cf.imes.framework.operatelog.core.enums.OperateTypeEnum.UPDATE;
import static com.cf.imes.module.report.enums.ErrorCodeConstants.DATASOURCE_CONNECT_FAIL;

/**
 * 报表数据源控制器
 *
 * @author Gqr
 * @since 2024/7/5 16:53
 */
@Tag(name = "管理后台 - 报表数据源")
@RestController
@RequestMapping("/report")
@Validated
public class ReportDatasourceController {
    @Resource
    private ReportDatasourceService datasourceService;

    @Resource
    private DataSourceService ureportDataSourceService;

    @Resource
    private TenantParamsUtils tenantParamsUtils;

    @PutMapping("/datasource")
    @Operation(summary = "创建报表数据源")
    @OperateLog(type = CREATE)
    @PreAuthorize("@ss.hasAnyPermissions('system:report:datasource-connect','base:report:datasource-connect')")
    public CommonResult<Long> createDatasource(@Valid @RequestBody ReportDatasourceSaveReqVO createReqVO) {
        return success(datasourceService.createDatasource(createReqVO));
    }

    @PostMapping("/datasource")
    @Operation(summary = "更新报表数据源")
    @OperateLog(type = UPDATE)
    @PreAuthorize("@ss.hasAnyPermissions('system:report:datasource-connect','base:report:datasource-connect')")
    public CommonResult<Boolean> updateDatasource(@Valid @RequestBody ReportDatasourceSaveReqVO updateReqVO) {
        datasourceService.updateDatasource(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/datasource/{id}")
    @Operation(summary = "删除报表数据源")
    @Parameter(name = "id", description = "数据源id", required = true, example = "1")
    @PreAuthorize("@ss.hasAnyPermissions('system:report:datasource-connect','base:report:datasource-connect')")
    public CommonResult<Boolean> deleteDatasource(@PathVariable("id") Long id) {
        datasourceService.deleteDatasource(id);
        return success(true);
    }

    @GetMapping("/datasource/{id}")
    @Operation(summary = "获取报表数据源")
    @Parameter(name = "id", description = "数据源id", required = true, example = "1")
    @PreAuthorize("@ss.hasPermission('report:design')")
    public CommonResult<ReportDatasourceRespVO> getDatasource(@PathVariable("id") Long id) {
        ReportDatasourceDO datasource = datasourceService.getDatasource(id);
        return success(BeanUtils.toBean(datasource, ReportDatasourceRespVO.class));
    }

    @GetMapping("/datasources")
    @Operation(summary = "获取报表数据源列表")
    @PreAuthorize("@ss.hasPermission('report:design')")
    public CommonResult<List<ReportDatasourceRespVO>> getDatasourcePage(@RequestParam(value = "organId", required = false) Long organId) {
        return success(BeanUtils.toBean(datasourceService.getDatasourceList(organId), ReportDatasourceRespVO.class));
    }

    @GetMapping("/datasource/beans")
    @Operation(summary = "获取springbean数据源列表")
    @PreAuthorize("@ss.hasPermission('report:design')")
    public CommonResult<List<ReportBeanDatasourceRespVO>> getBeanDatasourceList() {
        return success(datasourceService.getBeanDatasourceList());
    }

    @GetMapping("/springbean/result/clazz")
    @Operation(summary = "获取springbean数据源返回对象")
    @Parameter(name = "clazz", description = "返回对象类路径全名不能为空", required = true)
    @PreAuthorize("@ss.hasPermission('report:design')")
    public List<Field> springbeanFieldList(@RequestParam(value = "clazz") @NotEmpty(message = "类路径全名不能为空") @Size(max = 100, message = "类路径全名不能超过100个字符") String clazz) {
        return datasourceService.getSpringBeanResultFieldList(clazz);
    }

    @GetMapping("/datasource/bean/methods")
    @Operation(summary = "获取springbean数据源方法类表")
    @Parameter(name = "beanId", description = "springbeanId", required = true)
    @PreAuthorize("@ss.hasPermission('report:design')")
    public CommonResult<List<String>> getBeanDatasourceList(@RequestParam(value = "beanId") @NotEmpty(message = "beanId不能为空") @Size(max = 100, message = "beanId不能超过100个字符") String beanId) {
        return success(datasourceService.loadBeanMethods(beanId));
    }


    @PostMapping("/datasource/connect")
    @Operation(summary = "测试数据源连接")
    @PreAuthorize("@ss.hasAnyPermissions('system:report:datasource-connect','base:report:datasource-connect')")
    public CommonResult<Boolean> testDatasourceConnect(@RequestBody @Valid ReportDatasourceTestConnReqVO reqVO) {
        String success = MultipleJdbcTemplate.testConnection(BeanUtils.toBean(reqVO, DataSourceInfo.class));
        return Objects.equals("success", success) ? success(true) : error(DATASOURCE_CONNECT_FAIL);
    }

    @PostMapping("/datasource/tables")
    @Operation(summary = "获取数据库表列表")
    @OperateLog(enable = false)
    @PreAuthorize("@ss.hasPermission('report:design')")
    public CommonResult<List<Map<String, String>>> getDatasourceTables(@RequestBody @Valid ReportDatasourceTestConnReqVO reqVO) {
        return success(ureportDataSourceService.selectTableList(BeanUtils.toBean(reqVO, DataSourceInfo.class)));
    }

    @PostMapping("/datasource/table/fields")
    @Operation(summary = "获取数据源表字段")
    @OperateLog(enable = false)
    @PreAuthorize("@ss.hasPermission('report:design')")
    public CommonResult<List<Field>> getDatasourceTableFields(@RequestBody @Valid ReportDatasourcePreviewReqVO reqVO) {
        return success(datasourceService.getTableFields(tenantParamsUtils.prepareTenantParam(reqVO)));
    }

    @PostMapping("/datasource/preview")
    @Operation(summary = "数据源预览")
    @OperateLog(enable = false)
    @PreAuthorize("@ss.hasPermission('report:design')")
    public CommonResult<Map<String, Object>> previewData(@RequestBody @Valid ReportDatasourcePreviewReqVO reqVO) {
        return success(ureportDataSourceService.previewData(tenantParamsUtils.prepareTenantParam(reqVO)));
    }
}
