<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台（PHP版）
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码，建议反馈是我们前进的动力
// | 开源版本可自由商用，可去除界面版权logo
// | gitee下载：https://gitee.com/likeshop_gitee/likeadmin
// | github下载：https://github.com/likeshop-github/likeadmin
// | 访问官网：https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------

namespace app\adminapi\logic\master_worker;


use app\common\enum\worker\WorkerAccountLogEnum;
use app\common\logic\WorkerAccountLogLogic;
use app\common\model\finance\MasterWorkerCaseOutLog;
use app\common\model\financial\FinancialPaymentRecords;
use app\common\model\financial\MasterSettlementDetails;
use app\common\model\master_worker\EngineerSettlement;
use app\common\logic\BaseLogic;
use app\common\model\master_worker\MasterWorker;
use think\facade\Db;


/**
 * EngineerSettlement逻辑
 * Class EngineerSettlementLogic
 * @package app\adminapi\logic
 */
class EngineerSettlementLogic extends BaseLogic
{


    /**
     * @notes 添加
     * @param array $params
     * @return bool
     * @author likeadmin
     * @date 2024/11/15 17:21
     */
    public static function add(array $params, $adminId): bool
    {
        Db::startTrans();
        try {
            foreach ($params as $param) {
                //$param['payment_status'] == 1  默认上传的都是已经打款了
                $engineerSettlement = EngineerSettlement::where('master_worker_id', $param['master_worker_id'])
                    ->where('batch_number', $param['batch_number'])
                    ->where('is_export', 1)
                    ->where('is_deduction', 0)
                    ->where('payment_status', 0)
                    ->findOrEmpty();
                if(!$engineerSettlement->isEmpty()){

                    $masterWorker = MasterWorker::where('id', $param['master_worker_id'])->where('worker_number', $param['worker_number'])->find();
                    if($masterWorker && $masterWorker->user_money >= $param['total_settlement_amount']){
                        //$masterWorker->user_money = $masterWorker->user_money - $param['total_settlement_amount'];
                        //$masterWorker->save();
                        //实发扣款
                        if($param['final_settlement_amount']){
                            $final_res = WorkerAccountLogLogic::masterAccountLog($param['master_worker_id'],(float)$param['final_settlement_amount'],WorkerAccountLogEnum::UM_DEC_ADMIN,WorkerAccountLogEnum::DEC, '实发扣款','',[
                                'engineerSettlementId'=>$engineerSettlement->id,
                                'batch_number'=>$param['batch_number'],
                            ]);
                            if($final_res->id){
                                MasterSettlementDetails::create([
                                    'account_log_id' => $final_res->id,
                                    'payment_time' => $param['settlement_time']??date('Y-m-d H:i:s'),
                                    'batch_number' => $param['batch_number'],
                                    'status' => 3,
                                    'master_worker_id' => $param['master_worker_id'],
                                    'amount_change' => -(float)$param['final_settlement_amount'],
                                    'change_time' => time(),
                                    'remark' => '实发扣款'
                                ]);
                            }
                        }
                        //直接扣款
                        if($param['deduction_amount']){
                            $deduction_res = WorkerAccountLogLogic::masterAccountLog($param['master_worker_id'],(float)$param['deduction_amount'],WorkerAccountLogEnum::UM_DEC_ADMIN,WorkerAccountLogEnum::DEC, '直接扣款','',[
                                'engineerSettlementId'=>$engineerSettlement->id,
                                'batch_number'=>$param['batch_number'],
                            ]);
                            if($deduction_res->id){
                                MasterSettlementDetails::create([
                                    'account_log_id' => $deduction_res->id,
                                    'payment_time' => $param['settlement_time']??date('Y-m-d H:i:s'),
                                    'batch_number' => $param['batch_number'],
                                    'status' => 3,
                                    'master_worker_id' => $param['master_worker_id'],
                                    'amount_change' => -(float)$param['deduction_amount'],
                                    'change_time' => time(),
                                    'remark' => '直接扣款'
                                ]);
                            }
                        }
                        // 提现记录
                        $case_remark = '应发：'.$param['total_settlement_amount'].($param['deduction_amount']>0?'，扣款：'.$param['deduction_amount'].'，扣款说明：'.$param['deduction_describe']:'').'，实发：'.$param['final_settlement_amount'];
                        MasterWorkerCaseOutLog::create([
                            'sn' => generate_sn(MasterWorkerCaseOutLog::class,'sn'),
                            'worker_id' => $masterWorker->id,
                            'title' => '财务打款',
                            'change_amount' => $param['total_settlement_amount'],
                            'review_status' => 3,
                            'admin_id' => $adminId,
                            'remark' => '财务打款-'.$case_remark,
                            'create_time' => time(),
                            'update_time' => time(),
                        ]);

                        $engineerSettlement->deduction_amount = $param['deduction_amount']??0;
                        $engineerSettlement->deduction_describe = $param['deduction_describe']??'';
                        $engineerSettlement->final_settlement_amount = $param['final_settlement_amount']??0;
                        $engineerSettlement->settlement_time = $param['settlement_time']??date('Y-m-d H:i:s');
                        $engineerSettlement->settlement_details_remarks = $param['settlement_details_remarks']??'';
                        $engineerSettlement->new_balance = $masterWorker->user_money;
                        $engineerSettlement->payment_status = 1;
                        $engineerSettlement->is_export = 2;
                        $engineerSettlement->admin_id = $adminId;
                        $engineerSettlement->is_deduction = 1;
                        $engineerSettlement->save();

                        MasterSettlementDetails::where('master_worker_id', $param['master_worker_id'])
                            ->where('batch_number', $param['batch_number'])
                            ->where('status', 2)
                            ->update([
                                'payment_time' => $param['settlement_time']??date('Y-m-d H:i:s'),
                                'status'=>3, 'remark'=>''
                            ]);

                    }else{

                        $engineerSettlement->deduction_amount = $param['deduction_amount']??0;
                        $engineerSettlement->deduction_describe = $param['deduction_describe']??'';
                        $engineerSettlement->final_settlement_amount = $param['final_settlement_amount']??0;
                        $engineerSettlement->settlement_time = $param['settlement_time']??date('Y-m-d H:i:s');
                        $engineerSettlement->settlement_details_remarks = ($param['settlement_details_remarks']??'').'-余额不足';
                        $engineerSettlement->new_balance = $masterWorker->user_money;
                        $engineerSettlement->payment_status = 1;
                        $engineerSettlement->is_export = 2;
                        $engineerSettlement->admin_id = $adminId;
                        $engineerSettlement->is_deduction = 2;
                        $engineerSettlement->save();

                        //throw new \Exception('工程师不存在、余额不足');
                    }
                }
            }

            $payment_num = MasterSettlementDetails::where('batch_number', $params[0]['batch_number'])->where('status','<', 3)->count('id');
            FinancialPaymentRecords::where('batch_number', $params[0]['batch_number'])
                ->where('upload_status', 1)
                ->where('payment_status', 1)
                ->update([
                    'upload_status' => 3,
                    'payment_status'=> $payment_num>0?2:3
                ]);

            Db::commit();
            return true;
        } catch (\Exception $e) {
            Db::rollback();
            self::setError($e->getMessage());
            return false;
        }
    }


    /**
     * @notes 编辑
     * @param array $params
     * @return bool
     * @author likeadmin
     * @date 2024/11/15 17:21
     */
    public static function edit(array $params): bool
    {
        Db::startTrans();
        try {
            EngineerSettlement::where('id', $params['id'])->update([
                'master_worker_id' => $params['master_worker_id'],
                'worker_number' => $params['worker_number'],
                'engineer_name' => $params['engineer_name'],
                'original_balance' => $params['original_balance'],
                'total_settlement_amount' => $params['total_settlement_amount'],
                'deduction_amount' => $params['deduction_amount'],
                'final_settlement_amount' => $params['final_settlement_amount'],
                'settlement_time' => $params['settlement_time'],
                'settlement_details_remarks' => $params['settlement_details_remarks'],
            ]);

            Db::commit();
            return true;
        } catch (\Exception $e) {
            Db::rollback();
            self::setError($e->getMessage());
            return false;
        }
    }


    /**
     * @notes 删除
     * @param array $params
     * @return bool
     * @author likeadmin
     * @date 2024/11/15 17:21
     */
    public static function delete(array $params): bool
    {
        return EngineerSettlement::destroy($params['id']);
    }


    /**
     * @notes 获取详情
     * @param $params
     * @return array
     * @author likeadmin
     * @date 2024/11/15 17:21
     */
    public static function detail($params): array
    {
        return EngineerSettlement::findOrEmpty($params['id'])->toArray();
    }
    public static function downloadLists(): array
    {
        return [EngineerSettlement::where('id','>',0)
            ->field(['id', 'master_worker_id', 'worker_number', 'engineer_name', 'original_balance', 'total_settlement_amount', 'deduction_amount', 'final_settlement_amount', 'settlement_time', 'settlement_details_remarks'])
            ->order(['id' => 'desc'])
            ->select()
            ->toArray()[0]];
    }

    public static function engineerSettlementValidate($params)
    {
        //
        //上传表格中所有批号必须相同
        //$engineerSettlement 中每条都不能为空
        // $masterWorker->user_money >= $param['total_settlement_amount']
        //$param['total_settlement_amount'] = $params['final_settlement_amount']+deduction_amount;
        // 该批次是否为待上传
        try {
            if(empty($params)) throw new \Exception('表格数据为空');
            $master_worker_ids = array_column($params, 'master_worker_id');
            //上传表格中所有 master_worker_id 不能存在重复
            array_filter(array_count_values($master_worker_ids), function($count) {
                if($count>1) throw new \Exception('上传表格中所有工程师不能存在重复');
            });
            //上传表格中所有批号必须相同
            if(count(array_unique(array_column($params, 'batch_number')))>1){
                throw new \Exception('上传表格中所有批号必须同批次');
            }
            $batch_number = $params[0]['batch_number'];
            // 该批次是否为待上传
            $financialRecords = FinancialPaymentRecords::where('batch_number', $batch_number)->where('upload_status', 1)->findOrEmpty();
            if($financialRecords->isEmpty()){
                throw new \Exception('该批次不存在或已取消/已上传，禁止上传');
            }
            // 每条数据在表 EngineerSettlement 中不能为空即 下载记录必须存在
            $engineer_worker_ids = EngineerSettlement::where('batch_number', $batch_number)
                ->where('is_export', 1)
                ->where('is_deduction', 0)
                ->where('payment_status', 0)
                ->column('master_worker_id');
            $masterWorkers = MasterWorker::where('id', 'in',$master_worker_ids)->column('user_money', 'id');

            foreach ($params as &$param) {
                $param['deduction_amount'] = $param['deduction_amount']??0;
                $param['deduction_describe'] = $param['deduction_describe']??'';
                $param['settlement_details_remarks'] = $param['settlement_details_remarks']??'';

                if(!isset($param['total_settlement_amount']) || $param['total_settlement_amount']<0){
                    throw new \Exception('应付金额不能为空或负数:'.$param['master_worker_id']);
                }
                if(!isset($param['final_settlement_amount']) || $param['final_settlement_amount']<0){
                    throw new \Exception('实付金额不能为空或负数:'.$param['master_worker_id']);
                }
                if(isset($param['deduction_amount']) && $param['deduction_amount']<0){
                    throw new \Exception('扣款金额不能为负数:'.$param['master_worker_id']);
                }
                if($param['deduction_amount'] > 0 && (!isset($param['deduction_describe']) || empty($param['deduction_describe']))){
                    throw new \Exception('扣款存在，扣款说明不能为空:'.$param['master_worker_id']);
                }
                if(!in_array($param['master_worker_id'], $engineer_worker_ids)) throw new \Exception('下载记录不存在:'.$param['master_worker_id']);
                //判断日期时间格式是否正确 2024/1/1 00:00:00 或 2024-1-1 00:00:00
                if(
                    isset($param['settlement_time'])
                    && !preg_match('/^[0-9]{4}\/[0-9]{1,2}\/[0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}$/', $param['settlement_time'])
                    && !preg_match('/^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}$/', $param['settlement_time'])
                    && !preg_match('/^[0-9]{4}\/[0-9]{1,2}\/[0-9]{1,2}$/', $param['settlement_time'])
                    && !preg_match('/^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}$/', $param['settlement_time'])
                ){
                    throw new \Exception('日期时间格式错误:'.$param['master_worker_id']);
                }
                $param['settlement_time'] = isset($param['settlement_time'])?date('Y-m-d H:i:s', strtotime($param['settlement_time'])):date('Y-m-d H:i:s');
                if(!is_numeric($param['original_balance']) || !is_numeric($param['total_settlement_amount']) || !is_numeric($param['deduction_amount']) || !is_numeric($param['final_settlement_amount'])){
                    throw new \Exception('金额格式错误:'.$param['master_worker_id']);
                }
                if (bccomp((float)$param['total_settlement_amount'], bcadd((float)$param['final_settlement_amount'], (float)$param['deduction_amount'], 2), 2) !== 0) {
                    throw new \Exception('金额计算错误:' . $param['master_worker_id']);
                }
                if(!preg_match('/^[0-9]*$/', $param['worker_number'])){
                    throw new \Exception('工程师编号格式错误:'.$param['master_worker_id']);
                }
                if(!preg_match('/^[0-9]*$/', $param['master_worker_id'])){
                    throw new \Exception('工程师ID格式错误:'.$param['master_worker_id']);
                }
                if($masterWorkers[$param['master_worker_id']] < $param['total_settlement_amount']) throw new \Exception('余额不足-'.$param['master_worker_id']);
            }
            return $params;
        } catch (\Exception $e) {
            throw new \Exception($e->getMessage());
        }

    }
    public static function insertSettlementDetails()
    {
        $insert_sql = "INSERT INTO la_master_settlement_details (account_log_id, master_worker_id, amount_change, change_time)
                        SELECT
                        a.id,
                        a.worker_id AS master_worker_id,
                            CASE
                            WHEN a.change_amount > 0 AND a.action = 1 THEN a.change_amount
                                WHEN a.change_amount > 0 AND a.action = 2 THEN -a.change_amount
                                ELSE 0
                            END AS amount_change,
                            a.create_time
                        FROM
                            `la_master_worker_account_log` a
                        LEFT JOIN
                            `la_master_settlement_details` b ON a.id = b.account_log_id
                        WHERE
                            a.change_object = 1
                            AND b.account_log_id IS NULL";

        return Db::execute($insert_sql);
    }



}