package com.example.his.api.mis.service;


import cn.hutool.core.date.DateTime;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import com.example.his.api.common.utils.FaceAuthUtil;
import com.example.his.api.common.utils.MinioUtil;
import com.example.his.api.db.dao.*;
import com.example.his.api.exception.HisException;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

@Service("MisAppointmentService")
public class AppointmentService {
    @Resource
    private AppointmentDao appointmentDao;

    @Resource
    private GoodsSnapshotDao goodsSnapshotDao;

    @Resource
    private CheckupResultDao checkupResultDao;

    @Resource
    private FaceAuthUtil faceAuthUtil;

    @Resource
    private MinioUtil minioUtil;

    @Resource
    private OrderDao orderDao;

    @Resource
    private CheckupReportDao checkupReportDao;

    // 查询订单体检预约记录
    public ArrayList<HashMap> searchAppointmentList(int orderId) {
        ArrayList<HashMap> list = appointmentDao.searchAppointmentList(orderId);
        return list;
    }

    // 体检预约-分页查询
    public PageInfo<HashMap> searchMisAppointmentByPage(Map param) {
        PageHelper.startPage(MapUtil.getInt(param, "pageNum"), MapUtil.getInt(param, "pageSize"));
        ArrayList<HashMap> list = appointmentDao.searchMisAppointmentByPage(param);
        PageInfo<HashMap> pageInfo = new PageInfo<>(list);
        return pageInfo;
    }

    // 体检预约-删除
    public int deleteAppointment(Map param) {
        return appointmentDao.deleteAppointmentById(param);
    }

    // 体检签到-判断用户当天是否预约
    public int hasAppointInToday(Map param) {
        HashMap map = appointmentDao.hasAppointInToday(param);
        if (map == null) {
            return 0; //没有预约
        } else if (MapUtil.getInt(map, "status") != 1) {
            return -1; //已经签到了
        } else {
            return 1; //有预约，未签到
        }
    }

    // 体检签到-执行人脸识别完成签到
    @Transactional
    public boolean checkin(Map param) {
        String pid = MapUtil.getStr(param, "pid");
        String name = MapUtil.getStr(param, "name");
        String sex = IdcardUtil.getGenderByIdCard(pid) == 1 ? "男" : "女";
        String photo_1 = MapUtil.getStr(param, "photo_1");
        String photo_2 = MapUtil.getStr(param, "photo_2");

        //执行人脸识别
        boolean result = faceAuthUtil.verifyFaceModel(name, pid, sex, photo_1, photo_2);
        if (result) {
            //把用户照片保存到Minio，保留体检人签到证据
            String filename = pid + "_" + new DateTime().toDateStr() + ".jpg";
            String path = "checkin/" + filename;
            minioUtil.uploadImage(path, photo_2);
            //更新体检预约状态为已签到
            int rows = appointmentDao.checkin(param);
            if (rows != 1) {
                throw new HisException("保存签到记录失败");
            }
            //查询体检流水号和订单快照ID
            HashMap map = appointmentDao.searchUuidAndSnapshotId(param);
            String uuid = MapUtil.getStr(map, "uuid");
            String snapshotId = MapUtil.getStr(map, "snapshotId");
            List<Map> checkup = goodsSnapshotDao.searchCheckup(snapshotId, sex);
            //添加体检结果记录
            boolean bool = checkupResultDao.insert(uuid, checkup);
            if (!bool) {
                throw new HisException("添加体检结果失败");
            }
        }
        return result;
    }

    // 体检签到-查询体检预约信息
    public HashMap searchGuidanceInfo(int id) {
        HashMap map = appointmentDao.searchSummaryById(id);
        String snapshotId = MapUtil.getStr(map, "snapshotId");
        String sex = MapUtil.getStr(map, "sex");
        //生成二维码图片base64字符串
        String uuid = MapUtil.getStr(map, "uuid");
        QrConfig qrConfig = new QrConfig();
        qrConfig.setWidth(100);
        qrConfig.setHeight(100);
        qrConfig.setMargin(0);
        String qrCodeBase64 = QrCodeUtil.generateAsBase64(uuid, qrConfig, "jpg");
        map.put("qrCodeBase64", qrCodeBase64);

        List<Map> list = goodsSnapshotDao.searchCheckup(snapshotId, sex);
        LinkedHashSet<Map> set = new LinkedHashSet();
        list.forEach(one -> {
            HashMap temp = new HashMap() {{
                put("place", MapUtil.getStr(one, "place"));
                put("name", MapUtil.getStr(one, "name"));
            }};
            set.add(temp);
        });
        map.put("checkup", set);
        return map;
    }

    // 体检签到-查询体检预约信息
    @Transactional
    public boolean updateStatusByUuid(Map param) {
        int rows = appointmentDao.updateStatusByUuid(param);
        if (rows != 1) {
            return false;
        }
        int status = MapUtil.getInt(param, "status");
        if (status == 3) {
            //检查对应的订单是否所有体检预约都已经结束
            String uuid = MapUtil.getStr(param, "uuid");
            HashMap map = orderDao.searchOrderIsFinished(uuid);
            int orderId = MapUtil.getInt(map, "id");
            int n1 = MapUtil.getInt(map, "n1");
            int n2 = MapUtil.getInt(map, "n2");
            if (n1 == n2) {
                //更新订单为已结束状态
                rows = orderDao.updateAppointmentStatus(new HashMap<>() {{
                    put("status", 6);
                    put("id", orderId);
                }});
                if (rows != 1) {
                    return false;
                }
            }
            //查询体检结果ID
            String resultId = checkupResultDao.searchIdByUuid(uuid);
            param.put("resultId", resultId);
            rows = checkupReportDao.insert(param);
            if (rows != 1) {
                return false;
            }
        }
        return true;
    }

    // 医生体检-查询体检人信息
    public HashMap searchByUuid(String uuid) {
        HashMap map = appointmentDao.searchByUuid(uuid);
        if (map == null) {
            throw new HisException("不存在体检预约记录");
        }
        Integer status = MapUtil.getInt(map, "status");
        if (status == 1) {
            throw new HisException("该体检没有签到");
        } else if (status == 3) {
            throw new HisException("该体检预约已经结束");
        }
        return map;
    }
}
