package com.gxwebsoft.credit.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.common.core.exception.BusinessException;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.credit.mapper.CreditMpCustomerMapper;
import com.gxwebsoft.credit.service.CreditMpCustomerService;
import com.gxwebsoft.credit.entity.CreditMpCustomer;
import com.gxwebsoft.credit.param.CreditMpCustomerParam;
import com.gxwebsoft.credit.param.BatchFollowStepApprovalDTO;
import com.gxwebsoft.credit.param.EndFollowProcessDTO;
import com.gxwebsoft.credit.param.FollowStepApprovalDTO;
import com.gxwebsoft.credit.param.FollowStepQueryDTO;
import com.gxwebsoft.credit.vo.FollowStatisticsDTO;
import com.gxwebsoft.credit.vo.FollowStepDetailDTO;
import com.gxwebsoft.credit.vo.PendingApprovalStepVO;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * 小程序端客户Service实现
 *
 * @author 科技小王子
 * @since 2026-03-16 20:59:17
 */
@Service
public class CreditMpCustomerServiceImpl extends ServiceImpl<CreditMpCustomerMapper, CreditMpCustomer> implements CreditMpCustomerService {

    private final BaseController baseController = new BaseController();

    @Override
    public PageResult<CreditMpCustomer> pageRel(CreditMpCustomerParam param) {
        PageParam<CreditMpCustomer, CreditMpCustomerParam> page = new PageParam<>(param);
        page.setDefaultOrder("sort_number asc, create_time desc");
        List<CreditMpCustomer> list = baseMapper.selectPageRel(page, param);
        return new PageResult<>(list, page.getTotal());
    }

    @Override
    public List<CreditMpCustomer> listRel(CreditMpCustomerParam param) {
        List<CreditMpCustomer> list = baseMapper.selectListRel(param);
        // 排序
        PageParam<CreditMpCustomer, CreditMpCustomerParam> page = new PageParam<>();
        page.setDefaultOrder("sort_number asc, create_time desc");
        return page.sortRecords(list);
    }

    @Override
    public CreditMpCustomer getByIdRel(Integer id) {
        CreditMpCustomerParam param = new CreditMpCustomerParam();
        param.setId(id);
        return param.getOne(baseMapper.selectListRel(param));
    }

    @Override
    @Transactional
    public void approveFollowStep(FollowStepApprovalDTO dto) {
        CreditMpCustomer customer = getById(dto.getCustomerId());
        if (customer == null) {
            throw new BusinessException("客户不存在");
        }
        
        // 验证步骤是否已提交
        if (!isStepSubmitted(customer, dto.getStep())) {
            throw new BusinessException("该步骤尚未提交，无法审核");
        }
        
        // 更新审核状态
        updateStepApproval(customer, dto);
        
        // 如果审核通过，更新客户步骤状态
        if (dto.getApproved()) {
            updateCustomerStep(customer, dto.getStep());
        }
    }

    @Override
    @Transactional
    public void batchApproveFollowSteps(BatchFollowStepApprovalDTO dto) {
        for (FollowStepApprovalDTO approval : dto.getApprovals()) {
            approveFollowStep(approval);
        }
    }

    @Override
    public List<PendingApprovalStepVO> getPendingApprovalSteps(FollowStepQueryDTO query) {
        return baseMapper.selectPendingApprovalSteps(query);
    }

    @Override
    public FollowStatisticsDTO getFollowStatistics(Long customerId) {
        CreditMpCustomer customer = getById(customerId);
        if (customer == null) {
            throw new BusinessException("客户不存在");
        }
        
        FollowStatisticsDTO statistics = new FollowStatisticsDTO();
        statistics.setTotalSteps(7);
        
        List<FollowStepDetailDTO> stepDetails = new ArrayList<>();
        int completedSteps = 0;
        int currentStep = 1;
        
        for (int i = 1; i <= 7; i++) {
            FollowStepDetailDTO detail = getStepDetail(customer, i);
            stepDetails.add(detail);
            
            if ("approved".equals(detail.getStatus())) {
                completedSteps++;
                currentStep = i + 1;
            } else if ("submitted".equals(detail.getStatus()) && currentStep == 1) {
                currentStep = i;
            }
        }
        
        statistics.setCompletedSteps(completedSteps);
        statistics.setCurrentStep(Math.min(currentStep, 7));
        statistics.setProgress((double) completedSteps / 7 * 100);
        statistics.setStepDetails(stepDetails);
        
        return statistics;
    }

    @Override
    @Transactional
    public void endFollowProcess(EndFollowProcessDTO dto) {
        CreditMpCustomer customer = getById(dto.getCustomerId());
        if (customer == null) {
            throw new BusinessException("客户不存在");
        }
        
        customer.setFollowProcessEnded(1);
        customer.setFollowProcessEndTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        customer.setFollowProcessEndReason(dto.getReason());
        
        updateById(customer);
    }

    // 私有辅助方法
    private boolean isStepSubmitted(CreditMpCustomer customer, Integer step) {
        switch (step) {
            case 1: return customer.getFollowStep1Submitted() != null && customer.getFollowStep1Submitted() == 1;
            case 2: return customer.getFollowStep2Submitted() != null && customer.getFollowStep2Submitted() == 1;
            case 3: return customer.getFollowStep3Submitted() != null && customer.getFollowStep3Submitted() == 1;
            case 4: return customer.getFollowStep4Submitted() != null && customer.getFollowStep4Submitted() == 1;
            case 5: return customer.getFollowStep5Submitted() != null && customer.getFollowStep5Submitted() == 1;
            case 6: return customer.getFollowStep6Submitted() != null && customer.getFollowStep6Submitted() == 1;
            case 7: return customer.getFollowStep7Submitted() != null && customer.getFollowStep7Submitted() == 1;
            default: return false;
        }
    }
    
    private void updateStepApproval(CreditMpCustomer customer, FollowStepApprovalDTO dto) {
        String currentTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        Integer currentUserId = baseController.getLoginUserId();
        
        switch (dto.getStep()) {
            case 1:
                customer.setFollowStep1Approved(dto.getApproved() ? 1 : 0);
                customer.setFollowStep1ApprovedAt(currentTime);
                customer.setFollowStep1ApprovedBy(currentUserId != null ? currentUserId.longValue() : null);
                break;
            case 2:
                customer.setFollowStep2Approved(dto.getApproved() ? 1 : 0);
                customer.setFollowStep2ApprovedAt(currentTime);
                customer.setFollowStep2ApprovedBy(currentUserId != null ? currentUserId.longValue() : null);
                break;
            case 3:
                customer.setFollowStep3Approved(dto.getApproved() ? 1 : 0);
                customer.setFollowStep3ApprovedAt(currentTime);
                customer.setFollowStep3ApprovedBy(currentUserId != null ? currentUserId.longValue() : null);
                break;
            case 4:
                customer.setFollowStep4Approved(dto.getApproved() ? 1 : 0);
                customer.setFollowStep4ApprovedAt(currentTime);
                customer.setFollowStep4ApprovedBy(currentUserId != null ? currentUserId.longValue() : null);
                break;
            case 5:
                customer.setFollowStep5Approved(dto.getApproved() ? 1 : 0);
                customer.setFollowStep5ApprovedAt(currentTime);
                customer.setFollowStep5ApprovedBy(currentUserId != null ? currentUserId.longValue() : null);
                break;
            case 6:
                customer.setFollowStep6Approved(dto.getApproved() ? 1 : 0);
                customer.setFollowStep6ApprovedAt(currentTime);
                customer.setFollowStep6ApprovedBy(currentUserId != null ? currentUserId.longValue() : null);
                break;
            case 7:
                customer.setFollowStep7Approved(dto.getApproved() ? 1 : 0);
                customer.setFollowStep7ApprovedAt(currentTime);
                customer.setFollowStep7ApprovedBy(currentUserId != null ? currentUserId.longValue() : null);
                break;
        }
        
        updateById(customer);
    }

    private void updateCustomerStep(CreditMpCustomer customer, Integer step) {
        // 更新客户的总体步骤状态
        if (step >= customer.getStep()) {
            customer.setStep(step + 1);
            updateById(customer);
        }
    }

    private FollowStepDetailDTO getStepDetail(CreditMpCustomer customer, Integer step) {
        FollowStepDetailDTO detail = new FollowStepDetailDTO();
        detail.setStep(step);
        
        // 设置步骤标题
        String[] stepTitles = {"", "案件受理", "材料准备", "案件办理", "送达签收", "合同签订", "订单回款", "电话回访"};
        detail.setTitle(stepTitles[step]);
        
        // 获取步骤状态
        boolean submitted = isStepSubmitted(customer, step);
        boolean approved = isStepApproved(customer, step);
        
        if (approved) {
            detail.setStatus("approved");
            detail.setApprovedAt(getStepApprovedAt(customer, step));
        } else if (submitted) {
            detail.setStatus("submitted");
            detail.setSubmittedAt(getStepSubmittedAt(customer, step));
        } else {
            detail.setStatus("pending");
        }
        
        return detail;
    }

    private boolean isStepApproved(CreditMpCustomer customer, Integer step) {
        switch (step) {
            case 1: return customer.getFollowStep1Approved() != null && customer.getFollowStep1Approved() == 1;
            case 2: return customer.getFollowStep2Approved() != null && customer.getFollowStep2Approved() == 1;
            case 3: return customer.getFollowStep3Approved() != null && customer.getFollowStep3Approved() == 1;
            case 4: return customer.getFollowStep4Approved() != null && customer.getFollowStep4Approved() == 1;
            case 5: return customer.getFollowStep5Approved() != null && customer.getFollowStep5Approved() == 1;
            case 6: return customer.getFollowStep6Approved() != null && customer.getFollowStep6Approved() == 1;
            case 7: return customer.getFollowStep7Approved() != null && customer.getFollowStep7Approved() == 1;
            default: return false;
        }
    }

    private LocalDateTime getStepSubmittedAt(CreditMpCustomer customer, Integer step) {
        String submittedAt = null;
        switch (step) {
            case 1: submittedAt = customer.getFollowStep1SubmittedAt(); break;
            case 2: submittedAt = customer.getFollowStep2SubmittedAt(); break;
            case 3: submittedAt = customer.getFollowStep3SubmittedAt(); break;
            case 4: submittedAt = customer.getFollowStep4SubmittedAt(); break;
            case 5: submittedAt = customer.getFollowStep5SubmittedAt(); break;
            case 6: submittedAt = customer.getFollowStep6SubmittedAt(); break;
            case 7: submittedAt = customer.getFollowStep7SubmittedAt(); break;
        }
        return submittedAt != null ? LocalDateTime.parse(submittedAt, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : null;
    }

    private LocalDateTime getStepApprovedAt(CreditMpCustomer customer, Integer step) {
        String approvedAt = null;
        switch (step) {
            case 1: approvedAt = customer.getFollowStep1ApprovedAt(); break;
            case 2: approvedAt = customer.getFollowStep2ApprovedAt(); break;
            case 3: approvedAt = customer.getFollowStep3ApprovedAt(); break;
            case 4: approvedAt = customer.getFollowStep4ApprovedAt(); break;
            case 5: approvedAt = customer.getFollowStep5ApprovedAt(); break;
            case 6: approvedAt = customer.getFollowStep6ApprovedAt(); break;
            case 7: approvedAt = customer.getFollowStep7ApprovedAt(); break;
        }
        return approvedAt != null ? LocalDateTime.parse(approvedAt, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : null;
    }

}
