package com.huimv.employment.service.order;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.huimv.employment.common.exception.BizException;
import com.huimv.employment.common.exception.ErrorCode;
import com.huimv.employment.dao.entity.FeContract;
import com.huimv.employment.dao.entity.FeEmploymentDraft;
import com.huimv.employment.dao.entity.FeEmploymentOrder;
import com.huimv.employment.dao.entity.FeEnterprise;
import com.huimv.employment.dao.entity.FeWorkerRegistration;
import com.huimv.employment.dao.mapper.FeEmploymentDraftMapper;
import com.huimv.employment.dao.mapper.FeEmploymentOrderMapper;
import com.huimv.employment.dao.mapper.FeWorkerRegistrationMapper;
import com.huimv.employment.service.contract.ContractService;
import com.huimv.employment.service.conversation.ConversationService;
import com.huimv.employment.service.enterprise.EnterpriseService;
import com.huimv.employment.service.order.dto.EmploymentOrderItemResponse;
import com.huimv.employment.service.order.dto.OrderStartWorkRequest;
import com.huimv.employment.service.order.dto.OrderStartWorkResponse;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 企业端用工订单查询与开工确认。
 */
@Service
public class EmploymentOrderService {

    private static final String STEP_CONTRACT_SIGNING = "contract_signing";
    private static final String STEP_WORK_STARTED = "work_started";
    private static final String REG_CONTRACT_SIGNING = "contract_signing";
    private static final String REG_COMPLETED = "completed";
    private static final String REG_UNDER_REVIEW = "under_review";
    private static final String SIGN_SIGNED = "signed";

    private final FeEmploymentOrderMapper feEmploymentOrderMapper;
    private final FeEmploymentDraftMapper feEmploymentDraftMapper;
    private final FeWorkerRegistrationMapper feWorkerRegistrationMapper;
    private final ConversationService conversationService;
    private final EnterpriseService enterpriseService;
    private final ContractService contractService;

    public EmploymentOrderService(FeEmploymentOrderMapper feEmploymentOrderMapper,
                                  FeEmploymentDraftMapper feEmploymentDraftMapper,
                                  FeWorkerRegistrationMapper feWorkerRegistrationMapper,
                                  ConversationService conversationService,
                                  EnterpriseService enterpriseService,
                                  ContractService contractService) {
        this.feEmploymentOrderMapper = feEmploymentOrderMapper;
        this.feEmploymentDraftMapper = feEmploymentDraftMapper;
        this.feWorkerRegistrationMapper = feWorkerRegistrationMapper;
        this.conversationService = conversationService;
        this.enterpriseService = enterpriseService;
        this.contractService = contractService;
    }

    /**
     * 按会话查询其下草稿已转成正式订单的列表。
     * <p>仅返回已存在订单的草稿；无订单的草稿不出现在结果中。</p>
     */
    public List<EmploymentOrderItemResponse> listByConversation(Long userId, Long conversationId) {
        conversationService.requireOwned(userId, conversationId);
        FeEnterprise enterprise = enterpriseService.findEnterpriseByUserId(userId);
        if (enterprise == null) {
            throw new BizException(ErrorCode.BAD_REQUEST, "请先完成企业登记");
        }

        List<FeEmploymentDraft> drafts = feEmploymentDraftMapper.selectList(
                new LambdaQueryWrapper<FeEmploymentDraft>()
                        .eq(FeEmploymentDraft::getConversationId, conversationId)
                        .eq(FeEmploymentDraft::getEnterpriseId, enterprise.getId())
                        .orderByAsc(FeEmploymentDraft::getId));
        if (drafts == null || drafts.isEmpty()) {
            return Collections.emptyList();
        }

        List<Long> draftIds = new ArrayList<>(drafts.size());
        for (FeEmploymentDraft draft : drafts) {
            if (draft.getId() != null) {
                draftIds.add(draft.getId());
            }
        }
        if (draftIds.isEmpty()) {
            return Collections.emptyList();
        }

        List<FeEmploymentOrder> orders = feEmploymentOrderMapper.selectList(
                new LambdaQueryWrapper<FeEmploymentOrder>()
                        .eq(FeEmploymentOrder::getEnterpriseId, enterprise.getId())
                        .in(FeEmploymentOrder::getDraftId, draftIds)
                        .orderByDesc(FeEmploymentOrder::getCreateTime)
                        .orderByDesc(FeEmploymentOrder::getId));
        if (orders == null || orders.isEmpty()) {
            return Collections.emptyList();
        }

        List<EmploymentOrderItemResponse> result = new ArrayList<>(orders.size());
        for (FeEmploymentOrder order : orders) {
            result.add(toItem(order));
        }
        return result;
    }

    /**
     * 查询开工就绪状态（人数提示、是否齐签、是否可开工）。
     */
    public OrderStartWorkResponse getStartWorkStatus(Long userId, Long orderId) {
        FeEmploymentOrder order = requireOwnedOrder(userId, orderId);
        return buildStartWorkStatus(order, false);
    }

    /**
     * 企业确认开工：要求已过审工人全部签完；缺编须 {@code allow_understaffed=true}。
     * <p>订单 {@code contract_signing → work_started}。</p>
     */
    @Transactional(rollbackFor = Exception.class)
    public OrderStartWorkResponse startWork(Long userId, Long orderId, OrderStartWorkRequest request) {
        FeEmploymentOrder order = requireOwnedOrder(userId, orderId);
        OrderStartWorkResponse status = buildStartWorkStatus(order, true);
        if (STEP_WORK_STARTED.equals(order.getCurrentStepCode())
                || isStepAfter(order.getCurrentStepCode(), STEP_WORK_STARTED)) {
            status.setMessage("订单已进入开工阶段");
            return status;
        }
        if (!STEP_CONTRACT_SIGNING.equals(order.getCurrentStepCode())) {
            throw new BizException(ErrorCode.BAD_REQUEST,
                    "当前步骤不可开工：" + (order.getCurrentStepCode() == null ? "未知" : order.getCurrentStepCode()));
        }
        if (status.getApprovedCount() == null || status.getApprovedCount() <= 0) {
            throw new BizException(ErrorCode.BAD_REQUEST, "尚无已过审工人，无法开工");
        }
        if (!Boolean.TRUE.equals(status.getAllApprovedSigned())) {
            throw new BizException(ErrorCode.BAD_REQUEST,
                    "尚有已过审工人未完成签署（已签 " + status.getSignedCount()
                            + "/" + status.getApprovedCount() + "）");
        }
        boolean allowUnderstaffed = request != null && request.isAllowUnderstaffed();
        if (Boolean.TRUE.equals(status.getUnderstaffed()) && !allowUnderstaffed) {
            throw new BizException(ErrorCode.BAD_REQUEST,
                    "已签署 " + status.getSignedCount() + " 人，计划 "
                            + status.getPlannedCount() + " 人，未招满。"
                            + "确认缺编开工请传 allow_understaffed=true");
        }

        LocalDateTime now = LocalDateTime.now();
        FeEmploymentOrder update = new FeEmploymentOrder();
        update.setId(order.getId());
        update.setCurrentStepCode(STEP_WORK_STARTED);
        update.setUpdateTime(now);
        feEmploymentOrderMapper.updateById(update);
        order.setCurrentStepCode(STEP_WORK_STARTED);

        OrderStartWorkResponse result = buildStartWorkStatus(order, true);
        result.setMessage(Boolean.TRUE.equals(status.getUnderstaffed())
                ? "已确认缺编开工"
                : "已确认开工");
        return result;
    }

    private FeEmploymentOrder requireOwnedOrder(Long userId, Long orderId) {
        enterpriseService.requireEnterpriseUser(userId);
        FeEnterprise enterprise = enterpriseService.findEnterpriseByUserId(userId);
        if (enterprise == null) {
            throw new BizException(ErrorCode.BAD_REQUEST, "请先完成企业登记");
        }
        if (orderId == null) {
            throw new BizException(ErrorCode.BAD_REQUEST, "订单 ID 无效");
        }
        FeEmploymentOrder order = feEmploymentOrderMapper.selectById(orderId);
        if (order == null) {
            throw new BizException(ErrorCode.NOT_FOUND, "用工订单不存在");
        }
        if (order.getEnterpriseId() == null || !order.getEnterpriseId().equals(enterprise.getId())) {
            throw new BizException(ErrorCode.FORBIDDEN, "无权操作该订单");
        }
        return order;
    }

    private OrderStartWorkResponse buildStartWorkStatus(FeEmploymentOrder order, boolean forStartAction) {
        Long orderId = order.getId();
        int planned = order.getWorkerCount() != null && order.getWorkerCount() > 0
                ? order.getWorkerCount() : 0;

        List<FeWorkerRegistration> regs = feWorkerRegistrationMapper.selectList(
                new LambdaQueryWrapper<FeWorkerRegistration>()
                        .eq(FeWorkerRegistration::getOrderId, orderId));
        if (regs == null) {
            regs = Collections.emptyList();
        }

        int approved = 0;
        int signed = 0;
        int pendingSign = 0;
        int underReview = 0;
        for (FeWorkerRegistration reg : regs) {
            String st = reg.getRegStatus();
            if (REG_UNDER_REVIEW.equals(st)) {
                underReview++;
                continue;
            }
            if (!REG_CONTRACT_SIGNING.equals(st) && !REG_COMPLETED.equals(st)) {
                continue;
            }
            approved++;
            FeContract contract = contractService.findActiveByRegistrationId(reg.getId());
            if (contract != null && SIGN_SIGNED.equals(contract.getSignStatus())) {
                signed++;
            } else {
                pendingSign++;
            }
        }

        boolean allApprovedSigned = approved > 0 && pendingSign == 0;
        boolean understaffed = planned > 0 && signed < planned;
        boolean atSigning = STEP_CONTRACT_SIGNING.equals(order.getCurrentStepCode());
        boolean canStart = atSigning && allApprovedSigned;

        OrderStartWorkResponse response = new OrderStartWorkResponse();
        response.setOrderId(orderId);
        response.setOrderNo(order.getOrderNo());
        response.setCurrentStepCode(order.getCurrentStepCode());
        response.setPlannedCount(planned);
        response.setApprovedCount(approved);
        response.setSignedCount(signed);
        response.setPendingSignCount(pendingSign);
        response.setUnderReviewCount(underReview);
        response.setAllApprovedSigned(allApprovedSigned);
        response.setUnderstaffed(understaffed);
        response.setCanStartWork(canStart);

        if (STEP_WORK_STARTED.equals(order.getCurrentStepCode())
                || isStepAfter(order.getCurrentStepCode(), STEP_WORK_STARTED)) {
            response.setMessage("订单已进入开工阶段");
        } else if (!atSigning) {
            response.setMessage("订单尚未进入签约阶段");
        } else if (approved == 0) {
            response.setMessage("尚无已过审工人");
        } else if (!allApprovedSigned) {
            response.setMessage("已签 " + signed + "/" + approved + "，待签 " + pendingSign + " 人");
        } else if (understaffed) {
            response.setMessage("已齐签，但未招满（已签 " + signed + "/" + planned
                    + "）。缺编开工须传 allow_understaffed=true"
                    + (underReview > 0 ? "；另有 " + underReview + " 人待审" : ""));
        } else {
            response.setMessage(forStartAction ? "可确认开工" : "已齐签且人数达标，可确认开工"
                    + (underReview > 0 ? "（另有 " + underReview + " 人待审，不阻挡开工）" : ""));
        }
        return response;
    }

    private static boolean isStepAfter(String current, String target) {
        if (!StringUtils.hasText(current) || !StringUtils.hasText(target)) {
            return false;
        }
        String[] steps = {
                "draft_created", "plan_confirmed", "registration", "enterprise_audit",
                "contract_signing", "work_started", "settlement_pending", "settlement_paid", "completed"
        };
        int curIdx = -1;
        int targetIdx = -1;
        for (int i = 0; i < steps.length; i++) {
            if (steps[i].equals(current)) {
                curIdx = i;
            }
            if (steps[i].equals(target)) {
                targetIdx = i;
            }
        }
        return curIdx >= 0 && targetIdx >= 0 && curIdx > targetIdx;
    }

    private static EmploymentOrderItemResponse toItem(FeEmploymentOrder order) {
        EmploymentOrderItemResponse item = new EmploymentOrderItemResponse();
        item.setDraftId(order.getDraftId());
        item.setOrderId(order.getId());
        item.setOrderNo(order.getOrderNo());
        item.setTitle(order.getTitle());
        item.setWorkerCount(order.getWorkerCount());
        item.setWorkDays(order.getWorkDays());
        item.setWorkType(order.getWorkType());
        item.setWorkLocation(order.getWorkLocation());
        item.setWorkStartDate(order.getWorkStartDate());
        item.setWorkEndDate(order.getWorkEndDate());
        item.setOrderStatus(order.getOrderStatus());
        item.setCurrentStepCode(order.getCurrentStepCode());
        item.setRegisteredCount(order.getRegisteredCount());
        item.setPendingCount(order.getPendingCount());
        item.setAbnormalCount(order.getAbnormalCount());
        item.setTotalOutflow(order.getTotalOutflow());
        item.setSelectedPlanId(order.getSelectedPlanId());
        item.setCreateTime(order.getCreateTime());
        item.setUpdateTime(order.getUpdateTime());
        return item;
    }
}
