package com.fs.doctor.service.impl;

import com.fs.audit.domain.AuditFlow;
import com.fs.audit.dto.AuditRequestDTO;
import com.fs.audit.enums.AuditStatus;
import com.fs.audit.service.AuditService;
import com.fs.audit.utils.AuditFlowUtils;
import com.fs.common.BeanCopyUtils;
import com.fs.common.config.LoginContextManager;
import com.fs.common.core.domain.entity.SysUser;
import com.fs.common.core.domain.model.LoginUser;
import com.fs.common.enums.UserTypeEnum;
import com.fs.common.exception.ServiceException;
import com.fs.common.utils.SecurityUtils;
import com.fs.common.utils.StringUtils;
import com.fs.company.domain.CompanyUser;
import com.fs.company.service.ICompanyUserService;
import com.fs.doctor.domain.DoctorBalanceLog;
import com.fs.doctor.domain.WithdrawRecords;
import com.fs.doctor.enums.WithdrawAuditStatusEnum;
import com.fs.doctor.enums.WithdrawPaymentStatusEnum;
import com.fs.doctor.mapper.WithdrawRecordsMapper;
import com.fs.doctor.service.IDoctorBalanceLogService;
import com.fs.doctor.service.IWithdrawRecordsService;
import com.fs.doctor.vo.DoctorRecordAuditInfoVO;
import com.fs.provider.enums.BalanceChangeTypeEnum;
import com.fs.system.service.ISysUserService;
import com.fs.task.enums.ChangeReasonEnum;
import com.fs.task.vo.audit_Info.AuditFlowVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 医生提现记录Service业务层处理
 *
 * @author fs
 * @date 2026-01-27
 */
@Service
public class WithdrawRecordsServiceImpl implements IWithdrawRecordsService {
    @Autowired
    private WithdrawRecordsMapper withdrawRecordsMapper;
    @Autowired
    private AuditService auditService;
    @Autowired
    private IDoctorBalanceLogService doctorBalanceLogService;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private ICompanyUserService companyUserService;

    /**
     * 查询医生提现记录
     *
     * @param withdrawId 医生提现记录主键
     * @return 医生提现记录
     */
    @Override
    public WithdrawRecords selectWithdrawRecordsByWithdrawId(Long withdrawId) {
        return withdrawRecordsMapper.selectWithdrawRecordsByWithdrawId(withdrawId);
    }

    /**
     * 查询医生提现记录列表
     *
     * @param withdrawRecords 医生提现记录
     * @return 医生提现记录
     */
    @Override
    public List<WithdrawRecords> selectWithdrawRecordsList(WithdrawRecords withdrawRecords) {
        return withdrawRecordsMapper.selectWithdrawRecordsList(withdrawRecords);
    }

    /**
     * 新增医生提现记录
     *
     * @param withdrawRecords 医生提现记录
     * @return 结果
     */
    @Override
    public int insertWithdrawRecords(WithdrawRecords withdrawRecords) {
        return withdrawRecordsMapper.insertWithdrawRecords(withdrawRecords);
    }

    /**
     * 修改医生提现记录
     *
     * @param withdrawRecords 医生提现记录
     * @return 结果
     */
    @Override
    public int updateWithdrawRecords(WithdrawRecords withdrawRecords) {
        return withdrawRecordsMapper.updateWithdrawRecords(withdrawRecords);
    }

    /**
     * 批量删除医生提现记录
     *
     * @param withdrawIds 需要删除的医生提现记录主键
     * @return 结果
     */
    @Override
    public int deleteWithdrawRecordsByWithdrawIds(String[] withdrawIds) {
        return withdrawRecordsMapper.deleteWithdrawRecordsByWithdrawIds(withdrawIds);
    }

    /**
     * 删除医生提现记录信息
     *
     * @param withdrawId 医生提现记录主键
     * @return 结果
     */
    @Override
    public int deleteWithdrawRecordsByWithdrawId(String withdrawId) {
        return withdrawRecordsMapper.deleteWithdrawRecordsByWithdrawId(withdrawId);
    }


    /**
     * 提现审核（资金类操作，强约束）
     * <p>
     * ⚠️ 说明：
     * 1. 该接口为【直接审核通过 + 打款完成】
     * 2. 不允许选择审核状态，状态由系统强制指定
     * 3. auditInstanceId 为外部审核流程实例ID，必须存在
     * 4. 未回填 auditInstanceId 或未上传回执，一律禁止审核
     * <p>
     * 前端【只允许】传以下字段：
     * - withdrawId         必填
     * - bankReceiptUrl     必填（银行回执图片URL）
     * - paymentTime        可选（不传则后端补当前时间）
     * - auditRemark        可选
     * <p>
     * 其余字段一律由后端控制，防止越权与资金风险
     */
    @Transactional
    @Override
    public int auditWithdraw(WithdrawRecords withdrawRecords) {

        /* ====================== 1️⃣ 基础参数校验 ====================== */



        // 提现记录ID
        if (withdrawRecords.getWithdrawId() == null) {
            throw new ServiceException("withdrawId不能为空");
        }

        WithdrawRecords targetWithdrawRecords = withdrawRecordsMapper.selectWithdrawRecordsByWithdrawId(withdrawRecords.getWithdrawId());

        if(Objects.isNull(targetWithdrawRecords)){
            throw new ServiceException("提款申请不存在");

        }

        // 审核流程实例ID（⚠️ 外部系统回填，强依赖）
        if (targetWithdrawRecords.getAuditInstanceId() == null) {
            throw new ServiceException("auditInstanceId不能为空，无法执行审核");
        }

        // 银行回执图片（必须）
        if (StringUtils.isEmpty(withdrawRecords.getBankReceiptUrl())) {
            throw new ServiceException("必须上传银行回执图片");
        }

        /* ====================== 2️⃣ 强制业务状态（后端兜底） ====================== */

        // 固定：审核通过
        targetWithdrawRecords.setAuditStatus(
                WithdrawAuditStatusEnum.PASS.getCode().longValue()
        );

        // 固定：打款完成
        targetWithdrawRecords.setPaymentStatus(
                WithdrawPaymentStatusEnum.PAID.getCode().longValue()
        );
        //审核字段
        targetWithdrawRecords.setAuditRemark(withdrawRecords.getAuditRemark());
        targetWithdrawRecords.setAuditTime(new Date());
        targetWithdrawRecords.setAuditorId(LoginContextManager.getCurrentCompanyUserId());
        //打款时间
        targetWithdrawRecords.setPaymentTime(withdrawRecords.getPaymentTime());
        //回执图片
        targetWithdrawRecords.setBankReceiptUrl(withdrawRecords.getBankReceiptUrl());
        /* ====================== 3️⃣ 审核人与时间 ====================== */

        Long currentCompanyUserId = LoginContextManager.getCurrentCompanyUserId();



        /* ====================== 4️⃣ 打款时间处理 ====================== */

        // 前端不传则由后端补当前时间
        if (withdrawRecords.getPaymentTime() == null) {
            targetWithdrawRecords.setPaymentTime(new Date());
        }

        /* ====================== 5️⃣ 更新提现记录（资金关键点） ====================== */

        this.updateWithdrawRecords(targetWithdrawRecords);

        /* ====================== 6️⃣ 调用外部审核流程 ====================== */

        AuditRequestDTO auditRequestDTO = new AuditRequestDTO();
        auditRequestDTO.setAuditId(targetWithdrawRecords.getAuditInstanceId());
        auditRequestDTO.setUserId(currentCompanyUserId);
        auditRequestDTO.setUserType(UserTypeEnum.SALES.getCode());
        auditRequestDTO.setComment(targetWithdrawRecords.getAuditRemark());
        auditRequestDTO.setCompanyId(targetWithdrawRecords.getCompanyId());
        auditRequestDTO.setAction(targetWithdrawRecords.getAuditStatus().intValue());

        auditService.doAudit(auditRequestDTO);


        // 提现记录写入医生积分日志表
        DoctorBalanceLog doctorBalanceLog = new DoctorBalanceLog();
        doctorBalanceLog.setDoctorId(targetWithdrawRecords.getDoctorId());
        doctorBalanceLog.setDoctorName(targetWithdrawRecords.getDoctorName());
        doctorBalanceLog.setChangeMoney(targetWithdrawRecords.getCashAmount());
        doctorBalanceLog.setChangeType(BalanceChangeTypeEnum.DECREASE.getCode());
        //提现无关联任务
        doctorBalanceLog.setRelatedTaskId(null);
        doctorBalanceLog.setChangeReason(ChangeReasonEnum.WITHDRAW.getCode());
        doctorBalanceLog.setCreateAt(new Date());
        doctorBalanceLog.setCompanyId(LoginContextManager.getCurrentCompanyId());
        doctorBalanceLogService.insertDoctorBalanceLog(doctorBalanceLog);
        return 1;
    }


    @Override
    public DoctorRecordAuditInfoVO getRecordAuditInfo(Long withdrawRecordId) {
        DoctorRecordAuditInfoVO doctorRecordAuditInfoVO = new DoctorRecordAuditInfoVO();
        WithdrawRecords withdrawRecords = withdrawRecordsMapper.selectWithdrawRecordsByWithdrawId(withdrawRecordId);
        doctorRecordAuditInfoVO.setWithdrawRecords(withdrawRecords);

        List<AuditFlow> auditFlows = auditService.getAuditFlows(withdrawRecords.getAuditInstanceId());

        List<AuditFlowVO> auditFlowVOS = BeanCopyUtils.copyList(auditFlows, AuditFlowVO.class);
        for (AuditFlowVO auditFlowVO : auditFlowVOS) {

            // 1) 审核状态中文
            auditFlowVO.setStatusName(AuditStatus.fromCode(auditFlowVO.getStatus()).getDesc());

            // 2) 统一算出“要展示的审核人ID”
            //    优先 auditUserId，其次从 auditUserIds 取第一个
            Long displayUserId = auditFlowVO.getAuditUserId();
            if (displayUserId == null) {
                displayUserId = AuditFlowUtils.parseFirstIdFromAuditUserIds(auditFlowVO.getAuditUserIds());
            }

            if (displayUserId == null) {
                auditFlowVO.setAuditUserName("-");
                continue;
            }

            // 3) 统一算出“审核人类型”
            //    VO 约定：0 销售(company_user) / 1 系统用户(sys_user)
            Integer typeCode = auditFlowVO.getAuditUserType();

            // ✅ 如果类型为空：给一个策略
            // - step=0 申请人：你们大概率是系统用户发起 => 默认 1
            // - 其他节点：类型为空就走“先查 sys_user 再查 company_user”兜底
            boolean isStep0 = auditFlowVO.getStepNumber() != null && auditFlowVO.getStepNumber() == 0;

            if (typeCode == null) {
                if (isStep0) {
                    typeCode = 1; // ✅ 申请人默认系统用户（按你们约定）
                } else {
                    // 非 step=0：类型缺失，走兜底双查（下面会处理）
                    typeCode = -1;
                }
            }

            // 4) 根据类型查用户名
            String name = "-";

            if (typeCode == 1) {
                // 系统用户
                SysUser sysUser = sysUserService.selectUserById(displayUserId);
                if (sysUser != null) name = sysUser.getUserName();

            } else if (typeCode == 0) {
                // 销售/公司用户
                CompanyUser cu = companyUserService.selectCompanyUserById(displayUserId);
                if (cu != null) name = cu.getUserName();

            } else {
                // typeCode == -1：兜底双查（先 sys_user 后 company_user）
                SysUser sysUser = sysUserService.selectUserById(displayUserId);
                if (sysUser != null) {
                    name = sysUser.getUserName();
                    // 顺便把类型补回去（可选）
                    auditFlowVO.setAuditUserType(1);
                } else {
                    CompanyUser cu = companyUserService.selectCompanyUserById(displayUserId);
                    if (cu != null) {
                        name = cu.getUserName();
                        auditFlowVO.setAuditUserType(0);
                    }
                }
            }

            auditFlowVO.setAuditUserName(name);
        }

        doctorRecordAuditInfoVO.setFlowList(auditFlowVOS);
        return doctorRecordAuditInfoVO;
    }
}
