<?php

namespace App\Http\Controllers;

use DB;
use Hash;
use Carbon\Carbon;
use App\Models\User;
use Inertia\Inertia;
use Illuminate\Support\Str;
use App\Domain\Tags\Models\Tag;
use Illuminate\Validation\Rule;
use App\Domain\Feeds\Models\Feed;
use App\Notifications\Subscribed;
use App\Domain\Points\Models\Point;
use App\Notifications\LeaderChoice;
use Illuminate\Support\Facades\App;
use App\Domain\Feeds\Service\LiveFeed;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Database\Eloquent\Builder;
use App\Domain\Points\Enums\DirectionEnum;
use App\Domain\Votes\Services\VoteService;
use Illuminate\Http\Request as HttpRequest;
use App\Domain\Subscriptions\Models\Package;
use App\Domain\Subscriptions\Models\Subscription;
use App\Domain\Users\DataTransferObjects\UserData;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
use App\Domain\Subscriptions\Service\SubscriptionService;

class UsersController extends Controller
{

    public function __construct()
    {
        $this->middleware('subs.paid')->except('update', 'plan', 'postsCount', 'searchUserTag', 'testPaid');
    }

    public function index()
    {

        $users = User::filter(Request::only('search', 'sex'))
        ->where('id', '<>', auth()->user()->id)
        ->where('username', '<>', 'inner_systemuser_api')
        ->withCount(['subscriber_reverse as is_sub' => function (Builder $query)  {
            $query->where('user_id', auth()->user()->id);
        }])
        ->withCasts(['is_sub' => 'boolean'])
        ->orderBy('id', 'desc')
        ->cursorPaginate(User::PAGINATE);

        $nextCursor = get_cursor_hash($users);
        $users->transform(function ($user) {
            return array_merge([
                'is_sub' => $user->is_sub,
            ], UserData::fromModel($user)->toArray());
        });

        if(request()->wantsJson()){
            return ['collections' => $users->items(), 'next' => $nextCursor];
        }

        return Inertia::render('User/Index', [
            'filters' => Request::all('search', 'sex'),
            'nextCursor' => $nextCursor,
            'users' => $users->items(),
            'per_page' => User::PAGINATE,
        ]);
    }

    public function testing()
    {



        // $leaders = collect(SubscriptionService::leaders());
        $vote = (object) ['procent_site' => 10, 'procent_top' => 60];
        $t = (new VoteService($vote))->freeMode();
        dd($t);
        // $ids = $leaders->pluck('user_id');
        // $users = User::whereIn('id', $ids)->get();
        // $leaderUsers = $leaders->map(function($item) use($users) {
        //     $item->user = $users->where('id', $item->user_id)->first()->only(['id', 'first_name', 'last_name', 'username']);
        //     return $item;
        // });
        // dd($leaderUsers);

        // dd(Str::uuid());
        // $user = new \App\Models\User();
        // $user->password = \Illuminate\Support\Facades\Hash::make('sysSDFGtemuser345345');
        // $user->email = 'system@systemuser_api.com';
        // $user->first_name = 'systemuser_api';
        // $user->username = 'inner_systemuser_api';
        // $user->save();

        //dd($user);

        // $needArray = [
        //     1 => ['time' => true],
        //     2 => ['time' => true],
        //     3 => ['time' => true],
        // ];

        // $user = User::find(4);
        // $plucks = $user->feeds()->pluck('created_at', 'id')->transform(function ($item) {
        //     return ['time' => $item->getTimestamp()];
        // })->toArray();

        // dd($plucks);
        // DB::table('videos')->truncate();
        // DB::table('musics')->truncate();
        // DB::table('images')->truncate();
        // DB::table('user_feed_purchase')->truncate();
        // DB::table('users_feeds_like')->truncate();
        // DB::table('points')->truncate();
        // DB::table('notifications')->truncate();
        // DB::table('feed_tags')->truncate();
        // DB::table('feeds_comments')->truncate();
        // DB::table('complaints')->truncate();
        // DB::table('comments')->truncate();
        // DB::table('feeds')->truncate();

        //$feeds = Feed::all();
        //foreach ($feeds as $feed) {
            // $enity = $feed->feedable;
            // $uuid = (string) Str::uuid();
            // $feed->title = $enity->title;
            // $feed->body = $enity->body;
            // $feed->price = $enity->price;
            // $feed->is_paid = $enity->is_paid;
            // $feed->type = $feed->type;
            // $feed->slug = $uuid . '_' . $feed->type;
            // $feed->save();
            // $medias = $enity->getMedia('common');
            // $medias_paid = $enity->getMedia('paid');
            // $medias_preview = $enity->getMedia('preview');

            // foreach ($medias as $media) {
            //     if(file_exists($media->getPath())){
            //         $feed->addMedia($media->getPath())->toMediaCollection('common');
            //     }
            // }
            // foreach ($medias_paid as $media) {
            //     if(file_exists($media->getPath())){
            //         $feed->addMedia($media->getPath())->toMediaCollection('paid');
            //     }
            // }
            // foreach ($medias_preview as $media) {
            //     if(file_exists($media->getPath())){
            //         $feed->addMedia($media->getPath())->toMediaCollection('preview');
            //     }
            // }
        //}

    }


    public function update(User $user)
    {
        Request::validate([
            'first_name' => ['required', 'max:80'],
            'last_name' => ['required', 'max:80'],
            'username' => ['required', 'max:80', Rule::unique('users')->ignore($user->id)],
            'email' => ['required', 'max:50', 'email', Rule::unique('users')->ignore($user->id)],
            'password' => ['nullable'],
            'phone' => ['nullable'],
            'date_of_birth' => ['nullable'],
            'sex' => ['nullable'],
            'type' => ['nullable'],
            'private' => ['nullable'],
            'inn' => ['nullable'],
            'checking_account' => ['nullable'],
            'bik' => ['nullable'],
            // 'allow_adult_content' => ['nullable'],
            'about' => ['nullable', 'max:180'],
        ]);

        $user->update(Request::only('first_name', 'last_name', 'email', 'username', 'phone', 'date_of_birth', 'sex', 'about', 'private', 'inn', 'checking_account', 'bik', 'type'));

        if (Request::get('password')) {
            $user->update(['password' => Request::get('password')]);
        }

        return Redirect::back()->with('success', 'Профиль обновлен!');
    }

    public function destroy(User $user)
    {
        if (App::environment('demo') && $user->isDemoUser()) {
            return Redirect::back()->with('error', 'Deleting the demo user is not allowed.');
        }

        $user->delete();

        return Redirect::back()->with('success', 'User deleted.');
    }

    public function restore(User $user)
    {
        $user->restore();

        return Redirect::back()->with('success', 'User restored.');
    }

    public function subs(User $user)
    {

        if($user->private){
            return Redirect::back()->with('error', 'Закрытый аккаунт');
        }

        $check = \DB::table('users_subscribers')
            ->where('user_id', auth()->user()->id)
            ->where('subscriber_id', $user->id)
            ->first();

        auth()->user()->subscribers()->toggle([$user->id]);

        if(!$check){
            $message = [
                'user_id' => auth()->user()->id,
                'node_id' => null,
            ];
            $user->notify(new Subscribed($message));
            LiveFeed::addBySub($user);
        }else{
            LiveFeed::removeBySub($user);
        }

        return Redirect::back()->with('success', 'Success');
    }

    public function removePaidSubs(User $user)
    {
        auth()->user()->subscribers()->toggle([$user->id]);

        DB::table('users_package_customers')
            ->where('user_id', $user->id)
            ->where('customer_id', auth()->user()->id)
            ->delete();

        LiveFeed::removeBySub($user);

        return Redirect::back()->with('success', 'Успешно отписались от пользователя');
    }

    public function settingsAutoSubsPaidUser(User $user)
    {
        DB::table('users_subscribers')
                ->where('user_id', auth()->user()->id)
                ->where('subscriber_id', $user->id)
                ->update(['autosubscription' => DB::raw('NOT autosubscription')]);

        return Redirect::back()->with('success', 'Успешно выполнено');
    }

    public function settingsAutoSubs(User $user)
    {
        $auto = $user->autosubscription_site;

        if($auto){
            $msg = 'Автоматическое списание отключено!';
            $user->autosubscription_site = false;
        }else{
            $msg = 'Автоматическое списание включено!';
            $user->autosubscription_site = true;
        }

        $user->save();

        return Redirect::back()->with('success', $msg);
    }

    public function vote(User $user, HttpRequest $request)
    {

        $authUserActiveSubscription = nova_get_setting('vote_paid_mode') ? SubscriptionService::activeSubscription() : true;
        if(!$authUserActiveSubscription){
            return Redirect::back()->with('error', 'Только пользователи с подпиской могут выбрать лидера!');
        }

        $count_leader = nova_get_setting('vote_leader_count');
        if(!$request->vote && auth()->user()->subscribers()->where('leader', 1)->count() >= $count_leader){
            return Redirect::back()->with('error', "Можно выбрать {$count_leader} лидеров");
        }

        if(!$request->vote){
            $message = [
                'user_id' => auth()->user()->id,
                'node_id' => null,
            ];
            $user->notify(new LeaderChoice($message));
        }
        auth()->user()->subscribers()->updateExistingPivot($user->id, [
            'leader' => ! $request->vote,
        ]);
        return Redirect::back()->with('success', 'Success Vote!');
    }


    public function plan($plan_id)
    {
        $user = auth()->user();

        $active_subscription = SubscriptionService::activeSubscription();
        if ($active_subscription) {
            return Redirect::back()->with('error', 'Подписка уже активирована');
        }
        $balance = SubscriptionService::calculate($user->id);
        $plan = Package::findOrFail($plan_id);
        $plan_type = $plan->type;
        if ($plan_type === 'month3') {
            $ends_at = Carbon::now()->addMonths(3);
        } else {
            $ends_at = Carbon::now()->addMonths();
        }
        $price = $plan->price;
        if ($price > $balance) {
            return Redirect::back()->with('error', 'Недостаточно средств!');
        }

        $sub = new Subscription;
        $sub->user_id = $user->id;
        $sub->package_id = $plan->id;
        $sub->price = $price;
        $sub->ends_at = $ends_at;
        $sub->status = 'complete'; //YSV ENUM!
        $sub->save();

        $point = new Point;
        $point->user_id = $user->id;
        $point->point = $price;
        $point->type = 'Оплата за подписку';  //YSV ENUM!
        $point->direction = DirectionEnum::EXPENSE();
        $point->save();

        return Redirect::back()->with('success', 'Вы успешо подписались!');
    }

    public function testPaid()
    {
        // $price = 50;
        // $user = auth()->user();
        // $point = new Point;
        // $point->user_id = $user->id;
        // $point->point = $price;
        // $point->type = 'Пополнение баланса по кнопки';  //YSV ENUM!
        // $point->direction = DirectionEnum::COMING();
        // $point->save();
        // return Redirect::back()->with('success', 'Баланс успешно пополнен!');
    }


    public function postsCount($user_id)
    {
        $user = User::findOrFail($user_id);
        return $user->feeds()->count();
    }

    public function searchUserTag()
    {

        $search = Request::input('search');
        if(empty($search)){
            return [
                'users' => [],
                'tags' => [],
            ];
        }

        $sanitize_search = Str::slug($search);

        $users = User::where('username', '%'.$search.'%')
            ->where('username', '<>', 'inner_systemuser_api')
            ->orWhere('first_name', 'ilike', '%'.$search.'%')
            ->orWhere('last_name', 'ilike', '%'.$search.'%')->get();
        $users->each(function ($item) {
            $item->name = $item->name;
            return $item;
        });
        $sanitize_search = '%'.$sanitize_search.'%';
        $tags = Tag::where('slug', 'ilike', $sanitize_search)->withCount('feeds')->get();

        return [
            'users' => $users,
            'tags' => $tags,
        ];
    }

    public function friend() {
        $user = auth()->user();
        $readers = $user->subscribers()->filter(Request::only('search'))
        ->orderBy('id', 'desc')
        ->cursorPaginate(50);


        $users = [];
        $nextCursor = get_cursor_hash($readers);
        $readers->each(function ($item) use(&$users) {
            $users[] = UserData::fromModel($item)->toArray();
        });
        return ['records' => $users, 'cursor' => $nextCursor];

    }

    public function updatePassword(HttpRequest $request)
    {
        # Validation
        $request->validate([
            'old_password' => 'required',
            'new_password' => 'required|string|min:6',
        ]);

        #Match The Old Password
        if(!Hash::check($request->old_password, auth()->user()->password)){
            return back()->with("error", "Old Password Doesn't match!");
        }

        #Update the new Password
        User::whereId(auth()->user()->id)->update([
            'password' => Hash::make($request->new_password)
        ]);

        return back()->with("success", "Password changed successfully!");

    }


    public function addDocument(HttpRequest $request)
    {
        $this->validate($request, [
            'docs' => 'required|file|image',
        ]);

        $documents = $request->user()->getMedia('documents');

        if($documents->count()){
            foreach ($documents as $document) {
                $document->delete();
            }
        }
        $file = $request->file('docs');

        auth()->user()->addMedia($file)->toMediaCollection('documents', 'local');

        return back()->with("success", "Документ успешно загружен");

    }


    public function readDocument(string $uuid)
    {
        $media = Media::where('uuid', $uuid)->first();
        return response()->download($media->getPath(), $media->file_name);
    }

    public function verifyPhoneRequest(Carbon $now)
    {
        $user = auth()->user();
        if(empty($user->phone)){
            return back()->with("error", "Нужно ввести телефон");
        }
        if (!empty($user->phone_verify_token) && $user->phone_verify_token_expire && $user->phone_verify_token_expire->gt($now)) {
            return back()->with("error", "Токен уже запрошен.");
        }

        $user->phone_verified = false;
        $user->phone_verify_token = (string)random_int(10000, 99999);
        $user->phone_verify_token_expire = $now->copy()->addSeconds(300);
        $user->saveOrFail();

        return back()->with("success", "Верификация номера телефона успешно запрошена, ожидайте");
    }

    public function verifyPhone(HttpRequest $request, Carbon $now)
    {
        $user = auth()->user();
        $token = $request->input('token');
        if ($token !== $user->phone_verify_token) {
            return back()->with("error", "Токен уже запрошен.");
        }
        if ($user->phone_verify_token_expire->lt($now)) {
            return back()->with("error", "Срок действия токена истек.");
        }
        $user->phone_verified = true;
        $user->phone_verify_token = null;
        $user->phone_verify_token_expire = null;
        $user->saveOrFail();

        return back()->with("success", "Верификация номера телефона успешно завершена");
    }


}
