package com.ruoyi.credit.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.credit.domain.Contract;
import com.ruoyi.credit.domain.ContractEmployeeLink;
import com.ruoyi.credit.domain.EmployeeInfo;
import com.ruoyi.credit.domain.ServiceContract;
import com.ruoyi.credit.domain.ServicePeriod;
import com.ruoyi.credit.domain.ServicePeriodEmployee;
import com.ruoyi.credit.domain.ServicePeriodLoan;
import com.ruoyi.credit.mapper.ContractEmployeeLinkMapper;
import com.ruoyi.credit.mapper.ContractMapper;
import com.ruoyi.credit.mapper.EmployeeInfoMapper;
import com.ruoyi.credit.mapper.ServiceContractMapper;
import com.ruoyi.credit.mapper.ServicePeriodEmployeeMapper;
import com.ruoyi.credit.mapper.ServicePeriodMapper;
import com.ruoyi.credit.service.IContractEmployeeService;
import com.ruoyi.credit.service.IEmployeeManagerService;
import com.ruoyi.credit.service.IServicePeriodLoanService;
import com.ruoyi.framework.security.validator.DepartmentPermissionValidator;

/**
 * 合同员工关联服务实现
 * 
 * @author ruoyi
 * @date 2025-12-23
 */
@Service
public class ContractEmployeeServiceImpl implements IContractEmployeeService
{
    private static final Logger log = LoggerFactory.getLogger(ContractEmployeeServiceImpl.class);

    @Autowired
    private ContractEmployeeLinkMapper contractEmployeeLinkMapper;

    @Autowired
    private ServicePeriodMapper servicePeriodMapper;

    @Autowired
    private ServicePeriodEmployeeMapper servicePeriodEmployeeMapper;

    @Autowired
    private EmployeeInfoMapper employeeInfoMapper;

    @Autowired
    private ServiceContractMapper serviceContractMapper;

    @Autowired
    private ContractMapper contractMapper;

    @Autowired
    private IEmployeeManagerService employeeManagerService;

    @Autowired
    private IServicePeriodLoanService servicePeriodLoanService;

    @Autowired
    private DepartmentPermissionValidator departmentPermissionValidator;

    // ==================== 合同员工关联管理 ====================

    @Override
    @Transactional
    public ContractEmployeeLink linkIndividualEmployeeToContract(Long contractId, Long employeeId, String assignedRole)
    {
        log.info("关联单个员工到合同: contractId={}, employeeId={}, assignedRole={}", contractId, employeeId, assignedRole);

        // 验证员工是否存在
        EmployeeInfo employee = employeeInfoMapper.selectEmployeeInfoByEmployeeId(employeeId);
        if (employee == null) {
            throw new RuntimeException("员工不存在: employeeId=" + employeeId);
        }

        // 验证合同是否存在 - 首先查询dc_contract表
        Contract contract = contractMapper.selectContractByContractId(contractId);
        if (contract == null) {
            throw new RuntimeException("合同不存在: contractId=" + contractId);
        }

        ContractEmployeeLink link = new ContractEmployeeLink();
        link.setContractId(contractId);
        link.setEmployeeId(employeeId);
        link.setLinkType(ContractEmployeeLink.LINK_TYPE_INDIVIDUAL);
        link.setAssignedRole(StringUtils.isNotEmpty(assignedRole) ? assignedRole : "GENERAL");
        link.setLinkDate(DateUtils.getNowDate());
        link.setLinkStatus(ContractEmployeeLink.STATUS_ACTIVE);
        link.setCreateTime(DateUtils.getNowDate());

        contractEmployeeLinkMapper.insertContractEmployeeLink(link);
        log.info("成功关联单个员工到合同: linkId={}", link.getLinkId());

        return link;
    }

    @Override
    @Transactional
    public List<ContractEmployeeLink> linkMultipleEmployeesToContract(Long contractId, List<Long> employeeIds, String assignedRole)
    {
        log.info("批量关联员工到合同: contractId={}, employeeCount={}", contractId, employeeIds.size());

        List<ContractEmployeeLink> links = new ArrayList<>();
        for (Long employeeId : employeeIds) {
            try {
                ContractEmployeeLink link = linkIndividualEmployeeToContract(contractId, employeeId, assignedRole);
                links.add(link);
            } catch (Exception e) {
                log.warn("关联员工失败: employeeId={}, error={}", employeeId, e.getMessage());
            }
        }

        log.info("批量关联完成: 成功关联{}个员工", links.size());
        return links;
    }

    @Override
    public List<ContractEmployeeLink> getContractEmployeeLinks(Long contractId)
    {
        return contractEmployeeLinkMapper.selectContractEmployeeLinksByContractId(contractId);
    }

    @Override
    @Transactional
    public int unlinkContractEmployee(Long linkId)
    {
        log.info("取消合同员工关联: linkId={}", linkId);
        return contractEmployeeLinkMapper.deleteContractEmployeeLinkByLinkId(linkId);
    }

    // ==================== 服务周期管理 ====================

    @Override
    @Transactional
    public ServicePeriod createServicePeriod(ServicePeriod servicePeriod)
    {
        log.info("创建服务周期: contractId={}", servicePeriod.getContractId());

        // 验证数据创建权限并自动设置部门ID
        departmentPermissionValidator.validateDataCreation(servicePeriod);

        // 验证基础合同是否存在
        Contract baseContract = contractMapper.selectContractByContractId(servicePeriod.getContractId());
        if (baseContract == null) {
            throw new RuntimeException("合同不存在: contractId=" + servicePeriod.getContractId());
        }

        // 检查是否已存在服务合同记录，如果不存在则创建
        ServiceContract existingServiceContract = serviceContractMapper.selectServiceContractByContractId(servicePeriod.getContractId());
        if (existingServiceContract == null) {
            log.info("服务合同记录不存在，从基础合同创建服务合同记录: contractId={}", servicePeriod.getContractId());
            
            // 从基础合同创建服务合同记录
            ServiceContract serviceContract = new ServiceContract();
            serviceContract.setContractId(baseContract.getContractId());
            serviceContract.setContractNumber(baseContract.getContractNumber());
            serviceContract.setTitle(baseContract.getTitle());
            serviceContract.setSecurityCompany(baseContract.getSecurityCompany());
            serviceContract.setClientCompany(baseContract.getClientCompany());
            serviceContract.setContractAmount(baseContract.getContractAmount());
            serviceContract.setStartDate(baseContract.getStartDate());
            serviceContract.setEndDate(baseContract.getEndDate());
            serviceContract.setContractStatus(baseContract.getContractStatus());
            serviceContract.setContractType(baseContract.getContractType());
            serviceContract.setContractSource("PLATFORM_CREATED");
            serviceContract.setCreateBy(SecurityUtils.getUsername());
            serviceContract.setCreateTime(DateUtils.getNowDate());
            
            // 从基础合同获取部门ID，如果基础合同没有部门ID，则从服务周期获取
            if (baseContract.getDeptId() != null) {
                serviceContract.setDeptId(baseContract.getDeptId());
            } else {
                serviceContract.setDeptId(servicePeriod.getDeptId());
            }
            
            // 设置付款到期日 - 如果基础合同有则使用，否则默认为服务结束日期
            if (baseContract.getPaymentDueDate() != null) {
                serviceContract.setPaymentDueDate(baseContract.getPaymentDueDate());
            } else {
                // 默认付款到期日为服务结束日期
                serviceContract.setPaymentDueDate(baseContract.getEndDate());
            }
            
            // 保存服务合同记录
            serviceContractMapper.insertServiceContract(serviceContract);
            log.info("成功创建服务合同记录: contractId={}, deptId={}", servicePeriod.getContractId(), serviceContract.getDeptId());
        }

        // 生成周期编号
        String periodNumber = generateServicePeriodNumber(servicePeriod.getContractId());
        servicePeriod.setPeriodNumber(periodNumber);
        servicePeriod.setPeriodStatus(ServicePeriod.STATUS_CREATED);
        servicePeriod.setEmployeeCount(0);
        servicePeriod.setTotalLaborCost(BigDecimal.ZERO);
        
        // 计算初始贷款金额：如果有倍数且不为1则使用倍数，否则使用人工成本
        BigDecimal initialLoanAmount;
        if (servicePeriod.getLoanMultiplier() != null && 
            servicePeriod.getLoanMultiplier().compareTo(BigDecimal.ZERO) > 0 &&
            servicePeriod.getLoanMultiplier().compareTo(BigDecimal.ONE) != 0) {
            // 有倍数且不等于1，使用倍数计算
            initialLoanAmount = BigDecimal.ZERO.multiply(servicePeriod.getLoanMultiplier());
        } else {
            // 没有倍数或倍数为1时，贷款金额等于人工成本
            initialLoanAmount = BigDecimal.ZERO;
        }
        servicePeriod.setTotalLoanAmount(initialLoanAmount);
        
        servicePeriod.setCreateTime(DateUtils.getNowDate());
        servicePeriod.setCreatedBy(SecurityUtils.getUsername());

        servicePeriodMapper.insertServicePeriod(servicePeriod);
        log.info("成功创建服务周期: servicePeriodId={}, periodNumber={}, loanMultiplier={}, totalLoanAmount={}", 
                servicePeriod.getServicePeriodId(), periodNumber, servicePeriod.getLoanMultiplier(), servicePeriod.getTotalLoanAmount());

        return servicePeriod;
    }

    @Override
    public ServicePeriod getServicePeriod(Long servicePeriodId)
    {
        return servicePeriodMapper.selectServicePeriodByServicePeriodId(servicePeriodId);
    }

    @Override
    public List<ServicePeriod> selectServicePeriodList(ServicePeriod servicePeriod)
    {
        return servicePeriodMapper.selectServicePeriodList(servicePeriod);
    }

    @Override
    public List<ServicePeriod> getServicePeriodsByContract(Long contractId)
    {
        return servicePeriodMapper.selectServicePeriodsByContractId(contractId);
    }

    @Override
    @Transactional
    public int updateServicePeriod(ServicePeriod servicePeriod)
    {
        servicePeriod.setUpdateTime(DateUtils.getNowDate());
        servicePeriod.setUpdatedBy(SecurityUtils.getUsername());
        
        int result = servicePeriodMapper.updateServicePeriod(servicePeriod);
        
        // 更新后重新计算汇总信息（包括贷款金额）
        updateServicePeriodSummary(servicePeriod.getServicePeriodId());
        
        return result;
    }

    @Override
    @Transactional
    public int deleteServicePeriod(Long servicePeriodId)
    {
        log.info("删除服务周期: servicePeriodId={}", servicePeriodId);
        
        // 先删除相关的员工分配记录
        servicePeriodEmployeeMapper.deleteServicePeriodEmployeeByPeriodId(servicePeriodId);
        
        // 删除服务周期
        return servicePeriodMapper.deleteServicePeriodByServicePeriodId(servicePeriodId);
    }

    // ==================== 服务周期出勤员工选择 ====================

    @Override
    @Transactional
    public List<ServicePeriodEmployee> selectAttendanceEmployees(Long servicePeriodId, List<Long> employeeIds, Integer workDays)
    {
        log.info("为服务周期选择出勤员工: servicePeriodId={}, employeeCount={}, workDays={}", 
                servicePeriodId, employeeIds.size(), workDays);

        List<ServicePeriodEmployee> assignments = new ArrayList<>();
        List<String> failureReasons = new ArrayList<>();
        
        for (Long employeeId : employeeIds) {
            try {
                log.info("开始处理员工: employeeId={}", employeeId);
                
                // 验证员工是否可以分配
                Map<String, Object> validation = validateEmployeeAssignment(employeeId, servicePeriodId);
                if (!(Boolean) validation.get("valid")) {
                    String reason = "员工分配验证失败: employeeId=" + employeeId + ", reason=" + validation.get("message");
                    log.warn(reason);
                    failureReasons.add(reason);
                    continue;
                }

                EmployeeInfo employee = employeeInfoMapper.selectEmployeeInfoByEmployeeId(employeeId);
                if (employee == null) {
                    String reason = "员工不存在: employeeId=" + employeeId;
                    log.warn(reason);
                    failureReasons.add(reason);
                    continue;
                }

                log.info("员工信息: employeeId={}, name={}, position={}, status={}", 
                        employee.getEmployeeId(), employee.getEmployeeName(), 
                        employee.getPosition(), employee.getEmployeeStatus());

                ServicePeriodEmployee assignment = new ServicePeriodEmployee();
                assignment.setServicePeriodId(servicePeriodId);
                assignment.setEmployeeId(employeeId);
                assignment.setAssignedPosition(employee.getPosition());
                assignment.setWorkDays(workDays);
                assignment.setAssignmentStatus(ServicePeriodEmployee.STATUS_ASSIGNED);
                assignment.setAssignmentDate(DateUtils.getNowDate());
                assignment.setAssignedBy(SecurityUtils.getUsername());
                assignment.setCreateTime(DateUtils.getNowDate());

                // 智能获取员工薪资并转换为日薪标准
                BigDecimal assignedDailySalary = getEmployeeDailySalary(employee);
                log.info("员工{}转换后的日薪标准: {}", employeeId, assignedDailySalary);
                
                // 计算该员工在指定工作天数下的总成本（使用日薪标准计算）
                BigDecimal employeeCost = assignedDailySalary.multiply(BigDecimal.valueOf(workDays)).setScale(2, BigDecimal.ROUND_HALF_UP);
                log.info("员工{}工作{}天的总成本: {} (日薪{} × {}天)", employeeId, workDays, employeeCost, assignedDailySalary, workDays);
                
                // 设置分配薪资（日薪标准）和总成本
                assignment.setAssignedSalary(assignedDailySalary);
                assignment.setTotalCost(employeeCost);

                log.info("准备插入员工分配记录: servicePeriodId={}, employeeId={}, cost={}", 
                        servicePeriodId, employeeId, employeeCost);

                servicePeriodEmployeeMapper.insertServicePeriodEmployee(assignment);
                assignments.add(assignment);
                
                log.info("成功分配员工: employeeId={}, assignmentId={}", employeeId, assignment.getAssignmentId());
                
            } catch (Exception e) {
                String reason = "处理员工时发生异常: employeeId=" + employeeId + ", error=" + e.getMessage();
                log.error(reason, e);
                failureReasons.add(reason);
            }
        }

        // 更新服务周期的员工数量和总成本
        updateServicePeriodSummary(servicePeriodId);

        log.info("员工分配完成: 成功分配{}个员工，失败{}个员工", assignments.size(), failureReasons.size());
        if (!failureReasons.isEmpty()) {
            log.warn("分配失败的原因: {}", String.join("; ", failureReasons));
        }
        
        return assignments;
    }

    @Override
    public List<ServicePeriodEmployee> getServicePeriodEmployees(Long servicePeriodId)
    {
        return servicePeriodEmployeeMapper.selectServicePeriodEmployeesByPeriodId(servicePeriodId);
    }

    @Override
    public List<com.ruoyi.credit.dto.ServicePeriodEmployeeDTO> getServicePeriodEmployeesWithInfo(Long servicePeriodId)
    {
        return servicePeriodEmployeeMapper.selectServicePeriodEmployeesWithInfoByPeriodId(servicePeriodId);
    }

    @Override
    @Transactional
    public int updateServicePeriodEmployee(ServicePeriodEmployee servicePeriodEmployee)
    {
        servicePeriodEmployee.setUpdateTime(DateUtils.getNowDate());
        int result = servicePeriodEmployeeMapper.updateServicePeriodEmployee(servicePeriodEmployee);
        
        // 重新计算服务周期总成本
        updateServicePeriodSummary(servicePeriodEmployee.getServicePeriodId());
        
        return result;
    }

    @Override
    @Transactional
    public int removeServicePeriodEmployee(Long assignmentId)
    {
        ServicePeriodEmployee assignment = servicePeriodEmployeeMapper.selectServicePeriodEmployeeByAssignmentId(assignmentId);
        if (assignment == null) {
            return 0;
        }

        int result = servicePeriodEmployeeMapper.deleteServicePeriodEmployeeByAssignmentId(assignmentId);
        
        // 重新计算服务周期总成本
        updateServicePeriodSummary(assignment.getServicePeriodId());
        
        return result;
    }

    @Override
    @Transactional
    public Map<String, Object> batchRemoveServicePeriodEmployees(Long servicePeriodId, List<Long> assignmentIds)
    {
        log.info("批量移除服务周期员工: servicePeriodId={}, assignmentCount={}", servicePeriodId, assignmentIds.size());

        Map<String, Object> result = new HashMap<>();
        int successCount = 0;
        List<String> errors = new ArrayList<>();

        for (Long assignmentId : assignmentIds) {
            try {
                int deleteResult = servicePeriodEmployeeMapper.deleteServicePeriodEmployeeByAssignmentId(assignmentId);
                if (deleteResult > 0) {
                    successCount++;
                } else {
                    errors.add("分配ID " + assignmentId + ": 记录不存在或已被删除");
                }
            } catch (Exception e) {
                log.error("删除员工分配失败: assignmentId={}", assignmentId, e);
                errors.add("分配ID " + assignmentId + ": " + e.getMessage());
            }
        }

        // 重新计算服务周期总成本
        updateServicePeriodSummary(servicePeriodId);

        result.put("successCount", successCount);
        result.put("totalCount", assignmentIds.size());
        result.put("errors", errors);
        result.put("success", errors.isEmpty());

        log.info("批量移除完成: 成功移除{}个员工，失败{}个员工", successCount, errors.size());
        return result;
    }

    @Override
    @Transactional
    public Map<String, Object> clearAllServicePeriodEmployees(Long servicePeriodId)
    {
        log.info("清空服务周期所有员工: servicePeriodId={}", servicePeriodId);

        Map<String, Object> result = new HashMap<>();
        
        try {
            // 获取当前所有员工分配
            List<ServicePeriodEmployee> employees = servicePeriodEmployeeMapper.selectServicePeriodEmployeesByPeriodId(servicePeriodId);
            int totalCount = employees.size();
            
            if (totalCount == 0) {
                result.put("successCount", 0);
                result.put("totalCount", 0);
                result.put("message", "当前服务周期没有员工需要清空");
                result.put("success", true);
                return result;
            }

            // 批量删除所有员工分配
            int deletedCount = servicePeriodEmployeeMapper.deleteServicePeriodEmployeeByPeriodId(servicePeriodId);
            
            // 重新计算服务周期总成本
            updateServicePeriodSummary(servicePeriodId);

            result.put("successCount", deletedCount);
            result.put("totalCount", totalCount);
            result.put("message", "成功清空所有员工分配");
            result.put("success", true);

            log.info("清空完成: 成功清空{}个员工", deletedCount);
            
        } catch (Exception e) {
            log.error("清空服务周期员工失败: servicePeriodId={}", servicePeriodId, e);
            result.put("successCount", 0);
            result.put("totalCount", 0);
            result.put("message", "清空操作失败: " + e.getMessage());
            result.put("success", false);
        }

        return result;
    }

    // ==================== OCR信息提取 ====================

    @Override
    public Map<String, Object> extractEmployeeInfoFromOCR(MultipartFile contractFile)
    {
        log.info("通过OCR提取员工信息: fileName={}", contractFile.getOriginalFilename());

        Map<String, Object> result = new HashMap<>();
        
        try {
            // 调用员工管理服务的OCR功能
            Map<String, Object> ocrResult = employeeManagerService.extractEmployeeInfoFromOCR(contractFile);
            
            // 处理OCR结果，提取员工相关信息
            List<Map<String, Object>> extractedEmployees = new ArrayList<>();
            
            // 这里应该实现具体的OCR解析逻辑
            // 目前返回模拟数据
            Map<String, Object> employeeInfo = new HashMap<>();
            employeeInfo.put("employeeName", "从OCR提取的员工姓名");
            employeeInfo.put("position", "从OCR提取的岗位");
            employeeInfo.put("salaryStandard", "从OCR提取的薪资标准");
            extractedEmployees.add(employeeInfo);
            
            result.put("success", true);
            result.put("extractedEmployees", extractedEmployees);
            result.put("message", "OCR信息提取成功");
            
        } catch (Exception e) {
            log.error("OCR信息提取失败", e);
            result.put("success", false);
            result.put("message", "OCR信息提取失败: " + e.getMessage());
        }

        return result;
    }

    @Override
    @Transactional
    public int adjustSalaryStandard(Long servicePeriodId, Long employeeId, BigDecimal adjustedSalary, String salaryType)
    {
        log.info("手动调整薪资标准: servicePeriodId={}, employeeId={}, adjustedSalary={}, salaryType={}", 
                servicePeriodId, employeeId, adjustedSalary, salaryType);

        // 查找员工分配记录
        ServicePeriodEmployee query = new ServicePeriodEmployee();
        query.setServicePeriodId(servicePeriodId);
        query.setEmployeeId(employeeId);
        
        List<ServicePeriodEmployee> assignments = servicePeriodEmployeeMapper.selectServicePeriodEmployeeList(query);
        if (assignments.isEmpty()) {
            throw new RuntimeException("未找到员工分配记录");
        }

        ServicePeriodEmployee assignment = assignments.get(0);
        
        // 直接使用调整后的薪资作为日薪标准（不进行转换）
        // 用户在调整薪资时应该直接输入日薪值
        BigDecimal dailySalaryStandard = adjustedSalary;
        assignment.setAssignedSalary(dailySalaryStandard);
        
        // 重新计算总成本（使用日薪标准乘以工作天数）
        BigDecimal newTotalCost = dailySalaryStandard.multiply(BigDecimal.valueOf(assignment.getWorkDays())).setScale(2, BigDecimal.ROUND_HALF_UP);
        assignment.setTotalCost(newTotalCost);
        assignment.setUpdateTime(DateUtils.getNowDate());

        int result = servicePeriodEmployeeMapper.updateServicePeriodEmployee(assignment);
        
        // 重新计算服务周期总成本
        updateServicePeriodSummary(servicePeriodId);
        
        return result;
    }

    @Override
    @Transactional
    public Map<String, Object> batchAdjustSalaryStandards(Long servicePeriodId, Map<Long, BigDecimal> salaryAdjustments)
    {
        log.info("批量调整薪资标准: servicePeriodId={}, adjustmentCount={}", servicePeriodId, salaryAdjustments.size());

        Map<String, Object> result = new HashMap<>();
        int successCount = 0;
        List<String> errors = new ArrayList<>();

        for (Map.Entry<Long, BigDecimal> entry : salaryAdjustments.entrySet()) {
            try {
                adjustSalaryStandard(servicePeriodId, entry.getKey(), entry.getValue(), EmployeeInfo.SALARY_UNIT_DAILY);
                successCount++;
            } catch (Exception e) {
                errors.add("员工ID " + entry.getKey() + ": " + e.getMessage());
            }
        }

        result.put("successCount", successCount);
        result.put("totalCount", salaryAdjustments.size());
        result.put("errors", errors);
        result.put("success", errors.isEmpty());

        return result;
    }

    // ==================== 人工成本计算 ====================

    @Override
    public Map<String, Object> calculateLaborCost(Long servicePeriodId)
    {
        log.info("计算服务周期人工成本: servicePeriodId={}", servicePeriodId);

        Map<String, Object> result = new HashMap<>();
        
        List<ServicePeriodEmployee> employees = servicePeriodEmployeeMapper.selectServicePeriodEmployeesByPeriodId(servicePeriodId);
        
        BigDecimal totalCost = BigDecimal.ZERO;
        int totalEmployees = employees.size();
        int totalWorkDays = 0;
        
        List<Map<String, Object>> employeeCosts = new ArrayList<>();
        
        for (ServicePeriodEmployee employee : employees) {
            Map<String, Object> employeeCost = new HashMap<>();
            employeeCost.put("employeeId", employee.getEmployeeId());
            employeeCost.put("assignedPosition", employee.getAssignedPosition());
            employeeCost.put("workDays", employee.getWorkDays());
            employeeCost.put("assignedSalary", employee.getAssignedSalary());
            employeeCost.put("totalCost", employee.getTotalCost());
            
            employeeCosts.add(employeeCost);
            totalCost = totalCost.add(employee.getTotalCost()).setScale(2, BigDecimal.ROUND_HALF_UP);
            totalWorkDays += employee.getWorkDays();
        }
        
        result.put("servicePeriodId", servicePeriodId);
        result.put("totalCost", totalCost);
        result.put("totalEmployees", totalEmployees);
        result.put("totalWorkDays", totalWorkDays);
        result.put("averageCostPerEmployee", totalEmployees > 0 ? totalCost.divide(BigDecimal.valueOf(totalEmployees), 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO);
        result.put("employeeCosts", employeeCosts);
        
        return result;
    }

    @Override
    public BigDecimal calculateEmployeeCost(Long employeeId, Integer workDays, String salaryType)
    {
        EmployeeInfo employee = employeeInfoMapper.selectEmployeeInfoByEmployeeId(employeeId);
        if (employee == null) {
            return BigDecimal.ZERO;
        }

        // 获取员工的日薪标准
        BigDecimal dailySalary = getEmployeeDailySalary(employee);
        if (dailySalary.compareTo(BigDecimal.ZERO) == 0) {
            log.warn("员工{}没有有效的日薪数据，无法计算成本", employeeId);
            return BigDecimal.ZERO;
        }
        
        // 计算总成本：日薪 × 工作天数
        return dailySalary.multiply(BigDecimal.valueOf(workDays)).setScale(2, BigDecimal.ROUND_HALF_UP);
    }

    @Override
    @Transactional
    public BigDecimal recalculateTotalCost(Long servicePeriodId)
    {
        log.info("重新计算服务周期总成本: servicePeriodId={}", servicePeriodId);

        List<ServicePeriodEmployee> employees = servicePeriodEmployeeMapper.selectServicePeriodEmployeesByPeriodId(servicePeriodId);
        
        BigDecimal totalCost = employees.stream()
                .map(ServicePeriodEmployee::getTotalCost)
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .setScale(2, BigDecimal.ROUND_HALF_UP);

        // 更新服务周期总成本
        ServicePeriod servicePeriod = servicePeriodMapper.selectServicePeriodByServicePeriodId(servicePeriodId);
        if (servicePeriod != null) {
            servicePeriod.setTotalLaborCost(totalCost);
            servicePeriod.setEmployeeCount(employees.size());
            servicePeriod.setUpdateTime(DateUtils.getNowDate());
            servicePeriodMapper.updateServicePeriod(servicePeriod);
        }

        return totalCost;
    }

    // ==================== 数据验证 ====================

    @Override
    public Map<String, Object> validateEmployeeAssignment(Long employeeId, Long servicePeriodId)
    {
        Map<String, Object> result = new HashMap<>();
        log.info("验证员工分配: employeeId={}, servicePeriodId={}", employeeId, servicePeriodId);
        
        // 检查员工是否存在
        EmployeeInfo employee = employeeInfoMapper.selectEmployeeInfoByEmployeeId(employeeId);
        if (employee == null) {
            log.warn("员工不存在: employeeId={}", employeeId);
            result.put("valid", false);
            result.put("message", "员工不存在");
            return result;
        }
        log.info("员工存在: employeeId={}, name={}, status={}", employeeId, employee.getEmployeeName(), employee.getEmployeeStatus());

        // 检查员工状态
        if (!EmployeeInfo.STATUS_ACTIVE.equals(employee.getEmployeeStatus())) {
            log.warn("员工状态不是活跃状态: employeeId={}, status={}", employeeId, employee.getEmployeeStatus());
            result.put("valid", false);
            result.put("message", "员工状态不是活跃状态，当前状态: " + employee.getEmployeeStatus());
            return result;
        }

        // 检查是否已经分配到该服务周期
        ServicePeriodEmployee query = new ServicePeriodEmployee();
        query.setServicePeriodId(servicePeriodId);
        query.setEmployeeId(employeeId);
        
        List<ServicePeriodEmployee> existing = servicePeriodEmployeeMapper.selectServicePeriodEmployeeList(query);
        if (!existing.isEmpty()) {
            log.warn("员工已经分配到该服务周期: employeeId={}, servicePeriodId={}, existingAssignments={}", 
                    employeeId, servicePeriodId, existing.size());
            result.put("valid", false);
            result.put("message", "员工已经分配到该服务周期");
            return result;
        }

        log.info("员工分配验证通过: employeeId={}", employeeId);
        result.put("valid", true);
        result.put("message", "验证通过");
        return result;
    }

    @Override
    public String generateServicePeriodNumber(Long contractId)
    {
        // 首先尝试从dc_contract表获取合同信息
        Contract baseContract = contractMapper.selectContractByContractId(contractId);
        if (baseContract == null) {
            throw new RuntimeException("合同不存在: contractId=" + contractId);
        }

        // 获取该合同已有的服务周期数量
        List<ServicePeriod> existingPeriods = servicePeriodMapper.selectServicePeriodsByContractId(contractId);
        int periodCount = existingPeriods.size() + 1;

        // 生成格式: 合同编号-SP-序号
        return baseContract.getContractNumber() + "-SP-" + String.format("%03d", periodCount);
    }

    // ==================== 私有辅助方法 ====================

    /**
     * 智能获取员工日薪标准
     */
    private BigDecimal getEmployeeDailySalary(EmployeeInfo employee)
    {
        if (employee == null) {
            return BigDecimal.ZERO;
        }

        // 优先使用员工的日薪字段
        if (employee.getDailySalary() != null && employee.getDailySalary().compareTo(BigDecimal.ZERO) > 0) {
            log.info("员工{}使用日薪: {}", employee.getEmployeeId(), employee.getDailySalary());
            return employee.getDailySalary();
        }
        
        // 如果没有日薪，但有月薪，则转换月薪为日薪
        if (employee.getMonthlySalary() != null && employee.getMonthlySalary().compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal dailyFromMonthly = employee.getMonthlySalary().divide(BigDecimal.valueOf(22), 2, BigDecimal.ROUND_HALF_UP);
            log.info("员工{}从月薪{}转换为日薪: {}", employee.getEmployeeId(), employee.getMonthlySalary(), dailyFromMonthly);
            return dailyFromMonthly;
        }
        
        // 如果没有日薪和月薪，但有时薪，则转换时薪为日薪
        if (employee.getHourlySalary() != null && employee.getHourlySalary().compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal dailyFromHourly = employee.getHourlySalary().multiply(BigDecimal.valueOf(8));
            log.info("员工{}从时薪{}转换为日薪: {}", employee.getEmployeeId(), employee.getHourlySalary(), dailyFromHourly);
            return dailyFromHourly;
        }
        
        log.warn("员工{}没有任何薪资数据", employee.getEmployeeId());
        return BigDecimal.ZERO;
    }
    
    /**
     * 检查薪资单位是否有效
     */
    private boolean isValidSalaryUnit(String salaryUnit) {
        return EmployeeInfo.SALARY_UNIT_HOURLY.equals(salaryUnit) ||
               EmployeeInfo.SALARY_UNIT_DAILY.equals(salaryUnit) ||
               EmployeeInfo.SALARY_UNIT_MONTHLY.equals(salaryUnit);
    }


    /**
     * 根据薪资单位获取员工薪资
     */
    private BigDecimal getSalaryByUnit(EmployeeInfo employee, String salaryUnit)
    {
        if (employee == null || salaryUnit == null) {
            return BigDecimal.ZERO;
        }

        switch (salaryUnit) {
            case EmployeeInfo.SALARY_UNIT_HOURLY:
                return employee.getHourlySalary() != null ? employee.getHourlySalary() : BigDecimal.ZERO;
            case EmployeeInfo.SALARY_UNIT_DAILY:
                return employee.getDailySalary() != null ? employee.getDailySalary() : BigDecimal.ZERO;
            case EmployeeInfo.SALARY_UNIT_MONTHLY:
                return employee.getMonthlySalary() != null ? employee.getMonthlySalary() : BigDecimal.ZERO;
            default:
                // 如果薪资单位未知，优先使用有值的薪资类型
                // 优先级：日薪 > 月薪 > 时薪
                if (employee.getDailySalary() != null && employee.getDailySalary().compareTo(BigDecimal.ZERO) > 0) {
                    log.info("薪资单位未知，使用日薪: {}", employee.getDailySalary());
                    return employee.getDailySalary();
                } else if (employee.getMonthlySalary() != null && employee.getMonthlySalary().compareTo(BigDecimal.ZERO) > 0) {
                    log.info("薪资单位未知，使用月薪: {}", employee.getMonthlySalary());
                    return employee.getMonthlySalary();
                } else if (employee.getHourlySalary() != null && employee.getHourlySalary().compareTo(BigDecimal.ZERO) > 0) {
                    log.info("薪资单位未知，使用时薪: {}", employee.getHourlySalary());
                    return employee.getHourlySalary();
                }
                return BigDecimal.ZERO;
        }
    }



    /**
     * 更新服务周期汇总信息
     */
    private void updateServicePeriodSummary(Long servicePeriodId)
    {
        log.info("更新服务周期汇总信息: servicePeriodId={}", servicePeriodId);
        
        List<ServicePeriodEmployee> employees = servicePeriodEmployeeMapper.selectServicePeriodEmployeesByPeriodId(servicePeriodId);
        
        BigDecimal totalCost = employees.stream()
                .map(ServicePeriodEmployee::getTotalCost)
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .setScale(2, BigDecimal.ROUND_HALF_UP);

        ServicePeriod servicePeriod = servicePeriodMapper.selectServicePeriodByServicePeriodId(servicePeriodId);
        if (servicePeriod != null) {
            // 计算总放款金额：如果有贷款倍数且不为1则使用倍数，否则使用人工成本
            BigDecimal totalLoanAmount;
            BigDecimal multiplier = servicePeriod.getLoanMultiplier();
            
            log.info("计算贷款金额: totalCost={}, multiplier={}", totalCost, multiplier);
            
            if (multiplier != null && 
                multiplier.compareTo(BigDecimal.ZERO) > 0 &&
                multiplier.compareTo(BigDecimal.ONE) != 0) {
                // 有倍数且不等于1，使用倍数计算
                totalLoanAmount = totalCost.multiply(multiplier).setScale(2, BigDecimal.ROUND_HALF_UP);
                log.info("使用倍数计算: {} * {} = {}", totalCost, multiplier, totalLoanAmount);
            } else {
                // 没有倍数或倍数为1时，贷款金额等于人工成本
                totalLoanAmount = totalCost.setScale(2, BigDecimal.ROUND_HALF_UP);
                log.info("使用人工成本: {}", totalLoanAmount);
            }

            servicePeriod.setTotalLaborCost(totalCost);
            servicePeriod.setTotalLoanAmount(totalLoanAmount);
            servicePeriod.setEmployeeCount(employees.size());
            servicePeriod.setUpdateTime(DateUtils.getNowDate());
            
            int updateResult = servicePeriodMapper.updateServicePeriod(servicePeriod);
            log.info("更新服务周期汇总完成: servicePeriodId={}, totalCost={}, totalLoanAmount={}, employeeCount={}, updateResult={}", 
                    servicePeriodId, totalCost, totalLoanAmount, employees.size(), updateResult);
        } else {
            log.warn("服务周期不存在: servicePeriodId={}", servicePeriodId);
        }
    }

    // ==================== 服务周期贷款管理 ====================

    @Override
    public List<ServicePeriodLoan> getServicePeriodLoans(Long servicePeriodId)
    {
        return servicePeriodLoanService.selectServicePeriodLoansByPeriodId(servicePeriodId);
    }

    @Override
    public int updateServicePeriodLoan(ServicePeriodLoan servicePeriodLoan)
    {
        return servicePeriodLoanService.updateServicePeriodLoan(servicePeriodLoan);
    }

    @Override
    public int deleteServicePeriodLoanByLinkId(Long linkId)
    {
        return servicePeriodLoanService.deleteServicePeriodLoanByLinkId(linkId);
    }

    @Override
    public Map<String, Object> applyLoanBasedOnAttendance(Long servicePeriodId, Map<String, Object> loanRequest)
    {
        return servicePeriodLoanService.applyLoanBasedOnAttendance(servicePeriodId, loanRequest);
    }

    @Override
    public Map<String, Object> calculateLoanAmountBasedOnAttendance(Long servicePeriodId)
    {
        return servicePeriodLoanService.calculateLoanAmountBasedOnAttendance(servicePeriodId);
    }

    @Override
    public Map<String, Object> validateLoanAmountCalculation(Long servicePeriodId, BigDecimal requestedAmount)
    {
        return servicePeriodLoanService.validateLoanAmountCalculation(servicePeriodId, requestedAmount);
    }

    @Override
    public Map<String, Object> selectBankFinancingByContractTerm(Long servicePeriodId, Integer contractTermMonths)
    {
        return servicePeriodLoanService.selectBankFinancingByContractTerm(servicePeriodId, contractTermMonths);
    }

    @Override
    public Map<String, Object> generateServicePeriodLoanReport(Long servicePeriodId, String reportType)
    {
        return servicePeriodLoanService.generateServicePeriodLoanReport(servicePeriodId, reportType);
    }

    @Override
    public Map<String, Object> exportLoanAttendanceReport(Long servicePeriodId, String format)
    {
        return servicePeriodLoanService.exportLoanAttendanceReport(servicePeriodId, format);
    }

    @Override
    @Transactional
    public Map<String, Object> fixSalaryCalculationData(Long servicePeriodId)
    {
        log.info("开始修复服务周期薪资计算数据: servicePeriodId={}", servicePeriodId);
        
        Map<String, Object> result = new HashMap<>();
        int successCount = 0;
        int totalCount = 0;
        List<String> errors = new ArrayList<>();
        
        try {
            // 获取所有员工分配记录
            List<ServicePeriodEmployee> employees = servicePeriodEmployeeMapper.selectServicePeriodEmployeesByPeriodId(servicePeriodId);
            totalCount = employees.size();
            
            if (totalCount == 0) {
                result.put("message", "该服务周期没有员工分配记录");
                result.put("successCount", 0);
                result.put("totalCount", 0);
                result.put("success", true);
                return result;
            }
            
            for (ServicePeriodEmployee assignment : employees) {
                try {
                    // 获取员工信息
                    EmployeeInfo employee = employeeInfoMapper.selectEmployeeInfoByEmployeeId(assignment.getEmployeeId());
                    if (employee == null) {
                        errors.add("员工ID " + assignment.getEmployeeId() + ": 员工信息不存在");
                        continue;
                    }
                    
                    // 重新计算正确的日薪标准
                    BigDecimal correctDailySalary = getEmployeeDailySalary(employee);
                    BigDecimal correctTotalCost = correctDailySalary.multiply(BigDecimal.valueOf(assignment.getWorkDays())).setScale(2, BigDecimal.ROUND_HALF_UP);
                    
                    // 检查是否需要修复
                    boolean needFix = false;
                    if (assignment.getAssignedSalary().compareTo(correctDailySalary) != 0) {
                        log.info("员工{}的分配薪资需要修复: {} -> {}", 
                                assignment.getEmployeeId(), assignment.getAssignedSalary(), correctDailySalary);
                        needFix = true;
                    }
                    if (assignment.getTotalCost().compareTo(correctTotalCost) != 0) {
                        log.info("员工{}的总成本需要修复: {} -> {}", 
                                assignment.getEmployeeId(), assignment.getTotalCost(), correctTotalCost);
                        needFix = true;
                    }
                    
                    if (needFix) {
                        // 更新记录
                        assignment.setAssignedSalary(correctDailySalary);
                        assignment.setTotalCost(correctTotalCost);
                        assignment.setUpdateTime(DateUtils.getNowDate());
                        
                        int updateResult = servicePeriodEmployeeMapper.updateServicePeriodEmployee(assignment);
                        if (updateResult > 0) {
                            successCount++;
                            log.info("成功修复员工{}的薪资数据", assignment.getEmployeeId());
                        } else {
                            errors.add("员工ID " + assignment.getEmployeeId() + ": 更新数据库失败");
                        }
                    } else {
                        successCount++; // 数据正确，不需要修复
                    }
                    
                } catch (Exception e) {
                    log.error("修复员工{}薪资数据时发生异常", assignment.getEmployeeId(), e);
                    errors.add("员工ID " + assignment.getEmployeeId() + ": " + e.getMessage());
                }
            }
            
            // 重新计算服务周期汇总信息
            updateServicePeriodSummary(servicePeriodId);
            
            result.put("successCount", successCount);
            result.put("totalCount", totalCount);
            result.put("errors", errors);
            result.put("success", errors.isEmpty());
            result.put("message", String.format("修复完成: 成功处理%d个员工，失败%d个员工", successCount, errors.size()));
            
            log.info("薪资数据修复完成: servicePeriodId={}, 成功={}, 总数={}", servicePeriodId, successCount, totalCount);
            
        } catch (Exception e) {
            log.error("修复薪资计算数据失败: servicePeriodId={}", servicePeriodId, e);
            result.put("successCount", 0);
            result.put("totalCount", totalCount);
            List<String> errorList = new ArrayList<>();
            errorList.add("修复过程发生异常: " + e.getMessage());
            result.put("errors", errorList);
            result.put("success", false);
            result.put("message", "修复失败: " + e.getMessage());
        }
        
        return result;
    }
}