package com.jeesharp.business.modules.food.application;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.jeesharp.business.modules.food.dto.FoodCompanyJoinApplyAuditDTO;
import com.jeesharp.business.modules.food.dto.FoodCompanyJoinApplyCreateDTO;
import com.jeesharp.business.modules.food.entity.FoodCompany;
import com.jeesharp.business.modules.food.entity.FoodCompanyEmployee;
import com.jeesharp.business.modules.food.entity.FoodCompanyJoinApply;
import com.jeesharp.business.modules.food.service.FoodCompanyEmployeeService;
import com.jeesharp.business.modules.food.service.FoodCompanyJoinApplyService;
import com.jeesharp.business.modules.food.service.FoodCompanyService;
import com.jeesharp.business.modules.food.vo.FoodCompanyJoinApplyQueryVO;
import com.jeesharp.business.modules.food.vo.FoodCompanyJoinApplyVO;
import com.jeesharp.business.modules.food.vo.FoodCompanySearchVO;
import com.jeesharp.framework.exception.BizErrorException;
import com.jeesharp.framework.pojo.Page;
import com.jeesharp.framework.pojo.query.PageRespVO;
import com.jeesharp.framework.utils.WebFrameworkUtils;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
@Transactional(readOnly = true)
public class FoodCompanyJoinApplicationService {

    private static final String STATUS_PENDING = "pending";
    private static final String STATUS_APPROVED = "approved";
    private static final String STATUS_REJECTED = "rejected";
    private static final int EMPLOYEE_STATUS_ENABLED = 1;
    private static final int EMPLOYEE_BIND_STATUS_BOUND = 1;
    private static final String SOURCE_MINI = "MINI";

    private final FoodCompanyService foodCompanyService;
    private final FoodCompanyEmployeeService foodCompanyEmployeeService;
    private final FoodCompanyJoinApplyService foodCompanyJoinApplyService;

    public List<FoodCompanySearchVO> searchCompanies(String keyword) {
        return foodCompanyService.searchEnabledCompanies(keyword, 20).stream().map(this::toSearchVO).collect(Collectors.toList());
    }

    @Transactional(readOnly = false)
    public FoodCompanyJoinApplyVO submitApply(FoodCompanyJoinApplyCreateDTO dto) {
        if (StrUtil.isBlank(dto.getMemberId())) {
            throw new BizErrorException("会员ID不能为空");
        }
        FoodCompany company = foodCompanyService.getEnabledCompany(dto.getCompanyId());
        if (company == null) {
            throw new BizErrorException("企业不存在或已停用");
        }
        FoodCompanyEmployee bound = foodCompanyEmployeeService.getBoundEmployee(company.getId(), dto.getMemberId());
        if (bound != null) {
            throw new BizErrorException("您已加入该企业");
        }
        if (foodCompanyJoinApplyService.getPendingApply(company.getId(), dto.getMemberId()) != null) {
            throw new BizErrorException("已有待审核申请，请勿重复提交");
        }
        FoodCompanyJoinApply apply = new FoodCompanyJoinApply();
        apply.setId(IdUtil.getSnowflakeNextIdStr());
        apply.setCompanyId(company.getId());
        apply.setCompanyCode(company.getCompanyCode());
        apply.setCompanyName(company.getCompanyName());
        apply.setMemberId(dto.getMemberId());
        apply.setMemberNo(dto.getMemberNo());
        apply.setEmployeeName(dto.getEmployeeName().trim());
        apply.setMobile(dto.getMobile().trim());
        apply.setEmployeeNo(StrUtil.trim(dto.getEmployeeNo()));
        apply.setApplyReason(StrUtil.trim(dto.getApplyReason()));
        apply.setApplyTime(LocalDateTime.now());
        apply.setStatus(STATUS_PENDING);
        foodCompanyJoinApplyService.save(apply);
        return toApplyVO(apply);
    }

    public List<FoodCompanyJoinApplyVO> listMyApplications(String memberId) {
        return foodCompanyJoinApplyService.listByMemberId(memberId).stream().map(this::toApplyVO).collect(Collectors.toList());
    }

    public PageRespVO<FoodCompanyJoinApplyVO> findPage(Page<FoodCompanyJoinApply> page, FoodCompanyJoinApplyQueryVO query) {
        Page<FoodCompanyJoinApply> result = foodCompanyJoinApplyService.findPage(page, query);
        PageRespVO<FoodCompanyJoinApplyVO> resp = new PageRespVO<>();
        resp.setTotal(result.getTotal());
        resp.setPageNo(result.getPageNo());
        resp.setPageSize(result.getPageSize());
        resp.setRecords(result.getRecords().stream().map(this::toApplyVO).collect(Collectors.toList()));
        return resp;
    }

    public FoodCompanyJoinApplyVO get(String id) {
        return toApplyVO(foodCompanyJoinApplyService.get(id));
    }

    @Transactional(readOnly = false)
    public void approve(FoodCompanyJoinApplyAuditDTO dto) {
        FoodCompanyJoinApply apply = requirePendingApply(dto.getId());
        FoodCompany company = foodCompanyService.getEnabledCompany(apply.getCompanyId());
        if (company == null) {
            throw new BizErrorException("企业不存在或已停用");
        }
        FoodCompanyEmployee saved = foodCompanyEmployeeService.getBoundEmployee(apply.getCompanyId(), apply.getMemberId());
        if (saved == null) {
            FoodCompanyEmployee employee = new FoodCompanyEmployee();
            employee.setCompanyId(apply.getCompanyId());
            employee.setMemberId(apply.getMemberId());
            employee.setMemberNo(apply.getMemberNo());
            employee.setEmployeeNo(apply.getEmployeeNo());
            employee.setEmployeeName(apply.getEmployeeName());
            employee.setMobile(apply.getMobile());
            employee.setStatus(EMPLOYEE_STATUS_ENABLED);
            employee.setBindStatus(EMPLOYEE_BIND_STATUS_BOUND);
            employee.setBindTime(LocalDateTime.now());
            employee.setUnbindTime(null);
            employee.setSource(SOURCE_MINI);
            saved = foodCompanyEmployeeService.saveOrBindEmployee(employee);
        }
        apply.setEmployeeId(saved.getId());
        apply.setStatus(STATUS_APPROVED);
        apply.setAuditUserId(WebFrameworkUtils.getLoginUserId());
        apply.setAuditUserName(WebFrameworkUtils.getLoginUserName());
        apply.setAuditTime(LocalDateTime.now());
        apply.setAuditRemark(StrUtil.trim(dto.getAuditRemark()));
        foodCompanyJoinApplyService.update(apply);
    }

    @Transactional(readOnly = false)
    public void reject(FoodCompanyJoinApplyAuditDTO dto) {
        FoodCompanyJoinApply apply = requirePendingApply(dto.getId());
        apply.setStatus(STATUS_REJECTED);
        apply.setAuditUserId(WebFrameworkUtils.getLoginUserId());
        apply.setAuditUserName(WebFrameworkUtils.getLoginUserName());
        apply.setAuditTime(LocalDateTime.now());
        apply.setAuditRemark(StrUtil.trim(dto.getAuditRemark()));
        foodCompanyJoinApplyService.update(apply);
    }

    @Transactional(readOnly = false)
    public void delete(String ids) {
        foodCompanyJoinApplyService.batchDelete(StrUtil.splitTrim(ids, ','));
    }

    private FoodCompanyJoinApply requirePendingApply(String id) {
        FoodCompanyJoinApply apply = foodCompanyJoinApplyService.get(id);
        if (apply == null) {
            throw new BizErrorException("申请记录不存在");
        }
        if (!STATUS_PENDING.equals(apply.getStatus())) {
            throw new BizErrorException("申请记录不是待审核状态");
        }
        return apply;
    }

    private FoodCompanySearchVO toSearchVO(FoodCompany company) {
        FoodCompanySearchVO vo = new FoodCompanySearchVO();
        vo.setId(company.getId());
        vo.setCompanyId(company.getId());
        vo.setCompanyCode(company.getCompanyCode());
        vo.setCompanyName(company.getCompanyName());
        vo.setContactName(company.getContactName());
        vo.setContactPhone(company.getContactPhone());
        vo.setStatus(company.getStatus());
        return vo;
    }

    private FoodCompanyJoinApplyVO toApplyVO(FoodCompanyJoinApply apply) {
        if (apply == null) {
            return null;
        }
        FoodCompanyJoinApplyVO vo = new FoodCompanyJoinApplyVO();
        vo.setId(apply.getId());
        vo.setCreateDate(apply.getCreateDate());
        vo.setCompanyId(apply.getCompanyId());
        vo.setCompanyCode(apply.getCompanyCode());
        vo.setCompanyName(apply.getCompanyName());
        vo.setMemberId(apply.getMemberId());
        vo.setMemberNo(apply.getMemberNo());
        vo.setEmployeeId(apply.getEmployeeId());
        vo.setEmployeeNo(apply.getEmployeeNo());
        vo.setEmployeeName(apply.getEmployeeName());
        vo.setMobile(apply.getMobile());
        vo.setApplyReason(apply.getApplyReason());
        vo.setApplyTime(apply.getApplyTime());
        vo.setStatus(apply.getStatus());
        vo.setAuditUserId(apply.getAuditUserId());
        vo.setAuditUserName(apply.getAuditUserName());
        vo.setAuditTime(apply.getAuditTime());
        vo.setAuditRemark(apply.getAuditRemark());
        return vo;
    }
}
