<?php

namespace App\Domains\Real\Commands\Sync;

use App\Models\Real\Package;
use Illuminate\Support\Facades\DB;
use App\Exceptions\InvalidArgumentException;
use App\Domains\Real\Repositories\CompanyRepository;
use App\Domains\Real\Repositories\PackageRepository;

class PackageSync extends Command
{
    protected $name = 'real:sync-package';

    protected $description = '同步RD套餐数据';

    protected $companies;

    protected static $carrier_operator = [
        'lt' => 0,
        'yd' => 1,
        'dx' => 2,
        'qw' => 3,
    ];

    public function handle()
    {
        $datetime = $this->getDateTime();
        $this->companies = app(CompanyRepository::class)->withTrashed()->get()->pluck('sn')->toArray();

        $basePackages = $this->getBasePackages();

        Package::upsert($basePackages, ['sn', 'deleted_at']);

        $basePackages = Package::where('type', 0)->get()->toArray();

        $renewalPackages = $this->getRenewalPackages($basePackages);

        $flowPackages = $this->getFlowPackages();
        $optionalPackages = $this->getOptionalPackages();
        $additionalPackages = $this->getAdditionalPackages();
        $groupPackages = $this->getGroupPackages($basePackages);

        $packages = array_merge($renewalPackages, $flowPackages, $optionalPackages, $additionalPackages, $groupPackages);

        Package::upsert($packages, ['sn', 'deleted_at']);

        app(PackageRepository::class)->forgetCached();
    }

    // 基础包
    protected function getBasePackages()
    {
        $select = [
            DB::raw('0 as type'),
            'jxc_package.package_sn as sn',
            'jxc_package.name as name',
            'jxc_package.carrieroperator as carrier_operator',
            'jxc_package.price as cost_price',
            'jxc_package.guide_price as guide_price',
            'jxc_package.flows as flows',
            'jxc_package.voices as voices',
            'jxc_package.short_msg as messages',
            'jxc_package.short_msg_on as has_messages',
            'jxc_package.lbs as has_lbs',
            'jxc_package.flow_cycle as reset_months',
            'jxc_package.package_cycle as service_months',
            'jxc_package.del as del',
            DB::raw("FROM_UNIXTIME(jxc_package.create_time, '%Y-%m-%d %H:%i:%s') as created_at"),
        ];

        $packages = DB::connection('real')->table('jxc_package')->join('jxc_package_custom_relation', function ($join) {
            $join->on('jxc_package_custom_relation.package_sn', '=', 'jxc_package.package_sn')
            ->whereIn('jxc_package_custom_relation.custom_no', $this->companies);
        })->select($select)->where('type', 11)->get();

        return $this->transform($packages);
    }

    // 续费包
    protected function getRenewalPackages($basePackages)
    {
        $basePackages = array_keyBy($basePackages, 'sn');

        $select = [
            DB::raw('2 as type'),
            'jxc_package_renewal.bag_number as sn',
            'jxc_package_renewal.package_sn as parent_sn',
            'jxc_package_renewal.name as name',
            'jxc_package_renewal.price as cost_price',
            'jxc_package_renewal.guide_price as guide_price',
            'jxc_package_renewal.service_cycle as service_months',
            'jxc_package_renewal.create_time as created_at',
            'jxc_package_renewal.del',
        ];

        $packages = DB::connection('real')->table('jxc_package_renewal')->join('jxc_package_value_add_relation', function ($join) {
            $join->on('jxc_package_value_add_relation.value_add_number', '=', 'jxc_package_renewal.bag_number')
            ->whereIn('jxc_package_value_add_relation.custom_no', $this->companies)
            ->where('jxc_package_value_add_relation.type', 1);
        })->select($select)->get();

        $packages->map(function ($item) use ($basePackages) {
            $basePackage = $basePackages[$item->parent_sn];

            if (!$basePackage) {
                throw new InvalidArgumentException('续费包未找到对应基础套餐 #:'.$item->sn);
            }

            $item->parent_id = $basePackage['id'];
            $item->carrier_operator = array_flip(self::$carrier_operator)[$basePackage['carrier_operator']] ?? 'qw';
            $item->flows = $basePackage['flows'];
            $item->voices = $basePackage['voices'];
            $item->messages = $basePackage['messages'];
            $item->has_messages = $basePackage['has_messages'];
            $item->has_lbs = $basePackage['has_lbs'];
            $item->reset_months = $basePackage['reset_months'];
        });

        return $this->transform($packages);
    }

    // 加油包
    protected function getFlowPackages()
    {
        $select = [
            DB::raw('3 as type'),
            'jxc_package_flows.bag_number as sn',
            'jxc_package_flows.name as name',
            'jxc_package_flows.carrieroperator as carrier_operator',
            'jxc_package_flows.price as cost_price',
            'jxc_package_flows.guide_price as guide_price',
            'jxc_package_flows.flows as flows',
            'jxc_package_flows.voices as voices',
            'jxc_package_flows.short_msg as messages',
            'jxc_package_flows.lbs as has_lbs',
            'jxc_package_flows.flows_cycle as reset_months',
            'jxc_package_flows.service_cycle as service_months',
            'jxc_package_flows.create_time as created_at',
            'jxc_package_flows.del',
        ];

        $packages = DB::connection('real')->table('jxc_package_flows')->join('jxc_package_value_add_relation', function ($join) {
            $join->on('jxc_package_value_add_relation.value_add_number', '=', 'jxc_package_flows.bag_number')
            ->whereIn('jxc_package_value_add_relation.custom_no', $this->companies)
            ->where('jxc_package_value_add_relation.type', 2);
        })->select($select)->get();

        return $this->transform($packages);
    }

    // 可选包
    protected function getOptionalPackages()
    {
        $select = [
            DB::raw('4 as type'),
            'jxc_package_optional.bag_number as sn',
            'jxc_package_optional.name as name',
            'jxc_package_optional.carrieroperator as carrier_operator',
            'jxc_package_optional.price as cost_price',
            'jxc_package_optional.guide_price as guide_price',
            'jxc_package_optional.flows as flows',
            'jxc_package_optional.voices as voices',
            'jxc_package_optional.short_msg as messages',
            'jxc_package_optional.lbs as has_lbs',
            'jxc_package_optional.flows_cycle as reset_months',
            'jxc_package_optional.service_cycle as service_months',
            'jxc_package_optional.create_time as created_at',
            'jxc_package_optional.del',
        ];

        $packages = DB::connection('real')->table('jxc_package_optional')->join('jxc_package_value_add_relation', function ($join) {
            $join->on('jxc_package_value_add_relation.value_add_number', '=', 'jxc_package_optional.bag_number')
            ->whereIn('jxc_package_value_add_relation.custom_no', $this->companies)
            ->where('jxc_package_value_add_relation.type', 3);
        })->select($select)->get();

        return $this->transform($packages);
    }

    // 可选包
    protected function getAdditionalPackages()
    {
        $select = [
            DB::raw('5 as type'),
            'jxc_package_addoptional.bag_number as sn',
            'jxc_package_addoptional.name as name',
            DB::raw('"qw" as carrier_operator'),
            DB::raw('0 as cost_price'),
            'jxc_package_addoptional.guide_price as guide_price',
            DB::raw('0 as flows'),
            'jxc_package_addoptional.content_count as messages',
            'jxc_package_addoptional.reset_cycle as reset_months',
            'jxc_package_addoptional.service_cycle as service_months',
            'jxc_package_addoptional.create_time as created_at',
            'jxc_package_addoptional.del',
        ];

        $packages = DB::connection('real')->table('jxc_package_addoptional')->join('jxc_package_value_add_relation', function ($join) {
            $join->on('jxc_package_value_add_relation.value_add_number', '=', 'jxc_package_addoptional.bag_number')
            ->whereIn('jxc_package_value_add_relation.custom_no', $this->companies)
            ->where('jxc_package_value_add_relation.type', 4);
        })->select($select)->where('jxc_package_addoptional.tid', 1)->get();

        return $this->transform($packages);
    }

    // 组合包
    protected function getGroupPackages($basePackages)
    {
        $basePackages = array_keyBy($basePackages, 'sn');

        $select = [
            DB::raw('6 as type'),
            'jxc_package_group.sn as sn',
            'jxc_package_group.name as name',
            'jxc_package_group_item.package_sn as parent_sn',
            'jxc_package_group.price as cost_price',
            'jxc_package_group.price as guide_price',
            'jxc_package_group.createtime as created_at',
            'jxc_package_group.del',
        ];

        $packages = DB::connection('real')->table('jxc_package_group')->join('jxc_package_group_item', function ($join) {
            $join->on('jxc_package_group_item.sn', '=', 'jxc_package_group.sn')
                ->where('jxc_package_group_item.type', 1);
        })->select($select)->get();

        $packages->map(function ($item, $index) use ($basePackages, &$packages) {
            $basePackage = $basePackages[$item->parent_sn];

            if (!$basePackage) {
                unset($packages[$index]);
                return;
                throw new InvalidArgumentException('组合包未找到对应基础套餐 #:'.$item->sn);
            }

            $item->parent_id = $basePackage['id'];
            $item->carrier_operator = array_flip(self::$carrier_operator)[$basePackage['carrier_operator']] ?? 'qw';
            $item->flows = $basePackage['flows'];
            $item->voices = $basePackage['voices'];
            $item->messages = $basePackage['messages'];
            $item->has_messages = $basePackage['has_messages'];
            $item->has_lbs = $basePackage['has_lbs'];
            $item->reset_months = $basePackage['reset_months'];
            $item->service_months = $basePackage['service_months'];
        });

        return $this->transform($packages);
    }

    protected function transform($packages)
    {
        $packages = $packages->toArray();

        foreach ($packages as &$package) {
            $package = (array)$package;
            $package['name'] = trim($package['name']);
            $package['parent_id'] = $package['parent_id'] ?? 0;
            $package['carrier_operator'] = self::$carrier_operator[$package['carrier_operator']] ?? 255;
            $package['cost_price'] =  intval(floatval($package['cost_price']) * 100);
            $package['guide_price'] = intval(floatval($package['guide_price']) * 100);
            $package['flows'] = intval($package['flows']);
            $package['voices'] = intval($package['voices']);
            $package['messages'] = intval($package['messages']);
            $package['has_messages'] = $package['has_messages'] ?? 0;
            $package['has_lbs'] = $package['has_lbs'] ?? 0;
            $package['reset_months'] = $package['reset_months'] ?? 0;
            $package['service_months'] = $package['service_months'] ?? 0;

            $package['updated_at'] = date('Y-m-d H:i:s');
            $package['deleted_at'] = $package['del'] ? date('Y-m-d H:i:s') : null;
            unset($package['del']);
            unset($package['parent_sn']);

            ksort($package);
        }

        return array_values(array_keyBy($packages, 'sn'));
    }
}
