package com.aiotagro.cattletrade.business.service.impl;

import com.aiotagro.cattletrade.business.dto.SlaughterRecordCreateDto;
import com.aiotagro.cattletrade.business.dto.SlaughterRecordDto;
import com.aiotagro.cattletrade.business.dto.SlaughterRecordEditDto;
import com.aiotagro.cattletrade.business.entity.SlaughterEntry;
import com.aiotagro.cattletrade.business.entity.SlaughterHouse;
import com.aiotagro.cattletrade.business.entity.SlaughterRecord;
import com.aiotagro.cattletrade.business.mapper.SlaughterEntryMapper;
import com.aiotagro.cattletrade.business.mapper.SlaughterHouseMapper;
import com.aiotagro.cattletrade.business.mapper.SlaughterRecordMapper;
import com.aiotagro.cattletrade.business.service.ISlaughterRecordService;
import com.aiotagro.common.core.utils.SecurityUtil;
import com.aiotagro.common.core.utils.bean.BeanUtils;
import com.aiotagro.common.core.web.domain.AjaxResult;
import com.aiotagro.common.core.web.domain.PageResultResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 屠宰记录服务实现
 *
 * @author System
 * @date 2025-12-10
 */
@Service
public class SlaughterRecordServiceImpl extends ServiceImpl<SlaughterRecordMapper, SlaughterRecord> implements ISlaughterRecordService {

    @Autowired
    private SlaughterRecordMapper slaughterRecordMapper;
    @Autowired
    private SlaughterEntryMapper slaughterEntryMapper;
    @Autowired
    private SlaughterHouseMapper slaughterHouseMapper;

    @Override
    public PageResultResponse<SlaughterRecord> pageQuery(SlaughterRecordDto dto) {
        Integer pageNum = dto.getPageNum() != null ? dto.getPageNum() : 1;
        Integer pageSize = dto.getPageSize() != null ? dto.getPageSize() : 10;

        Page<SlaughterRecord> page = PageHelper.startPage(pageNum, pageSize);

        LambdaQueryWrapper<SlaughterRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.and(q -> q.eq(SlaughterRecord::getIsDelete, 0).or().isNull(SlaughterRecord::getIsDelete));

        if (StringUtils.hasText(dto.getRecordCode())) {
            wrapper.like(SlaughterRecord::getRecordCode, dto.getRecordCode().trim());
        }
        if (dto.getEntryId() != null) {
            wrapper.eq(SlaughterRecord::getEntryId, dto.getEntryId());
        }

        // 按进场编码模糊查询
        if (StringUtils.hasText(dto.getEntryCode())) {
            List<SlaughterEntry> matchedEntries = slaughterEntryMapper.selectList(new LambdaQueryWrapper<SlaughterEntry>()
                    .like(SlaughterEntry::getEntryCode, dto.getEntryCode().trim())
                    .and(q -> q.eq(SlaughterEntry::getIsDelete, 0).or().isNull(SlaughterEntry::getIsDelete)));
            if (CollectionUtils.isEmpty(matchedEntries)) {
                wrapper.eq(SlaughterRecord::getId, -1);
            } else {
                Set<Integer> entryIds = matchedEntries.stream().map(SlaughterEntry::getId).collect(Collectors.toSet());
                wrapper.in(SlaughterRecord::getEntryId, entryIds);
            }
        }

        // 按屠宰场过滤
        if (dto.getSlaughterHouseId() != null) {
            List<SlaughterEntry> matchedEntries = slaughterEntryMapper.selectList(new LambdaQueryWrapper<SlaughterEntry>()
                    .eq(SlaughterEntry::getSlaughterHouseId, dto.getSlaughterHouseId())
                    .and(q -> q.eq(SlaughterEntry::getIsDelete, 0).or().isNull(SlaughterEntry::getIsDelete)));
            if (CollectionUtils.isEmpty(matchedEntries)) {
                wrapper.eq(SlaughterRecord::getId, -1);
            } else {
                Set<Integer> entryIds = matchedEntries.stream().map(SlaughterEntry::getId).collect(Collectors.toSet());
                wrapper.in(SlaughterRecord::getEntryId, entryIds);
            }
        }

        wrapper.orderByDesc(SlaughterRecord::getCreateTime);

        List<SlaughterRecord> list = slaughterRecordMapper.selectList(wrapper);
        fillRelatedInfo(list);

        return new PageResultResponse<>(page.getTotal(), list);
    }

    @Override
    @Transactional
    public AjaxResult addRecord(SlaughterRecordCreateDto dto) {
        String yieldCheck = validateYieldRate(dto.getYieldRate());
        if (yieldCheck != null) {
            return AjaxResult.error(yieldCheck);
        }

        SlaughterEntry entry = loadEntry(dto.getEntryId());
        if (entry == null) {
            return AjaxResult.error("进场记录不存在");
        }

        int remaining = entry.getRemainingCapacity() == null ? 0 : entry.getRemainingCapacity();
        if (dto.getSlaughterCount() > remaining) {
            return AjaxResult.error("屠宰头数不能超过进场剩余头数，当前剩余：" + remaining);
        }

        SlaughterRecord record = new SlaughterRecord();
        BeanUtils.copyProperties(dto, record);

        if (!StringUtils.hasText(record.getRecordCode())) {
            record.setRecordCode(generateRecordCode());
        }

        Integer userId = SecurityUtil.getCurrentUserId();
        Date now = new Date();

        record.setCreatedBy(userId);
        record.setCreateTime(now);
        record.setIsDelete(0);

        int inserted = slaughterRecordMapper.insert(record);
        if (inserted <= 0) {
            return AjaxResult.error("新增屠宰记录失败");
        }

        // 扣减剩余头数
        if (!updateRemainingCapacity(entry.getId(), -dto.getSlaughterCount(), userId, now)) {
            throw new RuntimeException("扣减进场剩余头数失败");
        }

        return AjaxResult.success("新增屠宰记录成功");
    }

    @Override
    @Transactional
    public AjaxResult updateRecord(SlaughterRecordEditDto dto) {
        String yieldCheck = validateYieldRate(dto.getYieldRate());
        if (yieldCheck != null) {
            return AjaxResult.error(yieldCheck);
        }

        SlaughterRecord existing = slaughterRecordMapper.selectById(dto.getId());
        if (existing == null || (existing.getIsDelete() != null && existing.getIsDelete() == 1)) {
            return AjaxResult.error("屠宰记录不存在");
        }

        if (!Objects.equals(existing.getEntryId(), dto.getEntryId())) {
            return AjaxResult.error("暂不支持变更进场记录，请删除后重新新增");
        }

        SlaughterEntry entry = loadEntry(existing.getEntryId());
        if (entry == null) {
            return AjaxResult.error("进场记录不存在");
        }

        int remaining = entry.getRemainingCapacity() == null ? 0 : entry.getRemainingCapacity();
        int available = remaining + (existing.getSlaughterCount() == null ? 0 : existing.getSlaughterCount());
        if (dto.getSlaughterCount() > available) {
            return AjaxResult.error("屠宰头数不能超过进场剩余头数，当前可用：" + available);
        }

        SlaughterRecord record = new SlaughterRecord();
        BeanUtils.copyProperties(dto, record);

        if (!StringUtils.hasText(record.getRecordCode())) {
            record.setRecordCode(existing.getRecordCode());
        }

        Integer userId = SecurityUtil.getCurrentUserId();
        Date now = new Date();

        record.setUpdatedBy(userId);
        record.setUpdateTime(now);
        record.setIsDelete(0);

        int updated = slaughterRecordMapper.updateById(record);
        if (updated <= 0) {
            return AjaxResult.error("更新屠宰记录失败");
        }

        int adjust = (existing.getSlaughterCount() == null ? 0 : existing.getSlaughterCount()) - dto.getSlaughterCount();
        if (adjust != 0 && !updateRemainingCapacity(entry.getId(), adjust, userId, now)) {
            throw new RuntimeException("调整进场剩余头数失败");
        }

        return AjaxResult.success("更新屠宰记录成功");
    }

    @Override
    @Transactional
    public AjaxResult deleteRecord(Integer id) {
        if (id == null) {
            return AjaxResult.error("屠宰记录ID不能为空");
        }

        SlaughterRecord existing = slaughterRecordMapper.selectById(id);
        if (existing == null || (existing.getIsDelete() != null && existing.getIsDelete() == 1)) {
            return AjaxResult.error("屠宰记录不存在");
        }

        Integer userId = SecurityUtil.getCurrentUserId();
        Date now = new Date();

        UpdateWrapper<SlaughterRecord> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", id)
                .eq("is_delete", 0)
                .set("is_delete", 1)
                .set("updated_by", userId)
                .set("update_time", now);

        int result = slaughterRecordMapper.update(null, wrapper);
        if (result <= 0) {
            return AjaxResult.error("删除屠宰记录失败");
        }

        int recover = existing.getSlaughterCount() == null ? 0 : existing.getSlaughterCount();
        if (recover > 0 && !updateRemainingCapacity(existing.getEntryId(), recover, userId, now)) {
            throw new RuntimeException("回补进场剩余头数失败");
        }

        return AjaxResult.success("删除屠宰记录成功");
    }

    @Override
    public AjaxResult detail(Integer id) {
        if (id == null) {
            return AjaxResult.error("屠宰记录ID不能为空");
        }
        SlaughterRecord record = slaughterRecordMapper.selectById(id);
        if (record == null || (record.getIsDelete() != null && record.getIsDelete() == 1)) {
            return AjaxResult.error("屠宰记录不存在");
        }
        fillRelatedInfo(record);
        return AjaxResult.success("查询成功", record);
    }

    /**
     * 填充关联信息
     */
    private void fillRelatedInfo(List<SlaughterRecord> list) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        Set<Integer> entryIds = list.stream()
                .map(SlaughterRecord::getEntryId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        if (CollectionUtils.isEmpty(entryIds)) {
            return;
        }

        List<SlaughterEntry> entries = slaughterEntryMapper.selectBatchIds(entryIds);
        Map<Integer, SlaughterEntry> entryMap = entries.stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toMap(SlaughterEntry::getId, e -> e));

        Set<Integer> houseIds = entries.stream()
                .map(SlaughterEntry::getSlaughterHouseId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        Map<Integer, SlaughterHouse> houseMap = new java.util.HashMap<>();
        if (!CollectionUtils.isEmpty(houseIds)) {
            houseMap = slaughterHouseMapper.selectBatchIds(houseIds).stream()
                    .filter(Objects::nonNull)
                    .collect(Collectors.toMap(SlaughterHouse::getId, h -> h));
        }

        for (SlaughterRecord record : list) {
            SlaughterEntry entry = entryMap.get(record.getEntryId());
            if (entry != null) {
                record.setEntryCode(entry.getEntryCode());
                record.setSlaughterHouseId(entry.getSlaughterHouseId());
                record.setRemainingCapacity(entry.getRemainingCapacity());

                SlaughterHouse house = houseMap.get(entry.getSlaughterHouseId());
                if (house != null) {
                    record.setSlaughterHouseName(house.getHouseName());
                }
            }
        }
    }

    private void fillRelatedInfo(SlaughterRecord record) {
        if (record == null) {
            return;
        }
        fillRelatedInfo(Collections.singletonList(record));
    }

    private SlaughterEntry loadEntry(Integer entryId) {
        if (entryId == null) {
            return null;
        }
        SlaughterEntry entry = slaughterEntryMapper.selectById(entryId);
        if (entry == null || (entry.getIsDelete() != null && entry.getIsDelete() == 1)) {
            return null;
        }
        return entry;
    }

    /**
     * 更新进场剩余头数（delta为正表示回补，为负表示扣减）
     */
    private boolean updateRemainingCapacity(Integer entryId, int delta, Integer userId, Date now) {
        if (delta == 0) {
            return true;
        }
        UpdateWrapper<SlaughterEntry> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", entryId)
                .eq("is_delete", 0)
                .set("updated_by", userId)
                .set("update_time", now);

        if (delta < 0) {
            int decrease = Math.abs(delta);
            wrapper.ge("remaining_capacity", decrease)
                    .setSql("remaining_capacity = remaining_capacity - " + decrease);
        } else {
            wrapper.setSql("remaining_capacity = remaining_capacity + " + delta);
        }

        int updated = slaughterEntryMapper.update(null, wrapper);
        return updated > 0;
    }

    /**
     * 校验出肉率范围
     */
    private String validateYieldRate(BigDecimal yieldRate) {
        if (yieldRate == null) {
            return null;
        }
        if (yieldRate.compareTo(BigDecimal.ZERO) < 0 || yieldRate.compareTo(new BigDecimal("100")) > 0) {
            return "出肉率需在0-100之间";
        }
        return null;
    }

    /**
     * 生成屠宰记录编码：SL + yyyyMMdd + 3位流水
     */
    private String generateRecordCode() {
        String dateStr = new SimpleDateFormat("yyyyMMdd").format(new Date());
        String prefix = "SL" + dateStr;
        SlaughterRecord last = slaughterRecordMapper.selectLastCode(prefix + "%");
        int next = 1;
        if (last != null && StringUtils.hasText(last.getRecordCode())) {
            String lastCode = last.getRecordCode();
            if (lastCode.startsWith(prefix)) {
                String seq = lastCode.substring(prefix.length());
                try {
                    next = Integer.parseInt(seq) + 1;
                } catch (NumberFormatException ignored) {
                    next = 1;
                }
            }
        }
        return String.format("%s%03d", prefix, next);
    }
}


