package cn.iocoder.yudao.module.system.controller.admin.biz;

import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.system.controller.admin.biz.vo.*;
import cn.iocoder.yudao.module.system.controller.admin.biz.vo.excel.*;
import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyCheckInRecordDO;
import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyInfoDO;
import cn.iocoder.yudao.module.system.dal.dataobject.biz.MbtiRecordBO;
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
import cn.iocoder.yudao.module.system.service.biz.BirthdayCareService;
import cn.iocoder.yudao.module.system.service.biz.ElderlyInfoService;
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.converters.longconverter.LongStringConverter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.alibaba.fastjson.JSONArray;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;


@Tag(name = "管理后台 - 长者信息")
@RestController
@RequestMapping("/elderlyInfo")
public class ElderlyInfoController {

    @Resource
    private ElderlyInfoService elderlyInfoService;
    @Resource
    private BirthdayCareService birthdayCareService;
    @Resource
    private TenantService tenantService;


    @GetMapping("/findPage")
    @Operation(summary = "长者信息列表分页")
    @TenantIgnore
    //@PreAuthorize("@ss.hasPermission('elderlyInfo:query')")
    public CommonResult<PageResult<ElderlyInfoDO>> findPage(@Valid ElderlyInfoPageReqVO pageVO) {
        pageVO.setTenantIds(Objects.isNull(pageVO.getTenantIds()) ? new Long[]{TenantContextHolder.getTenantId()} : pageVO.getTenantIds());
        PageResult<ElderlyInfoDO> pageResult = elderlyInfoService.findPage(pageVO);
        for (ElderlyInfoDO elderlyInfoDO : pageResult.getList()) {
            TenantDO tenant = tenantService.getTenant(elderlyInfoDO.getTenantId());
            elderlyInfoDO.setTenantName(tenant == null ? null : tenant.getName());
        }
        return success(pageResult);
    }


    @GetMapping("/elderlyCheckInRecordPage")
    @Operation(summary = "长者入住办理列表分页")
    @TenantIgnore
    public CommonResult<PageResult<ElderlyCheckInRecordDO>> elderlyCheckInRecordPage(@Valid ElderlyInfoPageReqVO pageVO) {
        pageVO.setTenantId(Objects.isNull(pageVO.getTenantId()) ? SecurityFrameworkUtils.getLoginUser().getTenantId() : pageVO.getTenantId());
        PageResult<ElderlyCheckInRecordDO> pageResult = elderlyInfoService.elderlyCheckInRecordPage(pageVO);
        return success(pageResult);
    }


    @PostMapping("/addElder")
    @Operation(summary = "新增长者")
    public CommonResult<Boolean> addElder(@RequestBody ElderlyInfoDO elderlyInfo) {
        elderlyInfoService.addElder(elderlyInfo);
        return success(true);
    }


    @GetMapping("/findAllList")
    @Operation(summary = "查询所有长者")
    public CommonResult<List<ElderlyInfoDO>> findAllList(@RequestParam(value = "orgType",required = false) Integer orgType) {
        return success(elderlyInfoService.findAllList(orgType));
    }


    @PostMapping("/update")
    @Operation(summary = "修改长者")
    public CommonResult<Boolean> update(@RequestBody ElderlyInfoDO elderlyInfo) {
        elderlyInfoService.update(elderlyInfo);
        return success(true);
    }


    @DeleteMapping("/delete")
    @Operation(summary = "删除长者")
    @Parameter(name = "id", description = "长者ID", required = true, example = "1024")
    public CommonResult<Boolean> delete(@RequestParam("id") Long id) {
        elderlyInfoService.delete(id);
        return success(true);
    }

    @DeleteMapping("/deleteElderlyAndRelatedData")
    @Operation(summary = "删除长者及其相关数据", description = "删除长者信息及相关联的入住记录、入住申请、费用账单等数据，并释放占用的床位")
    @Parameter(name = "id", description = "长者ID", required = true, example = "1024")
    @TenantIgnore
    public CommonResult<Boolean> deleteElderlyAndRelatedData(@RequestParam("id") Long id) {
        elderlyInfoService.deleteElderlyAndRelatedData(id);
        return success(true);
    }

    @GetMapping("/findDetailById")
    @Operation(summary = "查询长者档案")
    @Parameter(name = "id", description = "长者ID", required = true, example = "1024")
    public CommonResult<ElderlyInfoDO> findDetailById(@RequestParam("id") Long id) {
        ElderlyInfoDO elderlyInfoDO = elderlyInfoService.findDetailById(id);
        return success(elderlyInfoDO);
    }


    @GetMapping("/generateAdmissionAssessment")
    @Operation(summary = "入住")
    @Parameter(name = "elderId", description = "长者ID", required = true, example = "1024")
    public CommonResult<Boolean> generateAdmissionAssessment(@RequestParam("elderId") Long elderId) {
        elderlyInfoService.generateAdmissionAssessment(elderId);
        return success(true);
    }

    @GetMapping("/findBpmRecord")
    @Operation(summary = "查询入住记录审批信息")
    @Parameter(name = "elderId", description = "长者id", required = true, example = "1024")
    public CommonResult<BpmCheckInRecordRespVO> findBpmRecord(@RequestParam("elderId") Long elderId) {
        BpmCheckInRecordRespVO elderlyInfoDO = elderlyInfoService.findBpmRecord(elderId);
        return success(elderlyInfoDO);
    }

    @GetMapping("/getElderListByBuild")
    @Operation(summary = "根据楼栋查询全部老人列表")
    @TenantIgnore
    public CommonResult<List<ElderlyInfoDO>> getElderListByBuild(@RequestParam(value = "buildId") Long buildId,
                                                                 @RequestParam(value = "floorId", required = false) Long floorId,
                                                                 @RequestParam(value = "roomId", required = false) Long roomId,
                                                                 @RequestParam(value = "tenantIds",required = false) Long[] tenantIds) {

        return success(elderlyInfoService.getElderListByBuild(buildId, floorId, roomId,tenantIds));
    }


    @PostMapping("/importElder")
    @Operation(summary = "导入长者数据")
    public CommonResult<Map<String, Object>> importElder(ElderlyImportVO elderlyImportVO) throws IOException {
        List<ElderlyImportExcelVO> dataList = ExcelUtils.read(elderlyImportVO.getFile(), ElderlyImportExcelVO.class);
        return success(elderlyInfoService.importElder(dataList));
    }

    @PostMapping("/downErrorExcel")
    @Operation(summary = "导出失败的长者excel")
    public void downErrorExcel(@RequestBody List<ElderlyImportExcelVO> payload, HttpServletResponse response) throws IOException {
//        List<ElderlyImportExcelVO> data = JSONArray.parseArray(payload.toString(), ElderlyImportExcelVO.class);
        ExcelUtils.write(response, "长者数据", "失败数据", ElderlyImportExcelVO.class, payload);
    }


    @GetMapping("/downloadExcel")
    @Operation(summary = "下载长者导入模板")
    public void downloadFile(HttpServletResponse response) throws IOException {
        String filePath = "files/长者导入模板.xlsx";
        ClassPathResource classPathResource = new ClassPathResource(filePath);
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment; filename=长者导入模板");
        IOUtils.copy(classPathResource.getInputStream(), response.getOutputStream());
        response.flushBuffer();
    }


    @GetMapping("/downloadElderFileExcel")
    @Operation(summary = "下载长者档案导入模板")
    public void downloadElderFileExcel(HttpServletResponse response) throws IOException {
        String filePath = "files/长者档案导入模板.xls";
        ClassPathResource classPathResource = new ClassPathResource(filePath);
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment; filename=长者档案导入模板");
        IOUtils.copy(classPathResource.getInputStream(), response.getOutputStream());
        response.flushBuffer();
    }

    @PostMapping("/importElderFile")
    @Operation(summary = "导入长者数据")
    public CommonResult<Map<String, Object>> importElderFile(ElderlyImportVO elderlyImportVO) throws IOException {
        List<ElderlyFileImportExcelVO> dataList = ExcelUtils.read(elderlyImportVO.getFile(), ElderlyFileImportExcelVO.class);
        return success(elderlyInfoService.importElderFile(dataList));
    }

    @PostMapping("/downElderFileErrorExcel")
    @Operation(summary = "导出失败的长者excel")
    public void downElderFileErrorExcel(@RequestBody Map<String, Object> payload, HttpServletResponse response) throws IOException {
        List<ElderlyFileImportExcelVO> data = JSONArray.parseArray(payload.toString(), ElderlyFileImportExcelVO.class);
        ExcelUtils.write(response, "长者档案数据", "失败数据", ElderlyFileImportExcelVO.class, data);
    }


    @GetMapping("/queryUngroupedElderlyList")
    @Operation(summary = "获取未护理分组的长者列表")
    @TenantIgnore
    public CommonResult<List<ElderlyInfoDO>> queryUngroupedElderlyList(@RequestParam(value = "orgType",required = false) Integer orgType,
                                                                       @RequestParam(value = "tenantId",required = false) Long tenantId) {
        tenantId = Objects.isNull(tenantId) ? TenantContextHolder.getTenantId() : tenantId;
        return success(elderlyInfoService.queryUngroupedElderlyList(orgType,tenantId));
    }


    @GetMapping("/getBirthdayPictures")
    @Operation(summary = "长者活动相册")
    public CommonResult<List<String>> getBirthdayPictures(@RequestParam("elderId") Long elderId) {
        return success(birthdayCareService.getBirthdayPictures(elderId));
    }


    @GetMapping("/exportElder")
    @Operation(summary = "导出长者信息Excel")
    public void exportElder(@Valid ElderlyInfoPageReqVO pageVO, HttpServletResponse response) throws IOException {
        pageVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        Map<String, Object> dataMap = elderlyInfoService.selectExportElderData(pageVO);
        List<ElderlyBaseInfoExportExcelVO> baseInfo = (List<ElderlyBaseInfoExportExcelVO>) dataMap.get("baseInfo");
        List<ElderlyContractInfoExportExcelVO> contractInfo = (List<ElderlyContractInfoExportExcelVO>) dataMap.get("contractInfo");

//        ExcelUtils.write(response,"长者档案","基本信息",ElderlyBaseInfoExportExcelVO.class,baseInfo);


        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
                .autoCloseStream(false) // 不要自动关闭，交给 Servlet 自己处理
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度，自动适配。最大 255 宽度
                .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度
                .build();

        WriteSheet sheet1 = EasyExcel.writerSheet(0, "基本信息").head(ElderlyBaseInfoExportExcelVO.class).build();
        WriteSheet sheet2 = EasyExcel.writerSheet(1, "合同信息").head(ElderlyContractInfoExportExcelVO.class).build();
        excelWriter.write(baseInfo, sheet1);
        excelWriter.write(contractInfo, sheet2);
        excelWriter.finish();
        // 设置 header 和 contentType。写在最后的原因是，避免报错时，响应 contentType 已经被修改了
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("长者档案", StandardCharsets.UTF_8.name()));
        response.setContentType("application/vnd.ms-excel;charset=UTF-8");
    }

    @GetMapping("/getCheckInDetail")
    @Operation(summary = "办理入住详情")
    public CommonResult<CheckInRecordDetailRespVO> getCheckInDetail(@RequestParam("checkInRecordId") Long checkInRecordId) {
        return success(elderlyInfoService.getCheckInDetail(checkInRecordId));
    }


    @GetMapping("/getGroupTenant")
    @Operation(summary = "获取集团租户")
    @PermitAll
    public CommonResult<List<GroupTenantRespVO>> getGroupTenant(@RequestParam(value = "groupId", required = false) Long groupId) {
        return success(elderlyInfoService.getGroupTenant(groupId));
    }

    @PostMapping("/getGroupHomeData")
    @Operation(summary = "集团数据")
    @PermitAll
    public CommonResult<ElderlyHomeRespVO> getGroupHomeData(@Valid ElderlyInfoHomeDataReqVO reqVO) {

        ElderlyHomeRespVO respVO = elderlyInfoService.getElderlyInfoHomeData(reqVO);

        return success(respVO);
    }

    @PostMapping("/getTenantHomeData")
    @Operation(summary = "机构数据")
    @PermitAll
    public CommonResult<ElderlyHomeRespVO> getTenantHomeData(@Valid ElderlyInfoHomeDataReqVO reqVO) {

        ElderlyHomeRespVO respVO = elderlyInfoService.getTenantHomeData(reqVO);

        return success(respVO);
    }

    @GetMapping("/getMonitorUrl")
    @Operation(summary = "获取监控地址")
    @PermitAll
    public CommonResult<String> getMonitorUrl(Long tenantId) {

        String url = elderlyInfoService.getMonitorUrl(tenantId);

        return success(url);
    }

    @GetMapping("/getWeeklyOperationSummary")
    @Operation(summary = "获取机构长者周运营统计")
    @PermitAll
    public CommonResult<ElderlyWeeklyOperationSummaryRespVO> getWeeklyOperationSummary(@RequestParam(value = "tenantId", required = false) Long tenantId) {
        return success(elderlyInfoService.getWeeklyOperationSummary(tenantId));
    }

    @GetMapping("/getInstitutionDashboard")
    @Operation(summary = "获取机构看板统计（院内动态、护理情况）")
    @TenantIgnore
    public CommonResult<InstitutionDashboardRespVO> getInstitutionDashboard() {
        return success(elderlyInfoService.getInstitutionDashboard());
    }

    @PostMapping("/getHomeDataElderlyPortrait")
    @Operation(summary = "获取大屏长者画像")
    public CommonResult<ElderlyHomeRespVO> getHomeDataElderlyPortrait(@Valid ElderlyInfoHomeDataReqVO reqVO) {
        ElderlyHomeRespVO respVO = elderlyInfoService.getHomeDataElderlyPortrait(reqVO);
        return success(respVO);
    }

    @PostMapping("/getHomeDataCheckInAnalysis")
    @Operation(summary = "获取大屏入住分析")
    public CommonResult<ElderlyHomeRespVO> getHomeDataCheckInAnalysis(@Valid ElderlyInfoHomeDataReqVO reqVO) {
        ElderlyHomeRespVO respVO = elderlyInfoService.getHomeDataCheckInAnalysis(reqVO);
        return success(respVO);
    }


    @PostMapping("/getElderlyVitalSigns")
    @Operation(summary = "获取长者健康体征")
    public CommonResult<ElderlyVitalSignsStatisticsMainRespVO> getElderlyVitalSigns(@Valid ElderlyVitalSignsMainPageReqVO reqVO) {

        ElderlyVitalSignsStatisticsMainRespVO respVO = elderlyInfoService.getElderlyVitalSigns(reqVO);

        return success(respVO);
    }

    @PostMapping("/getElderlyVitalSignsToday")
    @Operation(summary = "获取长者健康体征今日动态")
    public CommonResult<PageResult<ElderlyVitalSignsStatisticsTodayRespVO>> getElderlyVitalSignsToday(@Valid ElderlyVitalSignsMainPageReqVO reqVO) {

        PageResult<ElderlyVitalSignsStatisticsTodayRespVO> respVO = elderlyInfoService.getElderlyVitalSignsToday(reqVO);

        return success(respVO);
    }


    @PostMapping("/addElderlyAtHome")
    @Operation(summary = "居家长者新增")
    @TenantIgnore
    public CommonResult<Boolean>  addElderlyAtHome(@RequestBody ElderlyInfoSaveReqVO reqVO){
        elderlyInfoService.addElderlyAtHome(reqVO);
        return success(true);
    }

    @PostMapping("/saveMBTIResult")
    @Operation(summary = "保存结果")
    @PermitAll
    public CommonResult<Boolean>  saveResult(@RequestBody MbtiRecordBO reqVO){
        Boolean result = elderlyInfoService.saveResult(reqVO);
        return success(result);
    }

    @GetMapping("/findMbtiPage")
    @Operation(summary = "mbti分页")
    @PermitAll
    public CommonResult<PageResult<MbtiRecordBO>> findMbtiPage(@Valid MbtiRecordPageReqVO pageVO) {
        PageResult<MbtiRecordBO> pageResult = elderlyInfoService.findMbtiPage(pageVO);
        return success(pageResult);
    }

    @PostMapping("/updateElderlyAtHome")
    @Operation(summary = "居家长者修改")
    @TenantIgnore
    public CommonResult<Boolean> updateElderlyAtHome(@RequestBody ElderlyInfoDO elderlyInfoDO){
        elderlyInfoService.updateElderlyAtHome(elderlyInfoDO);
        return success(true);
    }

    @GetMapping("/enableOrDisabled")
    @Operation(summary = "居家长者启用或者禁用")
    @TenantIgnore
    public CommonResult<Boolean> enableOrDisabled(@RequestParam("elderId") Long elderId,@RequestParam("status") Integer status){
        elderlyInfoService.enableOrDisabled(elderId,status);
        return success(true);
    }


    @PostMapping("/deleteElderlyAtHome")
    @Operation(summary = "居家长者删除")
    public CommonResult<Boolean> deleteElderlyAtHome(@RequestBody List<Long> ids){
        elderlyInfoService.deleteElderlyAtHome(ids);
        return success(true);
    }

    @GetMapping("/getElderlyAtHome")
    @Operation(summary = "居家长者详情")
    public CommonResult<ElderlyInfoDO> getElderlyAtHome(@RequestParam("elderId") Long elderId){
        return success(elderlyInfoService.getElderlyAtHome(elderId));
    }

    @PostMapping("/importKingdeeElderlyExcel")
    @Operation(summary = "导入修改长者金蝶费用编码 Excel")
    public CommonResult<Map<String,Object>> importKingdeeElderlyExcel(@RequestBody MultipartFile file) throws IOException {
        List<KingdeeElderlyExcelVO> list = ExcelUtils.read(file, KingdeeElderlyExcelVO.class);
        return success( elderlyInfoService.importKingdeeElderlyExcel(list));
    }

    @PostMapping("/importCheckIn")
    @Operation(summary = "入住办理导入")
    public CommonResult<String> importCheckIn(@RequestParam("file") MultipartFile file) throws IOException {
        List<ElderlyCheckInImportVO> list = ExcelUtils.read(file, ElderlyCheckInImportVO.class);
        return success(elderlyInfoService.importCheckIn(list));
    }

    @PostMapping("/importDeposit")
    @Operation(summary = "押金导入")
    public CommonResult<String> importDeposit(@RequestParam("file") MultipartFile file) throws IOException {
        List<ElderlyDepositImportVO> list = ExcelUtils.read(file, ElderlyDepositImportVO.class);
        return success(elderlyInfoService.importDeposit(list));
    }

    @GetMapping("/miniGetElderInfo")
    @Operation(summary = "小程序获取长者信息")
    @TenantIgnore
    @PermitAll
    public CommonResult<String> miniGetElderInfo(@RequestParam("elderName") String elderName,
                                                 @RequestParam("tenantId") Long tenantId){
        return success(elderlyInfoService.miniGetElderInfo(elderName,tenantId));
    }
}
