<?php

namespace App\Services;

use App\Constants\BalanceUpdateType;
use App\Constants\MethodType;
use App\Constants\OrderStatus;
use App\Constants\TicketStatus;
use App\Constants\TxnStatus;
use App\Constants\TxnType;
use App\Constants\UserStatus;
use App\Facades\BalanceFacade as UserBalance;
use App\Facades\TransactionFacade as Transaction;
use App\Models\Order;
use App\Models\Ticket;
use App\Models\Transaction as TransactionModel;
use App\Models\User;
use App\Notifications\User\BalanceUpdatedNotify;
use App\Notifications\User\CustomMessageNotify;
use Carbon\Carbon;
use Illuminate\Support\Facades\Notification;

class UserService
{
    public function updateUserStatus(User $user, $status, $emailVerified, $twoFactor = false): User
    {
        if ($twoFactor && !$user->google2fa_secret) {
            $google2fa = app('pragmarx.google2fa');
            $user->google2fa_secret = $google2fa->generateSecretKey();
            $user->google2fa_enabled = true;
        } elseif (!$twoFactor) {
            $user->google2fa_enabled = false;
            $user->google2fa_secret = null;
        }

        $user->status = $status ? UserStatus::ACTIVE : UserStatus::BANNED;
        $user->email_verified_at = $emailVerified ? Carbon::now() : null;
        $user->save();

        return $user;
    }

    public function updateUserInfo(User $user, array $data)
    {
        $user->fill($data);
        $user->save();
    }

    public function updateUserPassword(User $user, $password)
    {
        $user->password = bcrypt($password);
        $user->save();
    }

    public function updateBalance(User $user, $type, $amount)
    {
        $isUpdated = UserBalance::update($user, $type, $amount);

        if ($isUpdated) {
            $transactionType = $type === BalanceUpdateType::ADD ? TxnType::ADD_BALANCE : TxnType::SUBTRACT_BALANCE;

            $transactionData = [
                'type' => $transactionType,
                'method_type' => MethodType::SYSTEM,
                'amount' => $amount,
                'user_id' => $user->id,
                'status' => TxnStatus::COMPLETED,
                'description' => __(':action balance by :admin', [
                    'action' => $type === BalanceUpdateType::ADD ? 'Added' : 'Subtracted',
                    'admin' => auth()->user()->name,
                ]),
            ];

            Transaction::createTransaction($transactionData);

            return true;
        }

        return false;
    }

    public function sendCustomNotification($message, $channels = ['mail'], $userId = null): void
    {

        if ($userId) {
            $user = $this->getUserById($userId);
            $user->notify(new CustomMessageNotify($message, $channels));
        } else {
            $users = User::where('status', UserStatus::ACTIVE)->get();
            Notification::send($users, new CustomMessageNotify($message, $channels));
        }
    }

    /**
     * Retrieve a user by ID or fail.
     *
     * @param int $id
     * @return User
     */
    public function getUserById($id)
    {
        return User::findOrFail($id);
    }

    public function notifyBalanceUpdate(User $user, $amount, $type)
    {
        $user->notify(new BalanceUpdatedNotify($amount, $type));
    }

    public function getCardStatistics(User $user)
    {
        $currencySymbol = setting('currency_symbol');

        return [
            [
                'title' => 'Total Deposits',
                'value' => $currencySymbol . \Txn::getTotalAmount(TxnType::DEPOSIT, TxnStatus::COMPLETED, $user->id),
                'icon' => 'wallet-2',
                'color' => 'danger',
            ],
            [
                'title' => 'Service Completed',
                'value' => Order::where('user_id', $user->id)->where('status', OrderStatus::COMPLETED)->count(),
                'icon' => 'service',
                'color' => 'success',
            ],
            [
                'title' => 'Running Service',
                'value' => Order::where('user_id', $user->id)
                    ->where('status', OrderStatus::WORKING)
                    ->count(),
                'icon' => 'order',
                'color' => 'indigo',
            ],
            [
                'title' => 'Pending Service',
                'value' => Order::where('user_id', $user->id)
                    ->where('status', OrderStatus::PENDING)
                    ->count(),
                'icon' => 'service-1',
                'color' => 'info',
            ],
            [
                'title' => 'Total Transaction',
                'value' => TransactionModel::where('user_id', $user->id)->count(),
                'icon' => 'transaction-2',
                'color' => 'warning',
            ],
            [
                'title' => 'Completed Transaction',
                'value' => TransactionModel::where('user_id', $user->id)->where('status', TxnStatus::COMPLETED)->count(),
                'icon' => 'transaction-3',
                'color' => 'success',
            ],
            [
                'title' => 'Total Support Ticket',
                'value' => Ticket::where('user_id', $user->id)->count(),
                'icon' => 'ticket-3',
                'color' => 'purple',
            ],
            [
                'title' => 'Pending Support Ticket',
                'value' => Ticket::where('user_id', $user->id)
                    ->where('status', TicketStatus::PENDING)
                    ->count(),
                'icon' => 'ticket-4',
                'color' => 'info',
            ],
            [
                'title' => 'Solved Support Ticket',
                'value' => Ticket::where('user_id', $user->id)->where('status', TicketStatus::COMPLETED)->count(),
                'icon' => 'ticket-check',
                'color' => 'success',
            ],
        ];
    }

    public function getTransactionStatistics($userId = null, array $filters = [])
    {
        // Set default date range if not provided
        $startDate = Carbon::parse(data_get($filters, 'start_date', now()->subWeek()))->startOfDay();
        $endDate = Carbon::parse(data_get($filters, 'end_date', now()))->endOfDay();

        // Format date range for display (Y-m-d format)
        $dateRange = $startDate->format('m/d/Y') . ' - ' . $endDate->format('m/d/Y');

        // Prepare the query for transactions
        $query = TransactionModel::whereBetween('created_at', [$startDate, $endDate])
            ->selectRaw('DATE(created_at) as date, status, COUNT(*) as total')
            ->groupBy('date', 'status');

        // Apply user filter if userId is provided
        if ($userId) {
            $query->where('user_id', $userId);
        }

        // Get statistics
        $transactionsStatistics = $query->get()
            ->groupBy('date')
            ->map(function ($items) {
                $statusTotals = $items->pluck('total', 'status');
                $statuses = TxnStatus::STATUS;

                // Fill missing statuses with zero
                return collect($statuses)->mapWithKeys(function ($status) use ($statusTotals) {
                    return [$status => $statusTotals->get($status, 0)];
                });
            })->toArray();

        // Initialize all dates within the range with zero values
        $selectedDateData = collect();
        for ($date = $startDate->copy(); $date->lte($endDate); $date->addDay()) {
            $selectedDateData->put($date->format('M d'), [ // Format the date key as "M d"
                TxnStatus::COMPLETED => 0,
                TxnStatus::PENDING => 0,
                TxnStatus::FAILED => 0,
            ]);
        }

        // Convert the keys of $transactionsStatistics to "M d" format
        $transactionsStatisticsFormatted = collect($transactionsStatistics)->mapWithKeys(function ($value, $key) {
            // Convert key from "Y-m-d" to "M d"
            $formattedKey = Carbon::parse($key)->format('M d');
            return [$formattedKey => $value];
        });

        // Merge actual statistics with default date data
        $mergedStatistics = $selectedDateData->merge($transactionsStatisticsFormatted);

        return [
            'transactionsStatistics' => $mergedStatistics,
            'dateRange' => $dateRange, // Keep this as Y-m-d format
        ];
    }


}
