<?php

namespace app\command;

use app\admin\controller\AdminController;
use app\model\Admins;
use app\model\Blacks;
use app\model\Finances;
use app\model\Orders;
use app\server\SMS;
use app\server\Tongcheng;
use stdClass;
use support\Log;
use support\Redis;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * 同程数据拉取
 */
class SpiderTc extends Command
{
    protected static $defaultName = 'spider:tc';
    protected static $defaultDescription = '同程订单拉取器';

    protected $_users = [];

    protected function configure()
    {
        $this->setName('spider:tc')
            ->setDescription('同程订单拉取器')
            ->setDefinition(
                new InputDefinition(array(
                    new InputOption('sn', 'sn', InputOption::VALUE_REQUIRED),
                    new InputOption('os', 'os', InputOption::VALUE_REQUIRED),
                    new InputOption('day', 'day', InputOption::VALUE_REQUIRED)
                ))
            );
    }

    protected function users($routeType)
    {
        // if (count($this->_users) > 0) return $this->_users;
        $users = Admins::where('status', 1)->where('is_order', 1)->where('route_type', $routeType)->select();
        $us = [];
        foreach ($users as $u) {
            $ru = Redis::get('CRM:USER:ONLINE:' . $u->id);
            if (empty($ru)) continue;

            $_u = new stdClass();
            $_u->username = $u->id;
            $us[] = $_u;
        };
        $this->_users = $us;
        return $this->_users;
    }

    protected $_redis_pool = [];

    protected function poolUser($status = 0, $categoryDesc = '')
    {
        $routeType = AdminController::ROUTE_LISTS[mb_substr($categoryDesc, 0, 2)] ?? 10;
        $status .= $routeType;
        if (empty($this->_redis_pool[$status])) {
            $this->_redis_pool[$status] = Redis::hGetAll('CRM:Pool:' . $status);
            $users = $this->users($routeType);
            $_users = [];
            if (empty($this->_redis_pool[$status])) {
                foreach ($users as $user) {
                    $_users[$user->username] = 0;
                    Redis::hSet('CRM:Pool:' . $status, $user->username, 0);
                }
                $this->_redis_pool[$status] = $_users;
            } else {
                asort($this->_redis_pool[$status]);
                $key_users = array_keys($this->_redis_pool[$status]);
                $username = $key_users[0];
                $max = $this->_redis_pool[$status][$username];
                $_users = [];
                foreach ($users as $user) {
                    $_users[] = $user->username;
                    if (!in_array($user->username, $key_users)) {
                        $this->_redis_pool[$status][$username] = $max;
                        Redis::hSet('CRM:Pool:' . $status, $user->username, $max);
                    }
                }
                foreach ($this->_redis_pool[$status] as $username => $val) {
                    if (!in_array($username, $_users)) {
                        unset($this->_redis_pool[$status][$username]);
                        Redis::hDel('CRM:Pool:' . $status, $username);
                    }
                }
            }
        }

        $username = null;
        try {
            $pool = $this->_redis_pool[$status];
            if (empty($pool)) $pool = [];
            asort($pool);
            $keys = array_keys($pool);
//            if(!!config('app.debug', true)) return 1;
            if (empty($keys)) {
                Log::error(dirname(__FILE__) . __LINE__ . '没有可以分配的用户');
                throw new \Exception('没有可以分配的用户');
            }
            $username = $keys[0];
            $this->_redis_pool[$status][$username] += 1;
            Redis::hIncrBy('CRM:Pool:' . $status, $username, 1);
        } catch (\Exception $e) {
            Log::error(dirname(__FILE__) . __LINE__ . '没有可以分配的用户', (array)json_encode($e));
            throw new \Exception('没有可以分配的用户');
        }
        return $username;
    }

    /** @var InputInterface $output */
    protected  $output;
    /**
     * @param InputInterface $input
     * @param OutputInterface $output
     * @return int
     */
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        // $name = $input->getArgument('name');
        $this->output = $output;
        $output->writeln('START spider:tc:'.date('Y-m-d H:i:s'));

        $os = $input->getOption('os');
        $orderid = $input->getOption('sn');
        $d = $input->getOption('day');
        if (empty($d)) {
            $d = 40;
        }

        if ($orderid) {
            $this->reloadStatus($orderid, $os, $output);
            return 1;
        }

        // echo "状态1\n";
        // $this->poolUser(1);
        // echo "状态2\n";
        // $this->poolUser(2);
        // echo "状态3\n";
        // $this->poolUser(3);
        // echo "状态4\n";
        // $this->poolUser(4);
        // echo "状态5\n";
        // $this->poolUser(5);
        // return 1;

        // $this->checks($output);
        // $output->writeln('CHECK spider:dy');

        // $day = new Douyin();
        // print_r($day->get(1));
        // return 1;

        // sleep(5);
//        $time = strtotime(date('Y-m-d'));
//        for ($i = 0; $i <= $d; $i++) {
//            $day = $time - $i * 24 * 3600;
//            $start = date('Y-m-d', $day);
//            $end = date('Y-m-d 23:59:59', $day);
//            $this->orders($start, $end, false);
//            // $this->_kuaishouOrder($start, $end, false);
//        }

        // 8点20 开始分配订单
        date_default_timezone_set('Asia/Shanghai');
        $startTime = strtotime(date('Y-m-d 09:10'));
        if (time() > $startTime) {
            $start = date('Y-m-d 00:00:00', strtotime("-{$d} days"));
            $output->writeln('END spider:tc:start:'.$start);
            $end = date('Y-m-d 23:59:59');
            $this->orders($start, $end, false);
        }

        if (date('H') >= 1 && date('H') <= 7) {
            $this->reload($output);
        }

        $output->writeln('END spider:tc:'.date('Y-m-d H:i:s'));
        return self::SUCCESS;
    }

    private function orders($start = null, $end = null, $order_id = false)
    {
        foreach (Orders::OSS as $k => $os) {
            $pages = 10;
            $page = 1;
            while (true) {
                if ($page > $pages) break;
                $list = [];

                switch ($k) {
                    case 6:
                        try {
                            $dou = new Tongcheng($k);
                            $list = $dou->get($page, $start, $end, '');
                            $pages = $dou->totalPage;
                        } catch (\Exception $e) {
                            Log::info('同程订单拉取失败:' . dirname(__FILE__) . __LINE__ . $e);
                        }
                        break;

                    default:
                        # code...
                        break;
                }

                foreach ($list as $order) {
                    $item = Orders::where('os', $order->os)->where('sn', $order->sn)->find();

                    if (empty($item)) {
                        $order->is_zhibo = 2;

                        $oldMobile = orders::where("os", $order->os)->where("mobile", $order->mobile)
                            ->where("create_time", '>=', time() - 24 * 3600 * 3)->find();

                        if (!empty($oldMobile)) {
                            $admin_id = $oldMobile->admin_id;
                        } else {
                            // $admin_id = $this->poolUser($order->orderStatus, $order->category_desc);
                            try {
                                $admin_id = \app\server\Orders::poolUser($order->orderStatus, $order->product_id);
                            } catch (\Exception $exception) {
                                Log::info(sprintf('tc create order fail:%s, order_id:%s', $exception->getMessage(), $order->sn));
                                continue;
                            }
                        }

                        if (empty($admin_id)) return null;
                        $order->admin_id = $admin_id;
                        $order->give_time = time();

                        //判断是否需要发短信 200-待使用，205-预约中（抖音），210-已预约（抖音），310-已履约（抖音），300-已完成
                        if (in_array($order->order_status, [200, 205, 210, 310, 300]) ) {
                            $this->sms($admin_id, $order);
                        }
                        $work = \app\server\Orders::getLiveRoomWork($order->create_at, $order->product_id);
                        if ($work) {
                            $order->live_room_work_id = $work->id;
                        }
                        //新获得一个用户的,提示管理员有新的订单
                        Redis::incrBy('CRM:USER:ONLINE:NEW:' . $admin_id, 1);
                        $item = new Orders();
                    }

                    if ($order->travel_date && empty($order->travel_end)) {
                        $days = $this->_days($order);
                        if ($days) {
                            $order->travel_end = date('Y-m-d 00:00:00', strtotime($order->travel_date) + $days * 24 * 3600);
                        }
                    }

                    if ($item->order_status !== 2 && $order->order_status == 2) {
                        Redis::incrBy('CRM:USER:WRITE:OFF:' . $item->admin_id, 1);
                    }

                    $back = $item->save($order->toArray());

                    if ($back) {
                        $this->_finance(0, $item->id, $item->asset_price);
                    }
                }

                // 数据小于50, 结束
                if (empty($list)) {
                    break;
                }
                $page++;
            }
        }
    }

    private function reload($output)
    {
        $back = Redis::set('SpiderMt:reload:dy:lock', time(), 'EX', 3600 * 8, 'NX');
        if (!$back) return;
        $orders = Orders::where('create_at', '<=', (time() - 15 * 24 * 3600) * 1000)->where('os', 6)->wherein('status', [1, 2, 3])->select();
        foreach ($orders as $order) {
            $this->reloadStatus($order->sn, $order->os, $output);
        }
    }

    /**
     * @param $admin_id
     * @param $order
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    private function sms($admin_id, $order) {
        $user = Admins::cache(true)->where('id', $admin_id)->find();
        $templateId = 261607;
        if ((!config('app.debug', true) || config('app.debug', true) === 'false') && (time() * 1000 - $order->create_at) / 1000 < 2 * 24 * 3600) {
            print_r([$order->mobile, $templateId, ['title' => $order->product_name, 'mobile' => $user->mobile]]);
            $has = Blacks::where('mobile', $order->mobile)->find();
            if (empty($has) && !empty($order->mobile)) {
                SMS::juhe_sms_send($order->mobile, $templateId, ['title' => $order->product_name, 'mobile' => $user->mobile]);
            } else {
                sleep(10);
            }
        } else {
            print_r([$order->mobile, $templateId, ['title' => $order->product_name, 'mobile' => $user->mobile]]);
        }
    }

    private function reloadStatus($orderid, $os, $output)
    {
        $w[] = ['sn', '=', $orderid];
        if ($os) $w[] = ['os', '=', $os];
        $item = Orders::where($w)->find();
        if (empty($item)) {
            $output->writeln('没有找到订单');
        }

        $m = new Tongcheng($os);
        $it = $m->get(1, null, null, $item->sn);


        if ($it) {
            $back = $item->save($it[0]);
            if ($back) {
                $this->_finance(0, $item->id, $item->asset_price);
            }
        } else {
            $output->writeln('没有拉取到数据:' . $orderid);
        }

    }

    private function _days($order)
    {
        if (stripos($order->product_name, '一日') !== false) {
            return 1;
        }
        preg_match('/(\d)天/', $order->product_name, $all);
        if (!empty($all) && intval($all[1]) > 0) {
            return $all[1];
        }
        return 0;
    }

    private function zhibo($title, $os = 0)
    {
        if ($os == 3) {

            return 2;
        }
        if (
            strlen($title) - 3 == strripos($title, "！")
            || strlen($title) - 1 == strripos($title, "!")
        ) {
            return 1;
        } elseif (strlen($title) - 3 == strripos($title, "甄")) {
            return 2;
        }
        return 0;
    }

    private function _finance($type = 1, $order_id = 0, $price = 0)
    {
        // $fa = Finances::where('order_id', $order_id)->where('type', $type)->find();
        $back = Redis::set('CRM:ORDER:LOCK:' . $order_id, time(), 'EX', 6, 'NX');
        if (!$back) return;

        $total = Finances::where('order_id', $order_id)->sum('total'); //总的关于这个订单的金额
        //如果总金额大于提交上来的核销金额,那就是退费的
        //如果提交上来的金额小于总金额,那就是核销的
        if ($total > $price) {
            $type = 2;
            $fee = -($total - $price);
        } elseif ($total < $price) {
            $type = 1;
            $fee = $price - $total;
        } else {
            return;
        }

        Finances::create([
            'order_id' => $order_id,
            'type' => $type,
            'total' => $fee,
            'status' => 1
        ]);
        return;

        // if(empty($fa)) {
        //     if($type == 2) {
        //         $has = Finances::where('order_id', $order_id)->where('type', 1)->find();
        //         if(empty($has)) return;
        //     }
        //     Finances::create([
        //         'order_id' => $order_id,
        //         'type' => $type,
        //         'total' => $price,
        //         'status' => 1
        //     ]);
        // }
    }
}
