package thyyxxk.webserver.service.outpatient.managedoctorinfo;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.constants.Capacity;
import thyyxxk.webserver.dao.his.outpatient.DoctorManageDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.dictionary.CodeName;
import thyyxxk.webserver.entity.outpatient.mangedoctorinfo.DoctorInfo;
import thyyxxk.webserver.entity.outpatient.mangedoctorinfo.QueryParam;
import thyyxxk.webserver.utils.ResultVoUtil;
import thyyxxk.webserver.utils.TokenUtil;

import java.util.Base64;
import java.util.Base64.Encoder;
import java.util.Base64.Decoder;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author dj
 */
@Slf4j
@Service
public class ManageDoctorInfoService {
    private final DoctorManageDao dao;

    @Autowired
    public ManageDoctorInfoService(DoctorManageDao dao) {
        this.dao = dao;
    }

    public ResultVo<List<CodeName>> getAllMzDept() {
        return ResultVoUtil.success(dao.getAllMzDept());
    }

    public ResultVo<Map<String, Object>> getAllDoctors(QueryParam param) {
        IPage<DoctorInfo> iPage = new Page<>(param.getCurrentPage(), param.getPageSize());
        int manageFlag = param.getIncludeDeleted() ? 0 : 1;
        iPage = dao.getAllDoctors(iPage, param.getDeptCode(), param.getDoctorName(), manageFlag);
        Map<String, Object> map = new HashMap<>(Capacity.TWO);
        map.put("totalSize", iPage.getTotal());
        map.put("list", iPage.getRecords());
        return ResultVoUtil.success(map);
    }

    public ResultVo<List<CodeName>> getAllTitles() {
        return ResultVoUtil.success(dao.getAllTitles());
    }

    public ResultVo<DoctorInfo> getDoctorInfo(String code) {
        return ResultVoUtil.success(dao.getDoctorInfo(code));
    }

    public ResultVo<String> uploadDoctorImg(String code, MultipartFile img) {
        log.info("上传医生头像，操作员：{}，医生编码：{}", TokenUtil.getInstance().getTokenUserId(), code);
        String org = base64Encode(img);
        BufferedImage bufferedImage = base64String2BufferedImage(org);
        BufferedImage resized = shrinkImage(bufferedImage);
        String shr = imageToBase64(resized);
        dao.updatePortraitUrl(shr, code);
        return ResultVoUtil.success();
    }

    private BufferedImage shrinkImage(BufferedImage img) {
        int type = BufferedImage.SCALE_SMOOTH;
        BufferedImage resizedImage = new BufferedImage(120, 160, type);
        Graphics2D g = resizedImage.createGraphics();
        Map<RenderingHints.Key, Object> m = new HashMap<>();
        m.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        m.put(RenderingHints.KEY_ALPHA_INTERPOLATION , RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
        m.put(RenderingHints.KEY_COLOR_RENDERING , RenderingHints.VALUE_COLOR_RENDER_QUALITY);
        m.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        m.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        m.put(RenderingHints.KEY_DITHERING , RenderingHints.VALUE_DITHER_ENABLE);
        g.setRenderingHints(m);
        g.drawImage(img, 0, 0, 120, 160, null);
        g.dispose();
        return resizedImage;
    }

    private static String imageToBase64(BufferedImage bufferedImage) {
        Encoder encoder = Base64.getEncoder();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            ImageIO.write(bufferedImage, "jpg", baos);
        } catch (IOException e) {
            log.error("将医生头像转换成base64出错", e);
        }
        return new String(encoder.encode((baos.toByteArray())));
    }

    private static BufferedImage base64String2BufferedImage(String base64string) {
        BufferedImage image = null;
        try {
            InputStream stream = baseToInputStream(base64string);
            image = ImageIO.read(stream);
        } catch (IOException e) {
            log.error("base64转bufferedImage出错", e);
        }
        return image;
    }

    private static InputStream baseToInputStream(String base64string){
        ByteArrayInputStream stream = null;
        try {
            Decoder decoder = Base64.getDecoder();
            byte[] bytes1 = decoder.decode(base64string);
            stream = new ByteArrayInputStream(bytes1);
        } catch (Exception e) {
            log.error("base64转inputStream出错", e);
        }
        return stream;
    }

    public ResultVo<String> saveDoctorInfo(DoctorInfo param) {
        if (param.getSpecialty().trim().length() > Capacity.MAX_SPECIALTY_LENGTH) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "医生擅长不能超过100个字！");
        }
        if (param.getIntroduction().trim().length() > Capacity.MAX_INTRODUCTION_LENGTH) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "医生简介不能超过300个字！");
        }
        dao.saveDoctorInfo(param);
        return ResultVoUtil.success();
    }

    public ResultVo<String> updateDoctorWxHomepageFlag(String code, Integer flag) {
        dao.updateDoctorWxHomepageFlag(code, flag);
        return ResultVoUtil.success();
    }

    public ResultVo<List<DoctorInfo>> getAllRecommendDoctors() {
        return ResultVoUtil.success(dao.getAllRecommendDoctors());
    }

    public ResultVo<String> updateWxHomepageOrder(String code, Integer order) {
        dao.updateWxHomepageOrder(code, order);
        return ResultVoUtil.success();
    }

    public ResultVo<String> deleteDoctor(String code) {
        dao.deleteDoctor(code);
        return ResultVoUtil.success("已成功删除。");
    }

    public ResultVo<String> updateDoctorStatus(String code, Integer status) {
        if (status == 1) {
            dao.recoverDoctor(code);
            return ResultVoUtil.success("已成功恢复。");
        }
        dao.deleteDoctor(code);
        return ResultVoUtil.success("已成功删除。");
    }

    private String base64Encode(MultipartFile file){
        String ret = null;
        if (file == null) {
            return null;
        }
        try {
            Encoder encoder = Base64.getEncoder();
            ret = encoder.encodeToString(file.getBytes());
        } catch (IOException e) {
            log.error("将图片文件转base64出错", e);
        }
        return ret;
    }
}
