<?php

namespace app\server;

use app\common\Error;
use app\model\Admins;
use app\model\Admins as AdminsModel;
use app\model\Blacks;
use app\model\FilterMobiles;
use app\model\Finances as FinancesModel;
use app\model\LiveRoomWorks;
use app\model\Orders as OrdersModel;
use app\model\Products;
use support\Log;
use support\Redis;

class Orders {
    protected static $redisPool = [];
    public static function isDaishiyong(OrdersModel $order): bool
    {
        // 根据 OrdersModel::AllOssStatusSql[1] 进行判断
        // ((os=1 and order_status=3) or (os=2 and order_status=4) or (os=3 and order_status=1))
        return (in_array($order->os, [1, 7]) && $order->order_status == 3)
            || ($order->os == 2 && $order->order_status == 4)
            || (in_array($order->os, [3, 5]) && in_array($order->order_status, [1, 5]))
            || (in_array($order->os, [6]) && in_array($order->order_status, [200]));
    }

    /**
     * @params []OrdersModel $order
     * @return array
     */
    public static function reminderOrders(OrdersModel ...$orders)
    {
        $admin_ids = [];
        $sns = [];

        foreach ($orders as $order) {
            $admin_ids[] = $order->admin_id;
            $sns[] = $order->sn;
        }

        $admins = AdminsModel::whereIn('id', $admin_ids)->select()->column('mobile', 'id');

        if (empty($admins)) {
            return array_fill_keys($sns, Error::undefined('admin check error'));
        }

        $ttl    = 86400;
        $result = [];

        $admins = array_column($admins, null, 'id');
        foreach($orders as $order) {
            $admin_mobile = $admins[$order->admin_id] ?? '';

            if (empty($order->mobile) || empty($admin_mobile)) {
                $result[$order->sn] = Error::undefined('client mobile or admin mobile invalid');
                continue;
            }
            if (FilterMobiles::isFilterMobile($order->mobile)) {
                $result[$order->sn] = Error::undefined('刷单账单');
                continue;
            }
            $admin_mobile = $admin_mobile['mobile'] ?? '';

            if (Blacks::CExists($order->mobile)) {
                $result[$order->sn] = Error::ERR_SMS_BLACKS;
                Log::info(__METHOD__ . " blacks", [$order->mobile, $order->sn]);
                continue;
            }

            $key = sprintf("CRM:%s:%s_%s", 'reminderOrders', $order->sn, $order->mobile);
            $ok  = Redis::set($key, time(), 'EX', $ttl, 'NX');

            if (!$ok) {
                $result[$order->sn] = Error::undefined('reminder cooldown');
                continue;
            }

            $res = SMS::juhe_sms_send($order->mobile, SMS::JUHE_TMP_REMINDER_ORDER, ['title' => $order->product_name, 'mobile' => $admin_mobile]);
            $err_code = $res['error_code'] ?? 0;

            if ($err_code != 0) {
                Log::error(__METHOD__ . " send error", [$res, $order->mobile, $order->sn]);
                $result[$order->sn] = Error::ERR_SMS_SEND_FAIL;
                continue;
            }

            $result[$order->sn] = [];
        }

        return count($orders) > 1 ? $result : reset($result);
    }

    public static function syncFromThird(OrdersModel $order)
    {
        $redisKey = 'sync_order:' . $order->sn;
        if (Redis::exists($redisKey)) {
            return 1;
        }
        $got = null;

        switch ($order->os) {
            case 1:
            case 7:
                $mt = new Meituan($order->os);
                $it = $mt->get(1, null, null, $order->sn);

                if ($it) {
                    $got = $it[0];
                }

                break;
            case 3:
            case 5:
                $dy = new Douyin($order->os);
                $it = $dy->get(1, null, null, $order->sn);
                if ($it) {
                    $got = $it[0];

                    // 查询未预约状态
                    if ($order->appointment_status == 0) {
                        $appointment_status = $dy->_orderMakeAppointmentStatus($order->sn);
                        if ($appointment_status !== null) {
                            $got['appointment_status'] = 1;
                        }
                    }
                }

                break;
            case 6:
            case 8:
                $tc = new Tongcheng($order->os);
                $it = $tc->get(1, null, null, $order->sn);

                if ($it) {
                    $got = $it[0];
                }
                break;
        }

        if (is_null($got)) {
            Log::info(__METHOD__ . ": get from os is null", [$order]);
            return;
        }

        $back = $order->save($got);

        if ($back) {
            self::finance(0, $order->id, $order->asset_price);
        }
        Redis::setEx($redisKey, 600, 1);

        return 0;
    }

    public static function finance($type = 1, $order_id = 0, $price = 0)
    {
        //总的关于这个订单的金额
        $total = FinancesModel::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;
        }

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

        return;
    }

    /**
     * 同步第三方返回
     * @param OrdersModel $order
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function syncFromThirdV2(OrdersModel $order)
    {
        $got = null;
        switch ($order->os) {
            case 1:
            case 7:
                $mt = new Meituan($order->os);
                $it = $mt->get(1, null, null, $order->sn);

                if ($it) {
                    $got = $it[0];
                }

                break;
            case 3:
            case 5:
                $dy = new Douyin($order->os);
                $it = $dy->get(1, null, null, $order->sn);
                if ($it) {
                    $got = $it[0];
                }

                break;
        }

        if (is_null($got)) {
            Log::info(__METHOD__ . ": get from os is null", [$order]);
            return $order;
        }

        $back = $order->save($got);

        if ($back) {
            self::finance(0, $order->id, $order->asset_price);
        }

        return $order;
    }

    /**
     * @param int $orderCreateTime
     * @param     $productId
     * @return array|mixed|\think\Model
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function getLiveRoomWork(int $orderCreateTime, $productId) {
        $orderCreateDate = date('Y-m-d H:i:s', $orderCreateTime/1000);
        $roomWork = LiveRoomWorks::join('live_room', 'live_room_works.live_room_id=live_room.id')
            ->where('live_room_works.start', '<', $orderCreateDate)
            ->where('live_room_works.end', '>', $orderCreateDate)
            ->whereRaw(sprintf('find_in_set(%s, live_room.`product_ids`)', $productId))
            ->field(['live_room_works.id'])
            ->find();

        return $roomWork;
    }

    /**
     * 分配用户
     * @param int    $status
     * @param string $categoryDesc
     * @return int|string
     * @throws \Exception
     */
    public static function poolUser($status, $thirdProductId) {
        $status .= $thirdProductId;
        if (empty(self::$redisPool[$status])) {
            self::$redisPool[$status] = Redis::hGetAll('CRM:Pool:' . $status);
            $users = self::users($thirdProductId);
            shuffle($users);
            $_users = [];
            if (empty(self::$redisPool[$status])) {
                foreach ($users as $user) {
                    $_users[$user->username] = 0;
                    Redis::hSet('CRM:Pool:' . $status, $user->username, 0);
                }
                self::$redisPool[$status] = $_users;
            } else {
                asort(self::$redisPool[$status]);
                $key_users = array_keys(self::$redisPool[$status]);
                $username = $key_users[0];
                $max = self::$redisPool[$status][$username];
                $_users = [];
                foreach ($users as $user) {
                    $_users[] = $user->username;
                    if (!in_array($user->username, $key_users)) {
                        self::$redisPool[$status][$username] = $max;
                        Redis::hSet('CRM:Pool:' . $status, $user->username, $max);
                    }
                }
                foreach (self::$redisPool[$status] as $username => $val) {
                    if (!in_array($username, $_users)) {
                        unset(self::$redisPool[$status][$username]);
                        Redis::hDel('CRM:Pool:' . $status, $username);
                    }
                }
            }
        }

        $username = null;
        try {
            $pool = self::$redisPool[$status];
            if (empty($pool)) $pool = [];
            asort($pool);
            $keys = array_keys($pool);
            if (empty($keys)) {
                throw new \Exception('没有可以分配的用户');
            }
            $username = $keys[0];
            self::$redisPool[$status][$username] += 1;
            Redis::hIncrBy('CRM:Pool:' . $status, $username, 1);
        } catch (\Exception $e) {
            Log::error(dirname(__FILE__) . __LINE__ . '没有可以分配的用户', func_get_args());
            throw new \Exception('没有可以分配的用户');
        }
        return $username;
    }

    /**
     * @param $thirdProductId
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    protected static function users($thirdProductId) {
        $product = Products::query()->where('third_product_id', $thirdProductId)->find();
        if (empty($product)) {
            return [];
        }
        $users = Admins::where('status', 1)->where('is_order', 1)->whereFindInSet('product_ids', $product->id)->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;
        };

        return $us;
    }

    /**
     * 发送订单短信
     * @param $admin_id
     * @param $order
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function sendOrderSms($admin_id, $order)
    {
        $user = Admins::cache(true)->where('id', $admin_id)->find();
        if ((!config('app.debug', true) || config('app.debug', true) === 'false') && (time() * 1000 - $order->create_at) / 1000 < 2 * 24 * 3600) {
            $has = Blacks::where('mobile', $order->mobile)->find();
            if (empty($has) && !empty($order->mobile)) {
                if (env('SMS_JUMP_URL')) {
                    SMS::juhe_sms_send($order->mobile, 265867, ['title' => $order->product_name, 'mobile' => $user->mobile, 'url' => env('SMS_JUMP_URL')]);
                } else {
                    SMS::juhe_sms_send($order->mobile, 261607, ['title' => $order->product_name, 'mobile' => $user->mobile]);
                }
            } else {
                sleep(10);
            }
        } else {
            Log::info('订单未发送短息:' . json_encode([$order->mobile, 261607, ['title' => $order->product_name, 'mobile' => $user->mobile]]));
        }
    }
}