package com.fuyuanshen.equipment.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fuyuanshen.common.core.utils.MapstructUtils;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fuyuanshen.common.satoken.utils.LoginHelper;
import com.fuyuanshen.equipment.domain.Device;
import com.fuyuanshen.equipment.domain.DeviceRepairImages;
import com.fuyuanshen.equipment.domain.DeviceType;
import com.fuyuanshen.equipment.domain.query.DeviceRepairRecordsQueryCriteria;
import com.fuyuanshen.equipment.domain.vo.DeviceRepairImagesVo;
import com.fuyuanshen.equipment.enums.RepairImageType;
import com.fuyuanshen.equipment.mapper.DeviceMapper;
import com.fuyuanshen.equipment.mapper.DeviceRepairImagesMapper;
import com.fuyuanshen.equipment.utils.FileHashUtil;
import com.fuyuanshen.system.domain.vo.SysOssVo;
import com.fuyuanshen.system.service.ISysOssService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import com.fuyuanshen.equipment.domain.bo.DeviceRepairRecordsBo;
import com.fuyuanshen.equipment.domain.vo.DeviceRepairRecordsVo;
import com.fuyuanshen.equipment.domain.DeviceRepairRecords;
import com.fuyuanshen.equipment.mapper.DeviceRepairRecordsMapper;
import com.fuyuanshen.equipment.service.IDeviceRepairRecordsService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;

/**
 * 设备维修记录Service业务层处理
 *
 * @author Lion Li
 * @date 2025-08-08
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class DeviceRepairRecordsServiceImpl extends ServiceImpl<DeviceRepairRecordsMapper, DeviceRepairRecords> implements IDeviceRepairRecordsService {

    private final DeviceRepairRecordsMapper baseMapper;
    private final DeviceRepairImagesMapper imagesMapper;
    private final ISysOssService ossService;
    private final FileHashUtil fileHashUtil;

    /**
     * 查询设备维修记录
     *
     * @param recordId 主键
     * @return 设备维修记录
     */
    @Override
    public DeviceRepairRecordsVo queryById(Long recordId){
        // 1. 主表
        DeviceRepairRecordsVo vo = baseMapper.selectVoById(recordId);
        if (vo == null) {
            throw new RuntimeException("维修记录不存在");
        }

        // 2. 子表图片
        List<DeviceRepairImagesVo> images = imagesMapper.selectVoList(
                new LambdaQueryWrapper<DeviceRepairImages>()
                        .eq(DeviceRepairImages::getRecordId, recordId)
                        .orderByAsc(DeviceRepairImages::getImageType)); // 如有排序需求
        // 3. 组装到 VO
        vo.setImages(images);   // 需要在 DeviceRepairRecordsVo 里加该字段
        return vo;
    }

    /**
     * 分页查询设备维修记录列表
     *
     * @param criteria        查询条件
     * @param page 分页参数
     * @return 设备维修记录分页列表
     */
    @Override
    public TableDataInfo<DeviceRepairRecordsVo> queryPageList(DeviceRepairRecordsQueryCriteria criteria, Page<DeviceRepairRecords> page) {
        // 管理员
        String username = LoginHelper.getUsername();
        if (!username.equals("admin")) {
            criteria.setCustomerId(LoginHelper.getUserId());
        }

        if(criteria.getRepairEndTime() !=null ){
            criteria.setRepairEndTime(DateUtil.endOfDay(criteria.getRepairEndTime()));
        }
        IPage<DeviceRepairRecordsVo> deviceRepairRecordsIPage = baseMapper.findAll(criteria, page);
        return new TableDataInfo<DeviceRepairRecordsVo>(deviceRepairRecordsIPage.getRecords(), deviceRepairRecordsIPage.getTotal());
    }

    /**
     * 查询符合条件的设备维修记录列表
     *
     * @param criteria 查询条件
     * @return 设备维修记录列表
     */
    @Override
    public List<DeviceRepairRecordsVo> queryList(DeviceRepairRecordsQueryCriteria criteria) {
        return baseMapper.findAll(criteria);
    }

    private LambdaQueryWrapper<DeviceRepairRecords> buildQueryWrapper(DeviceRepairRecordsBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<DeviceRepairRecords> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(DeviceRepairRecords::getRecordId);
        lqw.eq(StringUtils.isNotBlank(bo.getDeviceId()), DeviceRepairRecords::getDeviceId, bo.getDeviceId());
        lqw.eq(bo.getRepairTime() != null, DeviceRepairRecords::getRepairTime, bo.getRepairTime());
        lqw.eq(StringUtils.isNotBlank(bo.getRepairPart()), DeviceRepairRecords::getRepairPart, bo.getRepairPart());
        lqw.eq(StringUtils.isNotBlank(bo.getRepairReason()), DeviceRepairRecords::getRepairReason, bo.getRepairReason());
        lqw.eq(StringUtils.isNotBlank(bo.getRepairPerson()), DeviceRepairRecords::getRepairPerson, bo.getRepairPerson());
        return lqw;
    }

    /**
     * 新增设备维修记录
     *
     * @param bo 设备维修记录
     * @return 是否新增成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(DeviceRepairRecordsBo bo) {
        // 1. 保存主表
        DeviceRepairRecords entity = MapstructUtils.convert(bo, DeviceRepairRecords.class);
        validEntityBeforeSave(entity);
        boolean ok = baseMapper.insert(entity) > 0;
        if (!ok) {
            return false;
        }

        // 2. 回填主键
        Long recordId = entity.getRecordId();
        bo.setRecordId(recordId);

        // 3. 组装图片实体
        List<DeviceRepairImages> images = new ArrayList<>(2);
        addImageIfPresent(images, recordId, bo.getBeforeFile(), RepairImageType.BEFORE);
        addImageIfPresent(images, recordId, bo.getAfterFile(),  RepairImageType.AFTER);

        // 4. 批量插入
        if (!images.isEmpty()) {
            imagesMapper.insertBatch(images);
        }
        return true;
    }

    /**
     * 修改设备维修记录
     *
     * @param bo 设备维修记录
     * @return 是否修改成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(DeviceRepairRecordsBo bo) {
        Long recordId = bo.getRecordId();

        // 1. 校验记录是否存在
        DeviceRepairRecords dbRecord = baseMapper.selectById(recordId);
        if (dbRecord == null) {
            throw new RuntimeException("维修记录不存在");
        }

        // 2. 更新主表
        DeviceRepairRecords entity = MapstructUtils.convert(bo, DeviceRepairRecords.class);
        validEntityBeforeSave(entity);
        if (!StringUtils.isNotEmpty(entity.getDeviceId())){
            throw new RuntimeException("维修记录不能为空！！！");
        }
        boolean updated = baseMapper.updateById(entity) > 0;
        if (!updated) {
            return false;
        }
        // 3. 删除旧图片
        if(bo.getImageIds() != null){
            imagesMapper.deleteByIds(bo.getImageIds());
        }

        // 3. 收集需要保存的图片
        List<DeviceRepairImages> images = new ArrayList<>(2);
        addImageIfPresent(images, recordId, bo.getBeforeFile(), RepairImageType.BEFORE);
        addImageIfPresent(images, recordId, bo.getAfterFile(), RepairImageType.AFTER);

        // 4. 批量插入
        if (!images.isEmpty()) {
            imagesMapper.insertBatch(images);
        }
        return true;
    }

    /* ---------- 工具方法 ---------- */

    private void addImageIfPresent(List<DeviceRepairImages> list,
                                   Long recordId,
                                   MultipartFile file,
                                   RepairImageType imageType) {
        if (file == null || file.isEmpty()) {
            return;
        }

        // 1. 计算文件哈希
        String hash = null;
        try {
            hash = fileHashUtil.hash(file);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        // 2. 先根据 hash 查库（秒传）
        SysOssVo exist = ossService.updateHash(file,hash);

        DeviceRepairImages image = new DeviceRepairImages();
        image.setRecordId(recordId);
        image.setImageType(imageType);
        image.setImageUrl(exist.getUrl());

        list.add(image);
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(DeviceRepairRecords entity){
        //TODO 做一些数据校验,如唯一约束
        if (!StringUtils.isNotEmpty(entity.getDeviceId())){
            throw new RuntimeException("维修设备不能为空！！！");
        }
    }

    /**
     * 校验并批量删除设备维修记录信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }
}
