<?php

namespace App\Domains\Virtual\Commands\Sync;

use Carbon\Carbon;
use App\Models\Virtual\FlowPool;
use Illuminate\Support\Facades\DB;
use App\Models\Virtual\FlowPoolSetting;
use App\Models\Real\FlowPool as RealFlowPool;
use App\Domains\Virtual\Services\CommonService;
use App\Domains\Virtual\Repositories\CompanyRepository;
use App\Domains\Virtual\Repositories\PackageRepository;
use App\Domains\Virtual\Repositories\FlowPoolRepository;
use App\Domains\Virtual\Repositories\FlowPoolSettingRepository;

class FlowPoolSync extends Command
{
    protected $name = 'virtual:sync-flow-pool';

    protected $description = '同步VD流量池';

    protected static $carrier_operator = [10 => 0, 11 => 1, 12 => 2];
    protected static $shared = [10 => 2, 11 => 1];

    public function handle()
    {
        $companies = app(CompanyRepository::class)->withTrashed()->get()->keyBy('sn');
        $packages = app(PackageRepository::class)->withTrashed()->get()->keyBy('sn');
        $flowPools = FlowPool::withTrashed()->select(['id', 'sn'])->get()->keyBy('sn');
        $realFlowPools = RealFlowPool::select(['id', 'sn'])->get()->keyBy('sn');

        $oldFlowPools = DB::connection('vd_old')->table('ckb_data_pool')->select([
            'dp_sn',
            'dp_name',
            'dp_carrieroperator',
            'dp_share_type',
            'dp_vd_company_id',
            'dp_vd_packages',
            'dp_td_data_pool_sn',
            'dp_del',
            'dp_create_time',
        ])->get()->collect()->toArray();

        $oldFlowPoolSettings = DB::connection('vd_old')->table('ckb_data_pool_setting')->select([
            'dp_sn',
            'year_month',
            'dp_billing_rules',
            'dp_min_cost_rules',
        ])->get()->collect()->groupBy('dp_sn')->toArray();

        $maxId = FlowPool::withTrashed()->max('id');

        $array = [];
        $settingArray = [];

        foreach ($oldFlowPools as $key => $value) {
            $id = ++$maxId;
            $id = isset($flowPools[$value['dp_sn']]) ? $flowPools[$value['dp_sn']]['id'] : $id;

            $flowPoolPackages = json_decode($value['dp_vd_packages'], true);

            $flowPoolPackages = array_map(function ($item) use ($packages) {
                $sn = explode('---', $item)[0];
                return $packages[$sn]['id'];
            }, $flowPoolPackages);

            $settings =  $oldFlowPoolSettings[$value['dp_sn']];

            $settings = array_values(array_sort($settings, function ($item) {
                return $item['year_month'];
            }));

            foreach ($settings as $i => $item) {
                $dp_billing_rules = json_decode($item['dp_billing_rules'], true);
                $dp_min_cost_rules = json_decode($item['dp_min_cost_rules'], true);

                $month = Carbon::parse(substr_replace($item['year_month'], '-', 4, 0));

                if (count($settings) === 1) {
                    $start_at = '2000-01-01 00:00:00';
                    $end_at = '3000-01-31 23:59:59';
                } else {
                    if ($i === 0) {
                        $start_at = '2000-01-01 00:00:00';
                    } else {
                        $start_at = Carbon::parse(substr_replace($item['year_month'], '-', 4, 0))->format('Y-m-d H:i:s');
                    }

                    if ($i !== count($settings) - 1) {
                        $nextMonth = substr_replace($settings[$i+1]['year_month'], '-', 4, 0);
                        $end_at = Carbon::parse($nextMonth)->subMonth()->endOfMonth()->format('Y-m-d H:i:s');
                    } else {
                        $end_at = '3000-01-31 23:59:59';
                    }
                }

                $settingData = [
                    'pool_id' => $id,
                    'gradient_price' => intval($dp_billing_rules['first_month_price']) * 100,
                    'gradient' => floatval($dp_billing_rules['data_step_num']),
                    'gradient_unit' => $dp_billing_rules['data_step_num_unit'] === 'M' ? 0 : 1,
                    'start_at' => $start_at,
                    'end_at' => $end_at,
                    'created_at' => $month->copy()->startOfMonth()->format('Y-m-d H:i:s'),
                    'updated_at' => $month->copy()->startOfMonth()->format('Y-m-d H:i:s'),
                ];

                $minimum_settings = [];

                foreach ($dp_min_cost_rules as $package => $rule) {
                    $sn = explode('---', $package)[0];
                    $minimum_settings[] = [
                        'package_id' => $packages[$sn]['id'],
                        'flows' => floatval($rule['dp_min_cost_data']),
                        'price' => $rule['dp_min_cost_money'] * 100,
                    ];
                }

                $settingData['minimum_settings'] = json_encode($minimum_settings);

                $settingArray[] = $settingData;
            }

            $real_pool_ids = [];

            foreach (json_decode($value['dp_td_data_pool_sn'], true) as $pool_sn) {
                $pool_sn = explode('---', $pool_sn)[0];
                if (isset($realFlowPools[$pool_sn])) {
                    array_push($real_pool_ids, $realFlowPools[$pool_sn]['id']);
                }
            }

            $data = [
                'id' => $id,
                'sn' => $value['dp_sn'],
                'name' => $value['dp_name'],
                'company_id' => $companies[CommonService::stringifyCompanyId($value['dp_vd_company_id'])]['id'],
                'carrier_operator' => self::$carrier_operator[$value['dp_carrieroperator']],
                'shared' => self::$shared[$value['dp_share_type']],
                'package_ids' => json_encode($flowPoolPackages),
                'real_pool_ids' => json_encode($real_pool_ids),
                'start_at' => date('Y-m-1 00:00:00', $value['dp_create_time']),
                'remark' => '',
                'created_at' => date('Y-m-d H:i:s', $value['dp_create_time']),
                'updated_at' => date('Y-m-d H:i:s'),
                'deleted_at' => $value['dp_del'] ? date('Y-m-d H:i:s') : null,
            ];

            $array[] = $data;
        }

        FlowPool::upsert($array, 'id');
        $maxId = FlowPoolSetting::withoutTrashed()->max('id');
        if ($maxId) {
            FlowPoolSetting::whereIn('pool_id', array_pluck($array, 'id'))->forceDelete();
            DB::statement("select setval('virtual_flow_pool_settings_id_seq', {$maxId})");
        }
        FlowPoolSetting::insert($settingArray);

        app(FlowPoolRepository::class)->forgetCached();
        app(FlowPoolSettingRepository::class)->forgetCached();
    }
}
