<?php
namespace app\admin\controller;
require_once(__DIR__.'/xlsxwriter.class.php');

use app\model\Admins;
use app\model\Backs;
use app\model\Follows;
use app\model\Orders;
use app\model\Logs;
use app\model\ThirdMobileLogs;
use app\server\ThirdApiService;
use app\server\Orders as ServerOrders;
use stdClass;
use support\Log;
use support\Redis;
use support\Request;
use think\facade\Db;

class OrderController extends base
{

    public function index(Request $request) {
        $sn = $request->get('sn');
        $timetype = $request->get('timetype');
        $times = $request->get('times');
        $os_status = $request->get('os_status');

        $where = [];
        if(!$request->admin->is_super) {
            $where = [['admin_id','=', $request->admin->id]];
        } else {
            $where = [['admin_id', '>', 0]];
        }

        if($sn) {
            $where[] = ['sn','=', $sn];
        }

//        if (in_array($appointment_status, [0, 1])) {
//            $where[] = ['appointment_status', '=', $appointment_status];
//        }

        $status = $request->get('status', null);

        $query = Orders::attimes($timetype, $times)->with(['admin','anchor','backs', 'mobileInfo'])->where($where)
            ->order('create_at','desc')
            ->order('update_time','desc')
            ->order('id','desc');

        if($os_status) {
            if ($os_status[0] == array_search(Orders::OSS[4],Orders::OSS)){
                if (isset($os_status[1]) && is_numeric($os_status[1])) {
                    $query->whereRaw(Orders::AllOssStatusSql[$os_status[1]]);
                }
            }else{
                if (isset($os_status[0]) && is_numeric($os_status[0])) {
                    $query->where('os', $os_status[0]);
                }
                if (isset($os_status[1]) && is_numeric($os_status[1])) {
                    $query->where('order_status', $os_status[1]);
                }
            }
        }

        if($status!=null && $status >= 0) {
            $query->where('status', $status);
        }

        $appointment_status = $request->get('appointment_status', null);
        if($appointment_status!=null && $appointment_status >= 0) {
            $query->where('appointment_status', $appointment_status);
        }

        $mobile = $request->get('mobile');
        if($mobile){
            $query->where('mobile','like', '%'.$mobile.'%');
        }

        $productName = $request->get('product_name');
        if($productName){
            $query->where('product_name','like', '%'.$productName.'%');
        }

        $zhubo = $request->get('zhubo');
        if($zhubo){
            $zhubo_id = Admins::where('username', $zhubo)->value('id');
            $query->where('zhubo', $zhubo_id);
        }

        $admin = $request->get('admin');
        if($admin){
            $admin_id = Admins::where('username', $admin)->value('id');
            $query->where('admin_id', $admin_id);
        }

        $excel = $request->get('excel');
        if($excel == 1) {
            $orders = $query->select();

            $writer = new \XLSXWriter();
            $writer->writeSheetHeader('Sheet1', ['电话'=>'string','平台'=>'string','直播'=>'string','订单号'=>'string','下单时间'=>'string','状态'=>'string','跟进状态'=>'string',
            '标题'=>'string','跟进备注'=>'string','联系人'=>'string','出行时间'=>'string','回来时间'=>'string',
            '跟进时间'=>'string',
            '总金额'=>'price','支付金额'=>'price','核销金额'=>'price','人数'=>'integer','跟单人'=>'string','主播'=>'string']);

            foreach($orders as $order) {
                $writer->writeSheetRow('Sheet1', [$order->mobile, $order->os_name, $order->is_zhibo, "$order->sn", date('Y-m-d H:i:s', intval($order->create_at/1000)),$order->order_status_name, $order->status_name,
                $order->product_name, $order->remark, $order->contact, $order->travel_date, $order->travel_end,
                $order->last_follow ? date('Y-m-d H:i:s', intval($order->last_follow/1000)):'',
                $order->total_price/100, $order->actual_price/100, $order->asset_price/100, $order->quantity, $order->admin->username ?? '', $order->anchor->username ?? '']);
            }

            $file_name = "订单导出-".date('Ymd-His').".xlsx";

            $response = response();
            $c = $writer->writeToString();
            $response->withHeaders([
                'Content-Type' => 'application/force-download',
                'Content-Disposition' => 'attachment; filename="'.$file_name.'"',
                'Content-Transfer-Encoding' => 'binary',
                'Cache-Control' => 'max-age=0',
            ])->withBody($c);
            return $response;
            // return;
        }else{
            $orders = $query->paginate($request->get('limit',10));
        }

        foreach($orders as &$order) {
            if(empty($order->personnel)) {
                $order->personnel = new stdClass();
            }
        }

        $list = $orders->visible(['admin' => ['username','name','avatar']])->hidden(['check_sn'])->append(['order_status_name','status_name','os_name']);

        $localMobiles = [];
        foreach ($list as &$value) {
            $mobileInfo = $value['mobileInfo'] ?? '';
            if (empty($value['mobileInfo'])) {
                try {
                    if (isset($localMobiles[$value['mobile']])) {
                        // 防止重复查询第三方接口
                        $mobileInfo = $localMobiles[$value['mobile']];
                    } else {
                        $mobileInfo = (new ThirdApiService())->getMobileArea($value['mobile']);
                        $localMobiles[$value['mobile']] = $mobileInfo;
                    }
                } catch (\Exception $exception) {
                    $mobileInfo = [];
                    Log::info('查询手机归属地失败:' . $exception->getMessage());
                }
            }
            $value['mobileInfo'] = $mobileInfo;
        }

        $_oss = [];
        foreach (Orders::OSS as $key=>$os) {
            $_oss[$key] = ['label' => $os,'value' => $key];
            if($key == 1) {
                $statss = Orders::OrderStatus;
            }elseif($key ==2) {
                $statss = Orders::KuaishouStatus;
            }elseif($key ==3) {
                $statss = Orders::DouyinStatus;
            }elseif ($key == 4) {
                $statss = Orders::AllOssStatus;
            }elseif($key ==5) {
                $statss = Orders::DouyinStatus;
            }elseif($key ==6) {
                $statss = Orders::TongchengStatus;
            }elseif($key ==6) {
                $statss = Orders::OrderStatus;
            }

            $_ch = [];
            foreach($statss as $k=>$v) {
                $_ch[] = ['label' => $v,'value' => $k];
            }

            $_oss[$key]['children'] = $_ch;
        }

        return $this->success($list,null,['timetype'=>  Orders::timeType, 'oss' => array_values($_oss)]);
    }

    public function all(Request $request) {
        $sn = $request->get('sn');

        if($sn) {
            $where[] = ['sn','=', $sn];
        }
        $orders = Orders::with(['admin'])->where($where)->order('update_time','desc')->order('create_at','desc')->order('id','desc')->paginate($request->get('limit',10));

        return $this->success($orders->visible(['admin' => ['username','name','avatar']])->hidden(['mobile','check_sn'])->append(['order_status_name','status_name','os_name']));
    }

    public function pub(Request $request) {
        $orders = Orders::where('admin_id', 0)->order('create_at','desc')->order('id','desc')->paginate($request->get('limit',10));

        return $this->success($orders->hidden(['mobile','check_sn'])->append(['order_status_name','os_name']));
    }

    //公海领取订单
    public function fish(Request $request) {
        $id = $request->post('id');
        if(empty($id) || intval($id) <=0) return $this->error(2001, '请提交id');

        $order = Orders::find($id);
        if($order->admin_id > 0 ) return $this->error(2002, '订单没有找到或者已经转移到其他人');

        try{
            Orders::fish($order->id, $request->admin->id);
            return $this->success(null);
        }catch(\Exception $e){
            return $this->error(2003, '公海获取订单失败,订单没有找到或者已经转移到其他人');
        }
    }

    public function info(Request $request) {
        $id = $request->get('id');

        if(empty($id) || intval($id) <=0) return $this->error(2001, '请提交id');

        $where[] = ['id','=',$id];

        if($request->admin->is_super == 0) {
            $where[] = ['admin_id','=',$request->admin->id];
        }
        $item = Orders::where($where)->with(['follow.admin','finance'])->find();

        if(empty($item)) {
            return $this->error(2002, '订单没有找到或者已经转移到其他人');
        }
        Logs::see($item->id, $request->admin->id);

        if(empty($item->personnel)) {
            $item->personnel = new stdClass();
        }

        return $this->success($item->append(['order_status_name','os_name']));
    }

    //核销,跟单
    public function save(Request $request) {
        $id = $request->post('id');
        $next_follow = $request->post('next_follow');
        $check_sn = $request->post('check_sn');
        $desc = $request->post('desc');
        $status = $request->post('status');
        $is_wechat = $request->post('is_wechat');
        $personnel = $request->post('personnel');
        $travel_date = $request->post('travel_date');
        $travel_end = $request->post('travel_end');


        if(empty($desc) || empty($status)) return $this->error(2004, '跟进说明需要填写!');
        if(empty($personnel)) return $this->error(2004, '人员情况需要填写!');
        if(empty($travel_date)) return $this->error(2004, '出游时间需要填写!');
        if (in_array($status, [0, 1])){
            if(empty($next_follow)) return $this->error(2004, '下次跟进时间需要填写!');
        }
        if ($status == 2){
            $next_follow = '';
            if(empty($travel_end)) return $this->error(2004, '返回日期需要填写!');
            if(empty($check_sn)) return $this->error(2004, '核销码需要填写!');
        }

        $lock = 'Travel:Order:'.$id.':lock';
        $back = Redis::set($lock, $request->admin->id, 'EX', 6, 'NX');
        if(!$back) return $this->error(2005, '锁定失败');

        $item = Orders::where('id', $id)->where('admin_id', $request->admin->id)->find();
        if(empty($item)) return $this->error(2006, '订单不存在');
        if($item->admin_id != $request->admin->id) return $this->error(2007, '订单已经发生转移');

        //if(!empty($travel_date) && empty($travel_end)) return $this->error(2008, '核销的订单请填写出行和返回时间');

        Follows::create([
            'admin_id' => $request->admin->id,
            'order_id' => $item->id,
            'status'   => $status,
            'desc'     => $desc
        ]);

        //放弃跟进
        // if($status == 4) {
        //     $item->status = 0;
        //     $item->admin_id = 0;
        //     $item->remark = $desc;
        //     $item->save();
        //     return $this->success($item);
        // }else{
            //修改状态
            $item->check_sn = $check_sn;
            $item->status = $status;
            !empty($travel_date) && empty($item->travel_date) ? $item->travel_date = date('Y-m-d', strtotime($travel_date)) : null;
            !empty($travel_end) && empty($item->travel_end)  ? $item->travel_end = date('Y-m-d', strtotime($travel_end)) : null;
            $item->personnel = json_encode($personnel);
            $item->is_wechat = $is_wechat? 1: 0;
            $item->last_follow = microtime(true) * 1000;
            $item->next_follow = strtotime($next_follow??'') * 1000;
            $item->remark = $desc;

            $back = $item->save();
        // }

        if($back) {
            if ($item->check_sn) {
                //通过命令行核销订单
                Redis::LPUSH('Travel:Order:check:lits',json_encode([
                    'id' => $item->id,
                    'check_sn' => $item->check_sn
                ]));

                // 限制只被录入一次
                $has = Logs::where('admin_id', $request->admin->id)->whereIN('action',[2,3])->where('check_sn',$check_sn)->find();
                if(empty($has)) {
                    Logs::pass($item->id, $request->admin->id, $check_sn);
                }
            }
            if($item->is_wechat > 0 ) {
                $has = Logs::where('admin_id', $request->admin->id)->where('order_id', $item->id)->where('action', 5)->find();
                if(empty($has)) {
                    Logs::wechat($item->id, $request->admin->id);
                }
            }

            return $this->success($item);
        }else{
            return $this->error(2008, '保存订单失败');
        }
    }

    public function pass(Request $request) {
        $check_sn = $request->post('check_sn');
        if(!is_numeric($check_sn)) return $this->error(2008, '格式错误');

        $has = Orders::where('check_sn', $check_sn)->find();
        if($has) {
            return $this->error(2008, '核销码已经被使用了');
        }

        //限制只被录入一次
        $has = Logs::where('admin_id', $request->admin->id)->whereIN('action',[2,3])->where('check_sn', $check_sn)->find();
        if(empty($has)) {
            Logs::pass2($request->admin->id, $check_sn);
        }

        //通过命令行核销订单
        Redis::LPUSH('Travel:Order:check:lits',json_encode([
            'admin_id' => $request->admin->id,
            'check_sn' => $check_sn
        ]));

        return $this->success(null,'提交成功');
    }

    //把订单拉回
    public function backlist(Request $request) {
        $sn = $request->get('sn');
        $status = $request->get('status',null);

        $query = Backs::with(['into','outto','orders','apply'])->where(function($query) use($request) {
            $query->where('admin_id', $request->admin->id)->WhereOr('admin', $request->admin->id);
        })->order('update_time','desc')->order('id','desc');

        if($sn) {
            $order_id = Orders::where('sn', $sn)->value('id');
            $query->where('order_id', $order_id);
        }

        if($status != null) {
            $query->where('status', $status);
        }

        $backs = $query->paginate($request->get('limit',10));
        foreach($backs as &$back){
            if ($back->admin_id == $request->admin->id || $back->admin == $request->admin->id){
                $back->self = 0;
                if($back->apply_id == $request->admin->id) {
                    $back->self = 3;
                }
            }else{
                $back->self = 1;
            }
        }

        return $this->success($backs->append(['order_status_name','os_name']),null, Orders::OSS);
    }

    //把订单拉回
    public function back(Request $request) {
        $sn = $request->post('sn');
        $os = $request->post('os');
        $to_admin_id = $request->post('to_admin_id');
        $admin_id = empty($to_admin_id) ? $request->admin->id : $to_admin_id;

        if(empty($sn)) return $this->error(2001, '提交单号');

        $item = Orders::where('sn', $sn)->where('os', $os)->find();
        if(empty($item)) return $this->error(2002, '订单没有找到');
        if($item->admin_id == $admin_id) return $this->error(2002, '订单已经在账号上,不需要再拉取!');

        //管理员不用审批
        $status = 0;
        if ($request->admin->is_super == 1 || $request->admin->id == 1){
            $status = 1;
        }

        $backs = [
            'order_id' => $item->id,
            'admin_id' => $admin_id,
            'admin' => $item->admin_id,
            'apply_id' => $request->admin->id,
            'status' => $status
        ];
        try {
            Db::transaction(function() use ($backs,$item) {
                Backs::create($backs);
                Logs::todo($backs['order_id'], $backs['apply_id'], $backs['status'] == 1 ? 12 : 7,$item->sn);

                if ($backs['status'] == 1){//管理员审批处理
                    Orders::where('id', $backs['order_id'])->where('admin_id', $backs['admin'])->update(['admin_id'=> $backs['admin_id']]);
                    $other = Backs::where('order_id', $backs['order_id'])->where('status', 0)->lock()->select();
                    foreach($other as $o) {
                        Backs::where('id', $o->id)->where('status', 0)->update(['status' => 3]);
                        Logs::todo($o->order_id, $o->admin, 10); //取消其他转单需求
                    }
                }
            });
        }catch (\Exception $e){
            return $this->error(2003, '创建拉回记录失败了');
        }

        return $this->success(true);
    }

    public function toBack(Request $request) {
        $sn = $request->post('sn');
        $os = $request->post('os');
        $to_admin_id = $request->post('to_admin_id');
        $admin_id = empty($to_admin_id) ? $request->admin->id : $to_admin_id;

        if(empty($sn)) return $this->error(2001, '提交单号');

        $item = Orders::where('sn', $sn)->where('os', $os)->find();
        if(empty($item)) return $this->error(2002, '订单没有找到');
        if($item->admin_id == $admin_id) return $this->error(2002, '订单已经在账号上,不需要再拉取!');

        //管理员不用审批
        $status = 0;
        if ($request->admin->is_super == 1 || $request->admin->id == 1){
            $status = 1;
        }

        $backs = [
            'order_id' => $item->id,
            'admin_id' => $admin_id,
            'admin' => $item->admin_id,
            'apply_id' => $request->admin->id,
            'status' => $status
        ];
        try {
            Db::transaction(function() use ($backs,$item) {
                Backs::create($backs);
                Logs::todo($backs['order_id'], $backs['apply_id'], $backs['status'] == 1 ? 12 : 7,$item->sn);

                if ($backs['status'] == 1){//管理员审批处理
                    Orders::where('id', $backs['order_id'])->where('admin_id', $backs['admin'])->update(['admin_id'=> $backs['admin_id']]);
                    $other = Backs::where('order_id', $backs['order_id'])->where('status', 0)->lock()->select();
                    foreach($other as $o) {
                        Backs::where('id', $o->id)->where('status', 0)->update(['status' => 3]);
                        Logs::todo($o->order_id, $o->admin, 10); //取消其他转单需求
                    }
                }
            });
        }catch (\Exception $e){
            return $this->error(2003, '创建拉回记录失败了');
        }

        return $this->success(true);
    }

    /**
     * 同意操作
     * @param Request $request
     * @return \support\Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function backpass(Request $request) {
        $id = $request->post('id', 0);

        $item = Backs::where('id', $id)->find();
        if($item->status != 0) return $this->error(2004, '记录已经处理了.');
        if($item->admin != $request->admin->id && $item->admin != $item->apply_id) return $this->error(2005, '管理员错误');

        try {
            Backs::change($item);
            return $this->success('');
        }catch(\Exception $e) {
            return $this->error(2006, '确认失败了');
        }
    }

    /**
     * 拒绝操作
     * @param Request $request
     * @return \support\Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function backrefuse(Request $request) {
        $id = $request->post('id', 0);

        $item = Backs::where('id', $id)->find();
        if(empty($item)) return $this->error(2004, '记录没有找到.');
        if($item->status != 0) return $this->error(2004, '记录已经处理了.');
        if($item->admin != $request->admin->id && $item->admin != $item->apply_id) return $this->error(2005, '管理员错误');

        try {
            Backs::refuse($item);
            return $this->success('');
        }catch(\Exception $e) {
            return $this->error(2006, '确认失败了');
        }
    }

    /**
     * 取消操作
     * @param Request $request
     * @return \support\Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function backcancel(Request $request)
    {
        $id = $request->post('id', 0);

        $item = Backs::where('id', $id)->find();
        if(empty($item)) return $this->error(2004, '记录没有找到.');
        if($item->status != 0) return $this->error(2004, '记录已经处理了.');
        if($item->admin != $request->admin->id && $item->admin == $item->apply_id) return $this->error(2005, '管理员错误');

        try {
            Backs::cancel($item);
            return $this->success('');
        }catch(\Exception $e) {
            return $this->error(2006, '确认失败了');
        }
    }

    /**
     * 一键修复订单问题
     * @param Request $request
     * @return \support\Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function oneClickRepair(Request $request)
    {
        try {
            $ids = $request->post('id', 0);
            $idArr = explode(',', $ids);

            $flow = [];
            foreach ($idArr as $id) {
                Log::info('同步订单ID:' . $id);

                $order = Orders::where('id', $id)->find();

                if (empty($order)) {
                    return $this->error(2004, '记录没有找到.');
                }

                // 订单是待使用状态,先同步第三方状态
                if (ServerOrders::isDaishiyong($order)) {
                    ServerOrders::syncFromThird($order);
                    $flow[] = "订单为待使用状态,已请求第三方进行同步。";
                }
            }

            return $this->success(implode("\n", $flow));
        }catch(\Exception $e) {
            Log::info(sprintf('oneClickRepair error:%s, %s, %s', $e->getMessage(), $e->getFile(), $e->getLine()) );
            return $this->error(2006, '出错了:' . $e->getMessage());
        }
    }

    /**
     * 预约处理
     * @param Request $request
     * @return \support\Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function changeAppointmentStatus(Request $request)
    {
        try {
            $ids = $request->post('id', 0);
            $idArr = explode(',', $ids);

            $flow = [];
            foreach ($idArr as $id) {
                Log::info('同步订单ID:' . $id);

                $order = Orders::where('id', $id)->find();

                if (empty($order)) {
                    return $this->error(2004, '记录没有找到.');
                }

                // 订单是待使用状态,先同步第三方状态
                $order['appointment_status'] = 2;
                $order->save();
            }

            return $this->success(implode("\n", $flow));
        }catch(\Exception $e) {
            return $this->error(2006, '出错了:' . $e->getMessage());
        }
    }
}