<?php
namespace App\Domains\Stats\Services;

use App\Core\Service;
use Illuminate\Support\Facades\DB;
use App\Exceptions\NotAllowedException;
use App\Domains\Virtual\Services\CommonService;
use App\Domains\Virtual\Repositories\OrderRepository;
use App\Domains\Virtual\Repositories\CompanyRepository;
use App\Domains\Virtual\Repositories\PackageRepository;
use App\Domains\Virtual\Repositories\OrderCardPartitionRepository;

class OrderService extends Service
{
    protected $companyRepository;
    protected $packageRepository;
    protected $orderRepository;
    protected $orderCardPartitionRepository;

    /**
     * 构造函数
     *
     * @return void
     */
    public function __construct(
        CompanyRepository $companyRepository,
        PackageRepository $packageRepository,
        OrderRepository $orderRepository,
        OrderCardPartitionRepository $orderCardPartitionRepository
    ) {
        $this->companyRepository = $companyRepository;
        $this->packageRepository = $packageRepository;
        $this->orderRepository = $orderRepository;
        $this->orderCardPartitionRepository = $orderCardPartitionRepository;
    }


    /**
     * 统计
     *
     * @return void
     */
    public function index(array $conditions = [])
    {
        $repository =  $this->orderCardPartitionRepository->where('type', $conditions['type']);

        $companies = $this->companyRepository->withTrashed()->get()->pluck('name', 'id')->toArray();
        $packages = $this->packageRepository->withTrashed()->get()->pluck('name', 'id')->toArray();

        $select = [
            DB::raw("array_to_string(array_agg(id), ',') as order_id"),
            'company_id',
            'package_id',
            'unit_price',
            'pay_channel',
            DB::raw('SUM(counts) as counts'),
            DB::raw('SUM(custom_price) as custom_price'),
        ];

        $orders = $this->orderRepository->select($select)->withConditions($conditions)->applyConditions()
            ->groupBy(['company_id', 'package_id', 'unit_price', 'pay_channel'])->paginate($conditions['limit']);

        $order_ids = [];

        foreach ($orders as $order) {
            $order_ids = array_merge($order_ids, str_to_array($order->order_id));
        }

        $order_ids = array_unique($order_ids);

        $members = $repository->select([
            'order_id',
            DB::raw('COUNT(distinct sim) as counts'),
        ])->withConditions(['order_id' => $order_ids])->groupBy('order_id')->get()->keyBy('order_id');

        $orders->map(function ($item) use ($companies, $packages, $members) {
            $item->unit_price = sprintf('%.02f', $item->unit_price/100);
            $item->custom_price = sprintf('%.02f', $item->custom_price/100);
            $item->company_name = $companies[$item->company_id];
            $item->package_name = $packages[$item->package_id];

            $order_ids = str_to_array($item->order_id);

            $item->members = 0;

            foreach ($order_ids as $id) {
                $item->members += $members[$id]['counts'] ?? 0;
            }

            $item->pay_channel_name = CommonService::namePayChannel($item->pay_channel);
        });

        return $orders;
    }

    /**
     * 明细
     *
     * @return void
     */
    public function detail(array $conditions = [])
    {
        $repository =  $this->orderCardPartitionRepository->where('type', $conditions['type']);

        $cards = $repository->withConditions($conditions)->applyConditions()->paginate($conditions['limit']);

        return self::detailTransformer($cards);
    }

    /**
     * 格式转化
     *
     * @param mixed $cards
     * @return mixed
     */
    public static function detailTransformer($cards)
    {
        $companies = app(CompanyRepository::class)->withTrashed()->get()->pluck('name', 'id')->toArray();
        $packages = app(PackageRepository::class)->withTrashed()->get()->keyBy('id')->toArray();
        $orders = app(OrderRepository::class)->withTrashed()
            ->select(['id', 'unit_price', 'pay_channel', 'order_at'])
            ->withConditions(['id' => array_unique(array_pluck($cards, 'order_id'))])->get()->keyBy('id')->toArray();

        $cards->map(function ($item) use ($companies, $packages, $carrierOperators, $orders) {
            $package = $packages[$item->package_id];
            $order = $orders[$item->order_id];

            $item->company_name = $companies[$item->company_id];
            $item->package_name = $package['name'];
            $item->carrier_operator_name = $carrierOperators[$package['carrier_operator']];
            $item->service_months = $package['service_months'];
            $item->unit_price = sprintf('%.02f', $order['unit_price']/100);
            $item->pay_channel_name = CommonService::namePayChannel($order['pay_channel']);
            $item->order_at = $order['order_at'];
        });

        return $cards;
    }
}
