<?php
namespace App\Domains\Virtual\Http\Controllers;

use App\Dicts;
use App\Core\Controller;
use Illuminate\Http\Request;
use App\Exceptions\NotExistException;
use App\Exceptions\NotAllowedException;
use App\Domains\Virtual\Exports\OrderExport;
use App\Exceptions\InvalidArgumentException;
use App\Domains\Config\Services\ConfigService;
use App\Domains\Export\Services\ExportService;
use App\Domains\Export\Services\ImportService;
use App\Domains\Virtual\Services\OrderService;
use App\Domains\Virtual\Services\CommonService;
use App\Domains\Virtual\Exports\OrderCardExport;
use App\Domains\Virtual\Services\CompanyService;
use App\Domains\Virtual\Services\PackageService;
use App\Domains\Virtual\Repositories\OrderRepository;
use App\Domains\Virtual\Repositories\OrderCardPartitionRepository;

class OrderController extends Controller
{
    protected $request;
    protected $orderService;

    /**
     * 构造函数，自动注入.
     */
    public function __construct(Request $request, OrderService $orderService)
    {
        $this->request = $request;
        $this->orderService = $orderService;
    }

    /**
     * 列表.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Dicts $dicts)
    {
        $conditions = $this->request->all();
        $conditions['limit'] = $this->request->get('limit', 20);

        if (isset($conditions['sim'])) {
            $conditions['sim'] = array_map('intval', array_map('trim', str_to_array($conditions['sim'], "\n")));
        }

        $orders = $this->orderService->paginate($conditions);

        $carrierOperators = $dicts->get('carrier_operator');
        $orderStatues = $dicts->get('order_status');
        $transactionStatuses = $dicts->get('transaction_status');
        $logistics = app(ConfigService::class)->get('logistics');

        $orders->transform(function ($item) use ($carrierOperators, $orderStatues, $transactionStatuses, $logistics) {
            return collect([
                'id' => $item->id,
                'sn' => $item->sn,
                'transaction_no' => $item->transaction_no,
                'package_id' => $item->package_id,
                'package_name' => $item->package['name'],
                'company_id' => $item->company_id,
                'company_name' => $item->company['name'],
                'pay_channel' => $item->pay_channel,
                'pay_channel_name' => CommonService::namePayChannel($item->pay_channel),
                'carrier_operator' => $item->package['carrier_operator'],
                'carrier_operator_name' => $carrierOperators[$item->package['carrier_operator']],
                'unit_price' => $item->unit_price,
                'counts' => $item->counts,
                'total_price' => $item->total_price,
                'custom_price' => $item->custom_price,
                'shipments' => $item->shipments,
                'refunds' => $item->refunds,
                'order_status' => $item->order_status,
                'order_status_name' => $orderStatues[$item->order_status],
                'transaction_status' => $item->transaction_status,
                'transaction_status_name' => $transactionStatuses[$item->transaction_status],
                'remark' => $item->remark ?? '',
                'order_at' => (string) $item->order_at,
                'deleted_at' => (string) $item->deleted_at,
                'area' => $item->area ?? [],
                'address' => $item->address ?? '',
                'contacts' => $item->contacts,
                'mobile' => $item->mobile,
                'logistics_remark' => $item->logistics_remark ?? '',
                'logistics_company_name' => $logistics[$item->logistics_company] ?? '',
                'logistics_no' => $item->logistics_no,
                'extends' => [
                    'cancel_remark' => $item->extends['cancel_remark'] ?? '',
                    'refund_channel' => $item->extends['refund_channel'] ?? '',
                    'refund_account' => $item->extends['refund_account'] ?? '',
                    'refund_remark' => $item->extends['refund_remark'] ?? '',
                ],
            ]);
        });

        return res($orders, '订单列表', 201);
    }


    /**
     * 导出订单.
     *
     * @return \Illuminate\Http\Response
     */
    public function export()
    {
        $conditions = $this->request->all();

        if (isset($conditions['sim'])) {
            $conditions['sim'] = array_map('intval', array_map('trim', str_to_array($conditions['sim'], "\n")));
        }

        try {
            $total = app(OrderRepository::class)->withConditions($conditions)->count();

            if ($total > 200000) {
                throw new NotAllowedException('数据量过大，请筛选后再进行导出');
            }

            $queue = $total > 30000;

            $export = new OrderExport($conditions);
            $url = ExportService::store($export, 'public', $queue);
        } catch (\Exception $e) {
            throw $e;
        }

        return res($url, '导出成功', 201);
    }


    /**
    * 订单详情
    */
    public function show(Dicts $dicts, $id)
    {
        if (!$order = app(OrderRepository::class)->find($id)) {
            throw new NotExistException('订单不存在或已删除');
        }

        $logistics = app(ConfigService::class)->get('logistics');

        $carrierOperators = $dicts->get('carrier_operator');
        $orderStatues = $dicts->get('order_status');
        $transactionStatuses = $dicts->get('transaction_status');

        $company = CompanyService::load($order->company_id);
        $package = PackageService::load($order->package_id);

        $order->company_name = $company['name'];
        $order->package_name = $package['name'];
        $order->pay_channel = CommonService::namePayChannel($order->pay_channel);
        $order->carrier_operator = $package['carrier_operator'];
        $order->carrier_operator_name = $carrierOperators[$package['carrier_operator']];
        $order->order_status_name = $orderStatues[$order->order_status];
        $order->transaction_status_name = $transactionStatuses[$order->transaction_status];
        $order->logistics_company_name = $logistics[$order->logistics_company] ?? '';
        $order->unit_price = sprintf('%.02f', $order->unit_price/100);
        $order->total_price = sprintf('%.02f', $order->total_price/100);
        $order->custom_price = sprintf('%.02f', $order->custom_price/100);

        $order->extends = [
            'cancel_remark' => $order->extends['cancel_remark'] ?? '',
            'refund_channel' => $order->extends['refund_channel'] ?? '',
            'refund_account' => $order->extends['refund_account'] ?? '',
            'refund_remark' => $order->extends['refund_remark'] ?? '',
        ];

        return res($order, '订单详情', 201);
    }

    /**
     * 下单
     */
    public function create()
    {
        $attributes = $this->request->all();
        $attributes['source'] = 1;

        $res = $this->orderService->store($attributes);

        return res($res, '下单成功');
    }


    /**
     * 编辑.
     *
     * @return \Illuminate\Http\Response
     */
    public function update($id)
    {
        $attributes = $this->request->all();
        $attributes['id'] = $id;

        $order = $this->orderService->store($attributes);

        return res($order, '修改成功');
    }

    /**
     * 删除.
     *
     * @return \Illuminate\Http\Response
     */
    public function destroy()
    {
        $ids = $this->request->ids();

        $this->orderService->destroy($ids);

        return res(true, '删除成功');
    }

    /**
     * 重置.
     *
     * @return \Illuminate\Http\Response
     */
    public function reset()
    {
        $ids = $this->request->ids();

        $this->orderService->reset($ids);

        return res(true, '重置成功');
    }

    /**
     * 卡清单.
     *
     * @return \Illuminate\Http\Response
     */
    public function cards()
    {
        $conditions = $this->request->all();

        $cards = $this->orderService->cards($conditions);

        return res($cards, '卡清单');
    }

    /**
     * 导出卡清单.
     *
     * @return \Illuminate\Http\Response
     */
    public function cardsExport()
    {
        $conditions = $this->request->all();

        if (isset($conditions['sim'])) {
            $conditions['sim'] = array_map('intval', array_map('trim', str_to_array($conditions['sim'], "\n")));
        }

        try {
            $total = app(OrderCardPartitionRepository::class)->withConditions($conditions)->count();

            if ($total > 200000) {
                throw new NotAllowedException('数据量过大，请筛选后再进行导出');
            }

            $queue = $total > 30000;

            $export = new OrderCardExport($conditions);
            $url = ExportService::store($export, 'public', $queue);
        } catch (\Exception $e) {
            throw $e;
        }

        return res($url, '导出成功', 201);
    }

    /**
     * 排单.
     *
     * @return \Illuminate\Http\Response
     */
    public function ship()
    {
        $type = $this->request->get('type');

        if (!in_array($type, [1, 2])) {
            throw new InvalidArgumentException('排单方式不正确');
        }

        $orderId = $this->request->get('order_id');

        $simArray = [];

        if ($type == 1) {
            $file = $this->request->file('file');
            $simArray = ImportService::load($file, ['sim']);
            $simArray = array_pluck($simArray, 'sim');
        }

        if ($type == 2) {
            $segments = $this->request->get('segments');

            if (!is_array($segments) || empty($segments)) {
                throw new InvalidArgumentException('参数错误');
            }

            foreach ($segments as $segment) {
                $interval = intval($segment['end_no']) - intval($segment['start_no']);

                if ($interval < 0) {
                    throw new InvalidArgumentException('结束号段比较大于开始号段');
                }

                if ($interval > 10000) {
                    throw new InvalidArgumentException('一次排号限制10000张');
                }

                for ($i = intval($segment['start_no']); $i <= intval($segment['end_no']); $i++) {
                    array_push($simArray, $i);
                }
            }
        }

        $simArray = array_map(function ($item) {
            return intval(trim(str_replace("\t", '', $item)));
        }, $simArray);

        $order = $this->orderService->ship($orderId, $simArray);

        return res($order, '排单成功');
    }

    /**
     * 套餐升级.
     *
     * @return \Illuminate\Http\Response
     */
    public function upgrade()
    {


        $attributes = $this->request->all();

        $order = $this->orderService->upgrade($attributes);

        return res($order, '修改成功');
    }
}
