<?php
namespace App\Domain\Votes\Services;

use DB;
use Carbon\Carbon;
use App\Models\User;
use App\Domain\Points\Models\Point;
use App\Domain\Points\Enums\DirectionEnum;
use App\Domain\Subscriptions\Models\Subscription;
use App\Domain\Subscriptions\Service\SubscriptionService;

class VoteService
{
    public $vote;
    public $leaders;

    public function __construct($vote)
    {
        $leader_count = nova_get_setting('vote_leader_count');
        $leaders = SubscriptionService::leaders();
        $leaders = array_column(array_slice($leaders, 0, $leader_count), 'user_id');
        $this->leaders = $leaders;
        $this->vote = $vote;
    }


    public function accrualPoints()
    {
        DB::beginTransaction();

        $procent_site = (int)nova_get_setting('vote_procent_site');
        $procent_site = $procent_site / 100;

        $procent_top = (int)nova_get_setting('vote_procent_leader');
        $procent_top = $procent_top / 100;

        $procent_local = (int)nova_get_setting('vote_procent_local_leader');
        $procent_local = $procent_local / 100;

        $subscriptions = Subscription::with('user.subscribers.subscription')->where('ends_at', '>', Carbon::now())
        ->where('status', 'complete')->get();

        $sum_site = 0;
        $sdr_leader_pay = 0;
        $sdr_leader_for_all_pay = [];

        foreach ($subscriptions as $subscription) {


            $user = $subscription->user;
            $subscribers = $this->activeSubs($user->subscribers);

            // Фильтр лидеров
            $subscribersLeader = $subscribers->filter(function ($subscriber) {
                return $subscriber->pivot->leader === 1;
            });
             // Фильтр простых пользователей
            $subscribersSimple = $subscribers->filter(function ($subscriber) {
                return $subscriber->pivot->leader === 0;
            });



            $price = $subscription->price;
            $to_site = round($price * $procent_site);
            $sum_site += $to_site;

            $sdr = round($price - $to_site); // сумма для распределения

            $sdr_leader_global = round($sdr * $procent_top);
            $sdr_leader_local = round($sdr * $procent_local);

            $sdr_simple = $sdr - $sdr_leader_global - $sdr_leader_local;

            // добавляем лидерам
            $sdr_leader_pay += $sdr_leader_global;

            //если 0 подписок, но куплена подписка на сайт
            // отдаем лидеру 40%, а 60% сайту
            if($subscribers->isEmpty()){
                $sum_site += ($sdr - $sdr_leader_global); // 20%сайту(вместо локальных) и 40%сайту (вместо простых)
            }else {
                if ($subscribersLeader->isNotEmpty()) {
                    //Выплачиваем каждому локальному лидеру
                    $sdr_parts_local = round($sdr_leader_local / $subscribersLeader->count());
                    //сохраняем транзакции локальных лидеров
                    foreach ($subscribersLeader as $subs) {
                        $sdr_leader_for_all_pay[$subs->id][] = $sdr_parts_local;
                    }
                }else{
                    $sum_site += $sdr_leader_local; //если у пользователя есть подписки, но он не выбрал лидеров
                }

                if ($subscribersSimple->isNotEmpty()) {
                    //Выплачиваем каждому юзеру
                    $sdr_parts = round($sdr_simple / $subscribersSimple->count());
                    //сохраняем транзакции простых пользователей
                    foreach ($subscribersSimple as $subs) {
                        $sdr_leader_for_all_pay[$subs->id][] = $sdr_parts;
                    }
                }else{
                    $sum_site += $sdr_simple;
                }
            }

            $this->updateSubs($subscription);
        }

        $part_for_leader = round($sdr_leader_pay/count($this->leaders));
        foreach ($this->leaders as $leader) {
            $sdr_leader_for_all_pay[$leader][] = $part_for_leader;
        }


       $this->payUsers($sdr_leader_for_all_pay);
       $this->payForSystemUser($sum_site);

        DB::commit();
    }

    private function payUsers($sdr)
    {
        $sdr_users_pay = array_map(function ($lines) {
            return array_sum($lines);
        }, $sdr);


        foreach ($sdr_users_pay as $user_pay_id => $sdr_user) {
            $this->addPoint($user_pay_id, $sdr_user);
        }

    }

    private function payForSystemUser($sum_site)
    {
        $system_user_id = User::system()->id;
        $this->addPoint($system_user_id, $sum_site);
    }


    private function addPoint($user_id, $amount)
    {
        $point = new Point;
        $point->user_id = $user_id;
        $point->point = $amount;
        $point->type = 'votes';  //YSV ENUM!
        $point->direction = DirectionEnum::COMING();
        $point->save();

        $this->vote->users()->attach($user_id, ['payment' => $amount]);
    }

    private function updateSubs($sub)
    {
        $sub->status = 'end'; //YSV ENUM!
        $sub->save();
    }


    //проверка на акт. подписки
    private function activeSubs($subscribers)
    {
        return $subscribers->filter(function ($subscriber) {
            return optional($subscriber->subscription->first())->ends_at > Carbon::now();
        });
    }


    public function freeMode()
    {

        $users = SubscriptionService::freeLeaders();

        foreach ($users as $leader) {
            $this->vote->users()->attach($leader->id, ['payment' => $leader->countVote]);
        }

    }

}
