<?php

namespace App\Services\Admin;

use App\Models\AddCard;
use App\Models\Administration;
use App\Models\User;
use App\Services\Admin\Contracts\AdminServiceInterface;
use Carbon\Carbon;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;

class AdminService implements AdminServiceInterface
{
    public function getUserListWithStats(string $selectedMonth, ?string $search = null, ?string $flagSend = null): array
    {
        $startOfMonth = Carbon::parse($selectedMonth)->startOfMonth();
        $endOfMonth   = Carbon::parse($selectedMonth)->endOfMonth();

        $usersQuery = User::select('user.*')
            ->where('status', User::STATUS_ACTIVE)
            ->addSelect([
                'total_received' => Administration::selectRaw('COALESCE(SUM(received), 0)')
                    ->whereColumn('msnv', 'user.msnv')
                    ->whereBetween('date', [$startOfMonth, $endOfMonth]),
                'total_sent' => Administration::selectRaw('COALESCE(SUM(sent), 0)')
                    ->whereColumn('msnv', 'user.msnv')
                    ->whereBetween('date', [$startOfMonth, $endOfMonth])
            ]);

        $topReceivedUser = (clone $usersQuery)->orderByDesc('total_received')->first();
        $topSentUser     = (clone $usersQuery)->orderByDesc('total_sent')->first();

        if (!is_null($search) && trim($search) !== '') {
            $search = trim($search);
            $usersQuery->where(function ($q) use ($search) {
                $q->whereRaw('LOWER(msnv) LIKE ?', ['%' . strtolower($search) . '%'])
                  ->orWhereRaw('LOWER(mail) LIKE ?', ['%' . strtolower($search) . '%']);
            });
        }

        if (!is_null($flagSend) && $flagSend !== '') {
            $usersQuery->where('flag_send', intval($flagSend));
        }

        $users = $usersQuery->paginate(10)->withQueryString();

        return compact('users', 'topReceivedUser', 'topSentUser');
    }

    public function getUserTransactions(string $msnv, string $selectedMonth): LengthAwarePaginator
    {
        $startOfMonth = Carbon::parse($selectedMonth)->startOfMonth();
        $endOfMonth   = Carbon::parse($selectedMonth)->endOfMonth();

        return Administration::where('msnv', $msnv)
            ->whereBetween('date', [$startOfMonth, $endOfMonth])
            ->orderBy('date', 'desc')
            ->paginate(10)
            ->withQueryString();
    }

    public function createUser(array $data): void
    {
        User::create([
            'msnv'        => $data['msnv'],
            'name'        => $data['name'],
            'mail'        => $data['mail'],
            'pass'        => md5($data['password']),
            'departments' => $data['departments'],
            'role'        => $data['role'],
            'status'      => User::STATUS_ACTIVE,
            'card'        => 0,
            'flag_send'   => User::FLAG_SEND_DISABLED,
            'first_login' => User::FIRST_LOGIN_TRUE,
        ]);
    }

    public function updateUser(string $msnv, array $data): void
    {
        $user = User::where('msnv', $msnv)->firstOrFail();

        DB::transaction(function () use ($data, $user) {
            if (!empty($data['num_card'])) {
                AddCard::create([
                    'buyer'    => $user->msnv,
                    'num_card' => $data['num_card'],
                    'seller'   => Auth::user()->msnv,
                    'date'     => Carbon::today(),
                ]);
                $user->card += $data['num_card'];
            }

            $user->flag_send = isset($data['flag_send']) ? User::FLAG_SEND_ENABLED : User::FLAG_SEND_DISABLED;
            $user->save();
        });
    }

    public function deactivateUser(string $msnv): void
    {
        $user = User::where('msnv', $msnv)->firstOrFail();
        $user->status = User::STATUS_INACTIVE;
        $user->save();
    }

    public function resetAllCards(): void
    {
        User::where('status', User::STATUS_ACTIVE)->update(['card' => 0]);
    }
}