package com.ruoyi.credit.service.impl;

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 com.ruoyi.credit.domain.Contract;
import com.ruoyi.credit.domain.ServicePeriod;
import com.ruoyi.credit.domain.ServicePeriodEmployee;
import com.ruoyi.credit.domain.ServicePeriodLoan;
import com.ruoyi.credit.mapper.ContractMapper;
import com.ruoyi.credit.mapper.ServicePeriodMapper;
import com.ruoyi.credit.mapper.ServicePeriodEmployeeMapper;
import com.ruoyi.credit.mapper.ServicePeriodLoanMapper;
import com.ruoyi.credit.service.IDepartmentDataConsistencyService;
import com.ruoyi.framework.security.validator.DepartmentPermissionValidator;

/**
 * 部门数据一致性验证服务实现
 * 
 * 负责验证关联数据的部门一致性，确保服务周期与合同、员工与服务周期、债权与合同等关联数据
 * 都属于同一个部门，防止跨部门数据关联导致的数据泄露和权限问题。
 * 
 * @author ruoyi
 * @date 2025-01-12
 */
@Service
public class DepartmentDataConsistencyServiceImpl implements IDepartmentDataConsistencyService
{
    private static final Logger log = LoggerFactory.getLogger(DepartmentDataConsistencyServiceImpl.class);

    @Autowired
    private DepartmentPermissionValidator departmentPermissionValidator;

    @Autowired
    private ContractMapper contractMapper;

    @Autowired
    private ServicePeriodMapper servicePeriodMapper;

    @Autowired
    private ServicePeriodEmployeeMapper servicePeriodEmployeeMapper;

    @Autowired
    private ServicePeriodLoanMapper servicePeriodLoanMapper;

    /**
     * 验证服务周期与合同的部门一致性
     * 
     * @param contractId 合同ID
     * @param servicePeriodId 服务周期ID
     * @return 验证结果
     */
    @Override
    public boolean validateServicePeriodContractConsistency(Long contractId, Long servicePeriodId)
    {
        log.info("验证服务周期与合同的部门一致性: contractId={}, servicePeriodId={}", contractId, servicePeriodId);
        
        try {
            departmentPermissionValidator.validateServicePeriodContractConsistency(contractId, servicePeriodId);
            log.info("服务周期与合同部门一致性验证通过: contractId={}, servicePeriodId={}", contractId, servicePeriodId);
            return true;
        } catch (Exception e) {
            log.error("服务周期与合同部门一致性验证失败: contractId={}, servicePeriodId={}, error={}", 
                     contractId, servicePeriodId, e.getMessage());
            return false;
        }
    }

    /**
     * 验证员工与服务周期的部门一致性
     * 
     * @param employeeId 员工ID
     * @param servicePeriodId 服务周期ID
     * @return 验证结果
     */
    @Override
    public boolean validateEmployeeServicePeriodConsistency(Long employeeId, Long servicePeriodId)
    {
        log.info("验证员工与服务周期的部门一致性: employeeId={}, servicePeriodId={}", employeeId, servicePeriodId);
        
        try {
            departmentPermissionValidator.validateEmployeeServicePeriodConsistency(employeeId, servicePeriodId);
            log.info("员工与服务周期部门一致性验证通过: employeeId={}, servicePeriodId={}", employeeId, servicePeriodId);
            return true;
        } catch (Exception e) {
            log.error("员工与服务周期部门一致性验证失败: employeeId={}, servicePeriodId={}, error={}", 
                     employeeId, servicePeriodId, e.getMessage());
            return false;
        }
    }

    /**
     * 验证债权与合同的部门一致性
     * 
     * @param contractId 合同ID
     * @param creditId 债权ID
     * @return 验证结果
     */
    @Override
    public boolean validateCreditContractConsistency(Long contractId, Long creditId)
    {
        log.info("验证债权与合同的部门一致性: contractId={}, creditId={}", contractId, creditId);
        
        try {
            departmentPermissionValidator.validateCreditContractConsistency(contractId, creditId);
            log.info("债权与合同部门一致性验证通过: contractId={}, creditId={}", contractId, creditId);
            return true;
        } catch (Exception e) {
            log.error("债权与合同部门一致性验证失败: contractId={}, creditId={}, error={}", 
                     contractId, creditId, e.getMessage());
            return false;
        }
    }

    /**
     * 批量验证服务周期员工的部门一致性
     * 
     * @param servicePeriodId 服务周期ID
     * @return 验证结果
     */
    @Override
    @Transactional(readOnly = true)
    public boolean validateAllEmployeesInServicePeriod(Long servicePeriodId)
    {
        log.info("批量验证服务周期员工的部门一致性: servicePeriodId={}", servicePeriodId);
        
        try {
            // 获取服务周期的所有员工
            java.util.List<ServicePeriodEmployee> employees = servicePeriodEmployeeMapper.selectServicePeriodEmployeesByPeriodId(servicePeriodId);
            
            if (employees == null || employees.isEmpty()) {
                log.info("服务周期没有关联员工，跳过验证: servicePeriodId={}", servicePeriodId);
                return true;
            }

            // 逐个验证每个员工的部门一致性
            for (ServicePeriodEmployee employee : employees) {
                if (!validateEmployeeServicePeriodConsistency(employee.getEmployeeId(), servicePeriodId)) {
                    log.error("员工部门一致性验证失败: employeeId={}, servicePeriodId={}", 
                             employee.getEmployeeId(), servicePeriodId);
                    return false;
                }
            }

            log.info("所有员工部门一致性验证通过: servicePeriodId={}, employeeCount={}", servicePeriodId, employees.size());
            return true;

        } catch (Exception e) {
            log.error("批量验证员工部门一致性失败: servicePeriodId={}, error={}", servicePeriodId, e.getMessage(), e);
            return false;
        }
    }

    /**
     * 验证服务周期贷款的完整部门一致性
     * 包括：服务周期-合同一致性、员工-服务周期一致性
     * 
     * @param servicePeriodLoan 服务周期贷款对象
     * @return 验证结果
     */
    @Override
    @Transactional(readOnly = true)
    public boolean validateServicePeriodLoanConsistency(ServicePeriodLoan servicePeriodLoan)
    {
        log.info("验证服务周期贷款的完整部门一致性: loanId={}, servicePeriodId={}", 
                servicePeriodLoan.getLinkId(), servicePeriodLoan.getServicePeriodId());
        
        try {
            Long servicePeriodId = servicePeriodLoan.getServicePeriodId();
            
            // 1. 获取服务周期信息
            ServicePeriod servicePeriod = servicePeriodMapper.selectServicePeriodByServicePeriodId(servicePeriodId);
            if (servicePeriod == null) {
                log.error("服务周期不存在: servicePeriodId={}", servicePeriodId);
                return false;
            }

            // 2. 验证服务周期与合同的部门一致性
            if (servicePeriod.getContractId() != null) {
                if (!validateServicePeriodContractConsistency(servicePeriod.getContractId(), servicePeriodId)) {
                    return false;
                }
            }

            // 3. 验证所有员工与服务周期的部门一致性
            if (!validateAllEmployeesInServicePeriod(servicePeriodId)) {
                return false;
            }

            log.info("服务周期贷款完整部门一致性验证通过: loanId={}", servicePeriodLoan.getLinkId());
            return true;

        } catch (Exception e) {
            log.error("验证服务周期贷款部门一致性失败: loanId={}, error={}", 
                     servicePeriodLoan.getLinkId(), e.getMessage(), e);
            return false;
        }
    }

    /**
     * 验证合同相关的所有数据部门一致性
     * 包括：合同下的所有服务周期、服务周期下的所有员工、相关的债权记录
     * 
     * @param contractId 合同ID
     * @return 验证结果
     */
    @Override
    @Transactional(readOnly = true)
    public boolean validateContractRelatedDataConsistency(Long contractId)
    {
        log.info("验证合同相关的所有数据部门一致性: contractId={}", contractId);
        
        try {
            // 1. 验证合同存在
            Contract contract = contractMapper.selectContractByContractId(contractId);
            if (contract == null) {
                log.error("合同不存在: contractId={}", contractId);
                return false;
            }

            // 2. 获取合同下的所有服务周期
            java.util.List<ServicePeriod> servicePeriods = servicePeriodMapper.selectServicePeriodsByContractId(contractId);
            
            if (servicePeriods == null || servicePeriods.isEmpty()) {
                log.info("合同没有关联服务周期，跳过验证: contractId={}", contractId);
                return true;
            }

            // 3. 验证每个服务周期的部门一致性
            for (ServicePeriod servicePeriod : servicePeriods) {
                // 验证服务周期与合同的一致性
                if (!validateServicePeriodContractConsistency(contractId, servicePeriod.getServicePeriodId())) {
                    return false;
                }

                // 验证服务周期下所有员工的一致性
                if (!validateAllEmployeesInServicePeriod(servicePeriod.getServicePeriodId())) {
                    return false;
                }
            }

            log.info("合同相关数据部门一致性验证通过: contractId={}, servicePeriodCount={}", 
                    contractId, servicePeriods.size());
            return true;

        } catch (Exception e) {
            log.error("验证合同相关数据部门一致性失败: contractId={}, error={}", contractId, e.getMessage(), e);
            return false;
        }
    }

    /**
     * 修复数据部门不一致问题
     * 将指定记录的部门ID更新为目标部门ID
     * 
     * @param tableName 表名
     * @param recordId 记录ID
     * @param targetDeptId 目标部门ID
     * @return 修复结果
     */
    @Override
    @Transactional
    public boolean fixDepartmentInconsistency(String tableName, Long recordId, Long targetDeptId)
    {
        log.info("修复数据部门不一致问题: tableName={}, recordId={}, targetDeptId={}", 
                tableName, recordId, targetDeptId);
        
        try {
            // 这里应该根据表名调用相应的更新方法
            // 为了安全起见，只允许修复特定的业务表
            switch (tableName) {
                case "dc_service_period":
                    return fixServicePeriodDepartment(recordId, targetDeptId);
                case "dc_service_period_employee":
                    return fixServicePeriodEmployeeDepartment(recordId, targetDeptId);
                case "dc_service_period_loan":
                    return fixServicePeriodLoanDepartment(recordId, targetDeptId);
                default:
                    log.error("不支持修复的表: {}", tableName);
                    return false;
            }

        } catch (Exception e) {
            log.error("修复数据部门不一致问题失败: tableName={}, recordId={}, targetDeptId={}, error={}", 
                     tableName, recordId, targetDeptId, e.getMessage(), e);
            return false;
        }
    }

    /**
     * 修复服务周期的部门ID
     */
    private boolean fixServicePeriodDepartment(Long servicePeriodId, Long targetDeptId)
    {
        try {
            ServicePeriod servicePeriod = servicePeriodMapper.selectServicePeriodByServicePeriodId(servicePeriodId);
            if (servicePeriod == null) {
                return false;
            }

            servicePeriod.setDeptId(targetDeptId);
            int result = servicePeriodMapper.updateServicePeriod(servicePeriod);
            
            log.info("修复服务周期部门ID: servicePeriodId={}, targetDeptId={}, result={}", 
                    servicePeriodId, targetDeptId, result > 0);
            return result > 0;

        } catch (Exception e) {
            log.error("修复服务周期部门ID失败: servicePeriodId={}, targetDeptId={}", 
                     servicePeriodId, targetDeptId, e);
            return false;
        }
    }

    /**
     * 修复服务周期员工的部门ID
     */
    private boolean fixServicePeriodEmployeeDepartment(Long employeeId, Long targetDeptId)
    {
        try {
            // 这里需要根据实际的员工表结构来实现
            // 由于员工可能在员工信息表中，需要调用相应的服务
            log.info("修复员工部门ID: employeeId={}, targetDeptId={}", employeeId, targetDeptId);
            // TODO: 实现员工部门ID修复逻辑
            return true;

        } catch (Exception e) {
            log.error("修复员工部门ID失败: employeeId={}, targetDeptId={}", employeeId, targetDeptId, e);
            return false;
        }
    }

    /**
     * 修复服务周期贷款的部门ID
     */
    private boolean fixServicePeriodLoanDepartment(Long loanId, Long targetDeptId)
    {
        try {
            ServicePeriodLoan loan = servicePeriodLoanMapper.selectServicePeriodLoanByLinkId(loanId);
            if (loan == null) {
                return false;
            }

            loan.setDeptId(targetDeptId);
            int result = servicePeriodLoanMapper.updateServicePeriodLoan(loan);
            
            log.info("修复服务周期贷款部门ID: loanId={}, targetDeptId={}, result={}", 
                    loanId, targetDeptId, result > 0);
            return result > 0;

        } catch (Exception e) {
            log.error("修复服务周期贷款部门ID失败: loanId={}, targetDeptId={}", loanId, targetDeptId, e);
            return false;
        }
    }
}