<?php

namespace App\Domains\Real\Commands\Sync;

use Carbon\Carbon;
use App\Models\Real\Order;
use Illuminate\Support\Facades\DB;
use App\Domains\Card\Jobs\MongoCardJob;
use App\Models\Real\OrderCardPartition;
use App\Domains\Real\Repositories\OrderRepository;
use App\Domains\Real\Repositories\CompanyRepository;
use App\Domains\Real\Repositories\PackageRepository;
use App\Domains\Real\Repositories\OrderCardPartitionRepository;

class OrderBaseSync extends Command
{
    protected $name = 'real:sync-order';

    protected $description = '同步RD基础订单数据';

    protected $companies;

    protected $packages;

    protected static $carrierOperators = [1, 0, 2];

    protected $chunks = 1000;

    public function handle()
    {
        $this->companies = app(CompanyRepository::class)->withTrashed()->get()->keyBy('sn');
        $this->packages = app(PackageRepository::class)->withTrashed()->get()->keyBy('sn');

        $orders = $this->getOrders();
        $cards = $this->getCards($orders);

        try {
            DB::transaction(function () use ($orders, $cards) {
                $this->line('插入订单数据，条数:'.count($orders));
                foreach (array_chunk($orders, $this->chunks) as $data) {
                    $this->getOutput()->write('.');
                    Order::upsert($data, 'id');
                }
                app(OrderRepository::class)->forgetCached();
                $this->line('插入订单数据成功');

                $this->line('插入订单关联数据，条数:'.count($cards));
                foreach (array_chunk($cards, $this->chunks) as $data) {
                    $this->getOutput()->write('.');
                    $orders = DB::table('virtual_order_cards')->select(['sim', 'order_id'])
                        ->whereIn('sim', array_pluck($data, 'sim'))->get()->pluck('order_id', 'sim');

                    foreach ($data as &$value) {
                        $value['virtual_order_id'] = $orders[$value['sim']] ?? 0;
                    }

                    MongoCardJob::dispatch(array_pluck($data, 'sim'));

                    $only = [ 'order_id', 'company_id', 'package_id', 'counts', 'unit_price'];

                    DB::table('real_order_cards')->upsert($data, ['sim', 'deleted_at'], $only);
                }

                app(OrderCardPartitionRepository::class)->forgetCached();
                $this->line('插入订单关联数据成功');
            });
        } catch (\Exception $e) {
            $this->error($e->getMessage());
            throw $e;
        }
    }

    // 查询订单
    protected function getOrders()
    {
        $this->line('查询订单记录');
        $datetime = $this->getDateTime();

        $starttime = $datetime->copy()->startOfMonth()->startOfDay()->format('Y-m-d H:i:s');
        $endtime = $datetime->copy()->endOfMonth()->endOfDay()->format('Y-m-d H:i:s');

        $select = [
            'o_id',
            'o_number',
            'o_customer_number',
            'o_customer_name',
            'o_p_number',
            'o_p_name',
            'o_create_date',
            'o_create_time',
            'o_update_time',
            'o_amount',
            'o_price',
            'o_card_counts',
            'o_address',
            'o_contacts',
            'o_contact_number',
            'o_remark',
            'o_logistics_content',
            'o_is_del',
        ];

        $orders = DB::connection('real')->table('jxc_order')->select($select)->where(function ($query) {
            $query->where('o_status', '已出库待确认')->orWhere('o_status', '已确认');
        })->whereBetween('o_create_date', [$starttime, $endtime])->where('o_card_use', '销售卡')
            ->whereNotIn('o_b_number', config('filter.bloc'))->whereIn('o_customer_number', $this->companies->pluck('sn')->toArray())
            ->orderBy('o_create_date')->get()->keyBy('o_number')->toArray();

        $array = [];

        foreach ($orders as $item) {
            $item = (array)$item;

            $array[] = [
                'id' => $item['o_id'],
                'sn' => $item['o_number'],
                'type' => 0,
                'company_id' => $this->companies[$item['o_customer_number']]['id'] ?? 0,
                'package_id' => $this->packages[$item['o_p_number']]['id'] ?? 0,
                'transaction_no' => '',
                'pay_channel' => 'bank',
                'unit_price' => intval($item['o_price'] * 100),
                'counts' => $item['o_card_counts'],
                'total_price' => intval($item['o_amount'] * 100),
                'order_at' => Carbon::parse($item['o_create_date'])->format('Y-m-d H:i:s'),
                'address' => $item['o_address'],
                'contacts' => $item['o_contacts'],
                'mobile' => substr(preg_replace('/[^0-9]+/', '', single_case($item['o_contact_number'])), 0, 11),
                'remark' => $item['o_remark'],
                'logistics_remark' => $item['o_logistics_content'],
                'created_at' => date('Y-m-d H:i:s', $item['o_create_time']),
                'updated_at' => $item['o_update_time'],
                'deleted_at' => $item['o_is_del'] ? $item['o_update_time'] : null,
            ];
        }

        return $array;
    }

    // 获取月销售卡数据
    protected function getCards($orders)
    {
        $orders = array_keyBy($orders, 'sn');
        $orderRows = $this->getOrderRows($orders);
        $orderItems = $this->getOrderItems($orderRows);

        $cards = [];

        foreach ($orderItems as &$item) {
            $item['s_section_number'] = json_decode($item['s_section_number'], true);
            $item['o_number'] = $orderRows[$item['s_number']]['o_number'];

            foreach ($item['s_section_number'] as $value) {
                $sim = explode('-', $value['section_no'])[0];
                $order = $orders[$item['o_number']];

                for ($i=0; $i < $value['counts']; $i++) {
                    $cards[] = [
                        'type' => 0,
                        'sim' => intval($sim),
                        'order_id' => $order['id'],
                        'company_id' => $order['company_id'],
                        'package_id' => $order['package_id'],
                        'counts' => 1,
                        'unit_price' => $order['unit_price'],
                        'created_at' => $order['created_at'],
                        'updated_at' => $order['updated_at'],
                        'deleted_at' => $order['deleted_at'],
                    ];

                    $sim++;
                }
            }
        }

        unset($orderRows);
        unset($orderItems);

        $this->line('排单卡总数: ' . count($cards));

        $cards = array_sort($cards, function ($item) {
            return $item['order_at'];
        });

        $cards = array_keyBy($cards, 'sim');

        $this->line('排重后卡总数: ' . count($cards));

        return array_values($cards);
    }

    // 查询排单记录
    protected function getOrderRows($orders)
    {
        $this->line('查询排单记录');
        $orderRows = DB::connection('real')->table('jxc_order_single_row')->select('o_number', 's_number', 's_create_time')
        ->whereIn('o_number', array_pluck($orders, 'sn'))->where(function ($query) {
            $query->where('s_status', 4)->where('s_card_counts', '>', 0);
        })->get()->keyBy('s_number')->toArray();

        foreach ($orderRows as &$item) {
            $item = (array)$item;
        }

        return $orderRows;
    }

    // 查询排单详情
    protected function getOrderItems($orderRows)
    {
        $this->line('查询排单详情');

        $orderItems = DB::connection('real')->table('jxc_order_single_row_item')
        ->select('i_id', 's_number', 's_section_number')
        ->whereIn('s_number', array_keys($orderRows))->get()->toArray();

        foreach ($orderItems as &$item) {
            $item = (array)$item;
        }

        return $orderItems;
    }
}
