<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Minishlink\WebPush\WebPush;
use Minishlink\WebPush\Subscription;
use Twilio\Rest\Client;

use App\Models\Funding;
use App\Models\Trading;
use App\Models\Investment;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
        'address',
        'phone',
        'state',
        'profile',
        'country',
        'currency',
        'referral_code',
        'pass_copy',
        'verification_status'
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    public function fundings(){
        return $this->hasMany(Funding::class);
    }

    public function tradings(){
        return $this->hasMany(Trading::class);
    }

    
    public function copiers(){
        return $this->hasMany(Copier::class);
    }

    /**
     * Get all of the wallets for the User
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function wallets()
    {
        return $this->hasMany(Wallet::class);
    }

    public function balance(){
        $balance = 0;

        $funds = $this->fundings->where('status', 'successful')->sum('amount');
        $balance += $funds;

        $funds_single = $this->fundings->where('status', 'approved')->sum('amount');
        $balance += $funds_single;

        $tradings_expense = $this->tradings->where('status', '!=', 'declined')->sum('amount');
        $trading_profit = $this->tradings->where('status', '!=', 'declined')->sum('profit');
        $trading_capital = $this->tradings->where('status', 'closed')->sum('amount');


        $balance -= $tradings_expense;
        $balance += $trading_profit;
        $balance += $trading_capital;

        $copiers = $this->copiers->where('status', '!=', 'declined')->sum('amount');
        $copiers_profit = $this->copiers->where('status', '!=', 'declined')->sum('profit');
        $copier_capital = $this->copiers->where('status', 'completed')->sum('amount');


        $balance -= $copiers;
        $balance += $copiers_profit;
        $balance += $copier_capital;

        $investments = $this->investments->where('status', '!=', 'declined')->sum('amount_invested');
        $investments_profits = $this->investments->where('status', '!=', 'declined')->sum('earning');
        $investment_capital = $this->investments->where('status', 'completed')->sum('amount_invested');


        $balance -= $investments;
        $balance += $investments_profits;
        $balance += $investment_capital;

        $withdrawals = $this->withdrawals->where('status', '!=', 'declined')->sum('amount');
        $balance -= $withdrawals;

        // Add joint account transfers (money transferred from joint accounts to personal account)
        $jointAccountTransfers = $this->jointAccountTransfers()->sum('amount');
        $balance += $jointAccountTransfers;

        $balance += $this->referralEarning();
        

        return $balance;


    }

    public function subscriptionBalance(){
        // $balance = 0;
      
        // $funds = $this->fundings->where('gateway', 'Invested Capital')->sum('amount');
        // $balance += $funds;

        // $copiers = $this->copiers->where('status', '!=', 'declined')->sum('amount');
        // $balance += $copiers;       

        // $investments = $this->investments->where('status', '!=', 'declined')->sum('amount_invested');
        // $balance += $investments;

        // $tradings = $this->tradings->sum('amount');
        // $balance += $tradings;      
        
        // return $balance;


        $balance = 0;
      
        $funds = $this->fundings->where('gateway', 'Invested Capital')->sum('amount');
        $balance += $funds;

        $copiers = $this->copiers->where('status', '!=', 'declined')->where('status', '!=', 'pending')->sum('amount');
        $balance += $copiers;       

        $investments = $this->investments->where('status', '!=', 'declined')->where('status', '!=', 'pending')->sum('amount_invested');
        $balance += $investments;

        $tradings = $this->tradings->where('status', 'open')->sum('amount');
        $balance += $tradings;       
        
        $withdrawals = $this->withdrawals->where('status', '!=', 'declined')->where('source', 'Invested Capital')->sum('amount');
        $balance -= $withdrawals;
        
        return $balance;
    }

    public function withdrawableBalance(){
        // $balance = 0;

        // $funds = $this->fundings->where('gateway', 'Accumulated Profit')->sum('amount');
        // $balance += $funds;
        
        // $copiers = $this->copiers->where('status','!=', 'declined')->sum('profit');
        // $balance += $copiers;

        // $investments = $this->investments->where('status','!=', 'declined')->sum('earning');
        // $balance += $investments;     

        // $tradings = $this->tradings->sum('profit');
        // $balance += $tradings;

        // $withdrawals = $this->withdrawals->where('status', '!=', 'declined')->where('source', 'Accumulated Profit')->sum('amount');

        // $balance -= $withdrawals;
        // return $balance;


        $balance = 0;

        $funds = $this->fundings->where('gateway', 'Accumulated Profit')->sum('amount');
        $balance += $funds;
        
        $copiers = $this->copiers->where('status','!=', 'declined')->sum('profit');
        $balance += $copiers;


        $investments = $this->investments->where('status','!=', 'declined')->sum('earning');
        $balance += $investments;
     

        $tradings = $this->tradings->sum('profit');
        $balance += $tradings;


        $withdrawals = $this->withdrawals->where('status', '!=', 'declined')->where('source', 'Accumulated Profit')->sum('amount');
        $balance -= $withdrawals;


        return $balance;
    }

    /**
     * Get all of the subscriptions for the User
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function subscriptions()
    {
        return $this->hasMany('App\Models\Subscription');
    }

     /**
     * Get all of the plates for the User
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function plates()
    {
        return $this->hasMany(Plate::class);
    }


       /**
     * get the push subscription of a user
     * @return eloquent relaitionship
     */
    public function pushSubscription(){
        return $this->hasOne(PushSubscription::class);
    }

    /**
     * check if user has subscription
     * @return boolean
     */
    public function hasSubscription(){
        return $this->pushSubscription;
    }

    /**
     * Get all of the referrals for the User
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function referrals()
    {
        return $this->hasMany(Referral::class, 'inviter_id');
    }

    /**
     * Get all of the roles for the User
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function roles()
    {
        return $this->hasMany(Role::class);
    }

    public function isAdmin(): bool
    {
        return $this->roles()->where('role', 'admin')->exists();
    }

    public function referralEarning(){
        $bal = 0;
        $earnings = $this->referrals->where('status', 'approved')->sum('earning');
        $bal += $earnings;
        $withdrawals = $this->withdrawals->where('status', '!=', 'declined')->where('source', 'Referral')->sum('amount');
        $bal -= $withdrawals;

        $funds = $this->fundings->where('gateway', 'Referral Wallet')->sum('amount');
        $bal += $funds;

        $debits = $this->investments->where('status', '!=', 'declined')->where('payment_source', 'Referral Wallet');
        foreach ($debits as $debit) {
            $amount = $debit->amount_invested;
            $bal -= $amount;
        }

        return $bal;
    }

    /**
     * Get the upliner associated with the User
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function upliner()
    {
        return $this->hasOne(Referral::class, 'invited_id');
    }


    /**
     * send push messages to a user
     * @param push-message tittle, push-message text, push-message image and push-message link
     */
    public function pushMessage($title, $message, $image, $action){

        if ($this->hasSubscription()) {            
                $auth = [
                    'VAPID' => [
                        'subject' =>'mailto:support@menubarkitchen.com', // can be a mailto: or your website address
                        'publicKey'=>'BE2u3JzkXpiOYIIvv6esljeFPAsJoQol8snFELlx9SQo-2TqsUHvp0Db13WwhMiOttnT4_HBrRPm91htQICSLc8', // (recommended) uncompressed public key P-256 encoded in Base64-URL
                        'privateKey'=>'FYQSXH6e61yqEOHZe-eLgXSHn84-yiy0CKmZAz9OV_w', // (recommended) in fact the secret multiplier of the private key encoded in Base64-URL
                        ],
                ];

                $webPush = new webPush($auth);
                $endpoint = $this->pushSubscription->endpoint;
                $public_key = $this->pushSubscription->public_key;
                $auth_key = $this->pushSubscription->auth_key;

                $notification = [
                    'subscription' => Subscription::create([
                        'endpoint' => $endpoint,
                        'publicKey' => $public_key,
                        'authToken' => $auth_key
                    ]),
                    'payload' => '{"title": "'.$title.'", "message":"'.$message.'", "image":"'.$image.'", "action":"'.$action.'"}',
                    ];

                $webPush->queueNotification(
                    $notification['subscription'],
                    $notification['payload']
                );                

                foreach ($webPush->flush() as $report) {
                    $endpoint = $report->getRequest()->getUri()->__toString();
                }               
        }
    }

    public function sendSms($phone, $message){
        
            $sid    = "ACe19468bc0e10f2e23025a0981f5a0a7e";
            $token  = "242c07127f1fe0d487865f363a6c1f50";
            $twilio = new Client($sid, $token);

            $message = $twilio->messages
            ->create($phone, // to
                array(
                        "messagingServiceSid" => "MG8a06f5e626f39b6943e0c0ebeba0db18",
                "body" => $message
                )
            );

        print($message->sid);
    }
 


    /**
     * Get all of the depaytransactions for the User
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function depaytransactions()
    {
        return $this->hasMany(DepayTransaction::class);
    }

    public function jointAccountTransfers()
    {
        return $this->hasMany(JointAccountTransaction::class, 'initiated_by')
            ->where('transaction_type', 'transfer')
            ->where('status', 'completed');
    }

    /**
     * Get all of the withdrawals for the User
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function withdrawals()
    {
        return $this->hasMany(Withdrawal::class);
    }

    /**
     * Get all of the investments for the User
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function investments()
    {
        return $this->hasMany(Investment::class);
    }

    /**
     * Get all of the investments for the User
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function connections()
    {
        return $this->hasMany(Connection::class);
    }

    /**
     * Get all of the depaystransaction for the User
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function depaystransaction()
    {
        return $this->hasMany(DepayTransaction::class);
    }

    public function getCoinBalance($coin) {
        $bal = 0;
        $balance = Funding::where('gateway', $coin)->where('user_id', (int)$this->id)->where('status', 'successful')->sum("amount");
        $bal += $balance;
        $trading = Trading::where('pair', $coin)->where('user_id', (int)$this->id)->sum("profit");
        $bal += $trading;

        $investments = Investment::where('payment_source', $coin)->where('status', '!=', 'declined')->where('user_id', (int)$this->id)->sum("amount_invested");
        $bal -= $investments;

        $withdrawals = $this->withdrawals->where('status', '!=', 'declined')->where('source', $coin)->sum('amount');
        $bal -= $withdrawals;

        return $bal;
    }
    
}
