<?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\works;

use think\db\Query;
use think\Exception;
use think\facade\Db;
use app\common\enum\RefundEnum;
use app\common\logic\BaseLogic;
use app\common\logic\RefundLogic;
use PhpOffice\PhpSpreadsheet\IOFactory;
use app\common\model\refund\RefundRecord;
use app\common\model\works\GroupServiceWork;
use app\common\model\group_activity\GroupOrder;
use app\workerapi\logic\GroupServiceWorkLogLogic;
use app\common\model\group_activity\GroupUserOrder;
use app\common\model\master_worker\MasterWorkerTemporary;

/**
 * GroupServiceWork逻辑
 * Class GroupServiceWorkLogic
 * @package app\adminapi\logic\works
 */
class GroupServiceWorkLogic extends BaseLogic
{
    /**
     * @notes 编辑
     * @param array $params
     * @return bool
     * @author likeadmin
     * @date 2024/07/10 18:17
     */
    public static function edit(array $params): bool
    {
        Db::startTrans();
        try {
            GroupServiceWork::where('id', $params['id'])->update([
                'address' => $params['address'],
                'appointment_time' => strtotime($params['appointment_time']),
                'remark' => $params['remark'],
            ]);
            Db::commit();
            return true;
        } catch (\Exception $e) {
            Db::rollback();
            self::setError($e->getMessage());
            return false;
        }
    }


    /**
     * 工程师确认上门
     * @param $params
     * @return false|void
     */
    public static function confirmDoor($params)
    {
        Db::startTrans();
        try {
            $work = GroupServiceWork::where(['master_worker_id'=>$params['user_id'],'work_sn'=>$params['work_sn']])->findOrEmpty();
            if($work->isEmpty()){
                throw new Exception('工单不存在');
            }

            if($work->work_status != 3){
                throw new Exception('请勿重复点击');
            }

            $work->finally_door_time = time();//最后上门时间
            $work->work_status = 4;//已上门
            $work->service_status = 1;//服务中
            $work->work_images = $params['work_images'];
            $work->save();

            //添加变更日志
            $work_log = [
                'type' => 3,
                'work_id'=>$work->id,
                'master_worker_id'=>$work->master_worker_id,
                'opera_log'=>'编号['.$params['user_info']['worker_number'].']'.$params['user_info']['real_name'].'于'.date('y-m-d H:i:s',time()).'已上门',
            ];
            GroupServiceWorkLogLogic::add($work_log);
            Db::commit();

            //给客户发送工单验证码
            event('Notice',  [
                'scene_id' => 128,
                'params' => [
                    'user_id' => 0,
                    'mobile' => $work->mobile,
                    'code' => $work->code,
                ]
            ]);
        }
        catch (\Exception $e) {
            Db::rollback();
            self::setError($e->getMessage());
            return false;
        }
    }
    /**
     * 工程师确认服务完成
     * @param $params
     * @return false|void
     */
    public static function confirmServiceFinish($params)
    {
        Db::startTrans();
        try {
            $work = GroupServiceWork::where(['master_worker_id'=>$params['user_id'],'work_sn'=>$params['work_sn']])->findOrEmpty();
            if($work->isEmpty()){
                throw new Exception('工单不存在');
            }
            if($params['code'] != $work->code) {
                throw new Exception('验收码错误');
            }

            if($work->work_status !=4){
                throw new Exception('请勿重复操作');
            }

            $work->finished_time = time();//完成时间
            $work->finished_images = $params['finished_images'];
            $work->user_confirm_status = 5;//用户确认完成
            $work->work_status = 7;//服务工单已完结
            $work->service_status = 3;//工单已完成
            $work->save();

            //添加变更日志
            $work_log = [
                'type' => 4,
                'work_id'=>$work->id,
                'master_worker_id'=>$work->master_worker_id,
                'opera_log'=>'编号['.$params['user_info']['worker_number'].']'.$params['user_info']['real_name'].'于'.date('y-m-d H:i:s',time()).'于'.date('Y-m-d H:i:s',time()).'提交了确认服务完成',
            ];
            GroupServiceWorkLogLogic::add($work_log);
            Db::commit();

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

    public static function againDoor($params)
    {
        Db::startTrans();
        try {
            $work = GroupServiceWork::where('work_sn',$params['work_sn'])->findOrEmpty();
            if($work->isEmpty()){
                throw new \Exception('工单不存在');
            }
            if ($work->service_status >= 1) {
                throw new \Exception('工单已完成或服务中');
            }

            //添加变更日志
            $work_log = [
                'type' => 6,
                'work_id'=>$work->id,
                'master_worker_id'=>$work->master_worker_id,
                'opera_log'=>'编号['.$params['user_info']['worker_number'].']'.$params['user_info']['real_name'].'于'.date('y-m-d H:i:s',time()).'修改预约上门时间',
            ];
            GroupServiceWorkLogLogic::add($work_log);

            $work->appointment_time = strtotime($params['appointment_time']);
            $work->save();
            Db::commit();
            return true;
        } catch (\Exception $e) {
            Db::rollback();
            self::setError($e->getMessage());
            return false;
        }
    }
    
    public static function allocateWorker($params,$userInfo){
        Db::startTrans();
        try {
            $ids = explode(",",$params['id']);
            if (count($ids) > 50) {
                throw new \Exception('单次最多分配50个');
            }
            $worker = MasterWorkerTemporary::where(['id'=>$params['master_worker_id'],'is_disable' =>0])->findOrEmpty();
            if($worker->isEmpty()){
                throw new \Exception('工程师不存在或被禁用');
            }
            
            //批量派单
            $work = GroupServiceWork::whereIn('id',$ids)->where('work_status','<',6)->select()->toArray();
            
            foreach($work as $item) {
                if($item['master_worker_id'] != $params['master_worker_id']){
                    $work_log = [
                        'type' => 1,
                        'work_id'=>$item['id'],
                        'master_worker_id'=>$params['master_worker_id'],
                        'opera_log'=>'后台用户['.$userInfo['admin_id'].']'.$userInfo['name'].'于'.date('Y-m-d H:i:s',time()).'分配了工程师'.'编号['.$worker->worker_number.']'.$worker->real_name
                    ];
                    GroupServiceWorkLogLogic::add($work_log);

                    GroupServiceWork::where('id',$item['id'])->update([
                        'master_worker_id' => $params['master_worker_id'],
                        'work_status' => 3,
                        'dispatch_time' => time(),
                        'receive_time' => time(),
                        'user_confirm_status' => 2,
                        'code' => str_pad(rand(0, 9999), 4, '0', STR_PAD_LEFT),//从 0 - 9 中随机取 4 个数字
                    ]);
                }
            }
            
            Db::commit();
          
            // 工程师派单通知【给工程师的通知】【公众号通知，不发短信】
            $workDetail = GroupServiceWorkLogic::detail($params);
            $res = event('Notice',  [
                'scene_id' => 113,
                'params' => [
                    'user_id' => $params['master_worker_id'],
                    'order_id' => $params['id'],
                    'thing9' => $workDetail['title'],
                    'time7' => $workDetail['appointment_time'],
                    'thing8' => (iconv_strlen($workDetail['address'])>15)?(mb_substr($workDetail['address'],0,15,'UTF-8').'...'):$workDetail['address'],
                    'phone_number6' => asteriskString($workDetail['mobile']),
                ]
            ]);
            return true;
        }catch(\Exception $e){
            Db::rollback();
            self::setError($e->getMessage());
            return false;
        }
    }

    public static function cancelAllocation($params,$userInfo){
        Db::startTrans();
        try {

            $work = GroupServiceWork::findOrEmpty($params['id']);
            if($work->isEmpty()){
                throw new Exception('工单不存在');
            }
            if($work->work_status >=6 ){
                throw new \Exception('工单状态只能修改待结算之前的');
            }
            $worker = MasterWorkerTemporary::where(['id'=>$work->master_worker_id])->findOrEmpty();
            if($worker->isEmpty()){
                throw new \Exception('工程师不存在');
            }
            $params['master_worker_id'] = (isset($params['master_worker_id']) && !empty($params['master_worker_id']))?$params['master_worker_id']:$work->master_worker_id;
    
            //添加变更日志
            $work_log = [
                'type' => 2,
                'work_id'=>$work->id,
                'master_worker_id'=>$work->master_worker_id,
                'opera_log'=>'后台用户['.$userInfo['admin_id'].']'.$userInfo['name'].'于'.date('Y-m-d H:i:s',time()).'取消了工程师'.'编号['.$worker->worker_number.']'.$worker->real_name
            ];
            GroupServiceWorkLogLogic::add($work_log);

            $work->master_worker_id = 0;
            $work->work_status = 0;
            $work->dispatch_time = 0;
            $work->receive_time = 0;
            $work->save();
            Db::commit();
            return true;
        }catch(\Exception $e){
            Db::rollback();
            self::setError($e->getMessage());
            return false;
        }
    }


    /**
     * 工单详情
     * @param $params
     * @return array|false
     */
    public static function detail($params){
        $work_where = !empty($params['work_sn'])?['work_sn'=>$params['work_sn']]:['id'=>$params['id']];
        if (!empty($params['master_worker_id'])) {
            $work_where['master_worker_id'] = $params['master_worker_id'];
        }
        $result = GroupServiceWork::with([
                'worker'=> function(Query $query) {
                    $query->field('id,worker_number,real_name,mobile');
                },
                'serviceWorkLog' =>function(Query $query){
                    $query->field('id,work_id,opera_log,create_time');
                }
            ])
            ->where($work_where)
            ->field('id,work_sn,real_name,mobile,address,title,category_type,master_worker_id,work_status,user_confirm_status,service_status,dispatch_time,appointment_time,receive_time,work_images,finished_images,finished_time,area_name,finally_door_time,create_time,remark,third_type,work_total,work_amount,settlement_amount,work_pay_status')
            ->append(['id','work_status_text','service_status_text'])
            ->findOrEmpty()->toArray();
        if (empty($result)) {
            self::setError('工单不存在');
            return false;
        }
        
        //工程师工单按钮状态
        $work_service_status = 0;
        $work_service_status_text = '待派单';
        //工单状态
        if($result['work_status'] == 1){
            $work_service_status = 1;
            $work_service_status_text = '待领单';
        }
        if($result['work_status'] == 2){
            $work_service_status = 2;
            $work_service_status_text = '预约上门';
        }
        if($result['work_status'] == 3){
            $work_service_status = 3;
            $work_service_status_text = '等待上门';
        }
        
        if($result['work_status'] == 5 and $result['user_confirm_status']==2){
            $work_service_status = 7;
            $work_service_status_text = '完成服务';
        }
        if($result['work_status'] == 5 and $result['user_confirm_status']==3){
            $work_service_status = 8;
            $work_service_status_text = '用户确认完成服务中';
        }
        if($result['work_status'] ==6){
            $work_service_status = 9;
            $work_service_status_text = '待结算';
        }
        if($result['work_status'] ==7){
            $work_service_status = 10;
            $work_service_status_text = '已完结';
        }
        if($result['work_status'] ==8){
            $work_service_status = 11;
            $work_service_status_text = '已评价';
        }
        if($result['work_status'] ==9){
            $work_service_status = 12;
            $work_service_status_text = '已退费';
        }

        $result['work_service_status'] = $work_service_status;
        $result['work_service_status_text'] = $work_service_status_text;
        
        return  $result;
    }

    /**
     * 导入拼团工单
     */
    public static function import($file) {
        
        try {
            // 移动文件到指定目录
            $info = $file->move(root_path('public') . 'uploads');
            if ($info) {
                $filePath = $info->getPathname();

                // 读取 Excel 文件
                $spreadsheet = IOFactory::load($filePath);
                $worksheet = $spreadsheet->getActiveSheet();
                $highestRow = $worksheet->getHighestRow();

                // 假设第一行为表头，从第二行开始读取数据
                for ($row = 2; $row <= $highestRow; $row++) {
                    $data = [
                        'title' => $worksheet->getCell('A' . $row)->getValue(),
                        'real_name' => $worksheet->getCell('B' . $row)->getValue(),
                        'mobile' => $worksheet->getCell('C' . $row)->getValue(),
                        'address' => $worksheet->getCell('D' . $row)->getValue(),
                        'area_name' => $worksheet->getCell('E'. $row)->getValue(),
                        'appointment_time' => $worksheet->getCell('F'. $row)->getValue(),
                        'work_total' => $worksheet->getCell('G'. $row)->getValue(),
                        'work_amount' => $worksheet->getCell('H'. $row)->getValue(),
                        'settlement_amount' => $worksheet->getCell('I'. $row)->getValue(),
                        'remark' => $worksheet->getCell('J'. $row)->getValue(),
                    ];
                    
                    if(empty($data['title']) || empty($data['real_name']) || empty($data['mobile']) || empty($data['address'])){
                        continue;
                    }
                    $data['third_type'] = 2;
                    $data['work_pay_status'] = 2;
                    $data['category_type'] = 2;
                    $data['appointment_time'] = $data['appointment_time'] ? strtotime($data['appointment_time']) : 0;
                    $data['work_sn'] = generate_sn(GroupServiceWork::class, 'work_sn');
                    GroupServiceWork::create($data);
                }
                return true;
            } else {
                self::setError($file->getError());
                return false;
            }
        } catch (\Exception $e) {
            self::setError($e->getMessage());
            return false;
        }
    }

    /**
     * 退款
     */
    public static function refund($params,$userInfo){
        Db::startTrans();
        try {

            $work = GroupServiceWork::findOrEmpty($params['id']);
            if($work->isEmpty()){
                throw new Exception('工单不存在');
            }
            if($work->work_status >=7 ){
                throw new \Exception('此工单不支持退款');
            }
            if(!$work->group_user_order_id ){
                throw new \Exception('临时工单，不支持退款');
            }
            $order = GroupUserOrder::where(['id'=>$work->group_user_order_id])->findOrEmpty()->toArray();
            if (empty($order)){
                throw new \Exception('用户拼团订单不存在');
            }
            if ($order['refund_status'] != 0) {
                throw new \Exception('用户拼团订单已退款');
            }
            
            //添加变更日志
            $work_log = [
                'type' => 5,
                'work_id'=>$work->id,
                'master_worker_id'=>$work->master_worker_id,
                'opera_log'=>'后台用户['.$userInfo['admin_id'].']'.$userInfo['name'].'于'.date('Y-m-d H:i:s',time()).'执行退款'
            ];
            GroupServiceWorkLogLogic::add($work_log);

            //退款
            $work->work_status = 9;
            $work->service_status = 5;
            $work->save();
            
            // 生成退款记录
            $recordSn = generate_sn(RefundRecord::class, 'sn');
            $record = RefundRecord::create([
                'sn' => $recordSn,
                'user_id' => $order['user_id'],
                'order_id' => $order['id'],
                'order_sn' => $order['sn'],
                'order_type' => RefundEnum::ORDER_TYPE_GROUP,
                'order_amount' => $order['paid_amount'],
                'refund_amount' => $order['paid_amount'],
                'refund_type' => RefundEnum::TYPE_ADMIN,
                'transaction_id' => $order['transaction_id'] ?? '',
                'refund_way' => RefundEnum::getRefundWayByPayWay($order['pay_way']),
            ]);
            
            //更新用户拼团订单
            GroupUserOrder::where('id',$order['id'])->update(['status' => 2,'refund_status' => 1]);

            //更新拼团订单
            GroupOrder::where('id',$order['id'])->update([
                'num' => Db::raw('num-1')
            ]);

            // 退款
            $result = RefundLogic::refund($order, $record['id'], $order['paid_amount'], $userInfo['admin_id']);

            if ($result !== true) {
                throw new Exception(RefundLogic::getError());
                Db::rollback();
                return false;
            } else {
                Db::commit();
                return true;
            }
        }catch(\Exception $e){
            Db::rollback();
            self::setError($e->getMessage());
            return false;
        }
    }
    
}