<?php

namespace App\Service\User;

use App\Enum\BankProvider;
use App\Enums\OtpReason;
use App\Helpers\MessageContent;
use App\Models\Bank;
use App\Models\SystemSetting;
use App\Models\User;
use App\Models\UserBank;
use App\Models\UserKyc;
use App\Service\MailService;
use App\Service\ThirdParty\Interfaces\BVNVerificationInterface;
use App\Service\ThirdParty\Interfaces\NINVerificationInterface;
use App\Service\ThirdParty\Interfaces\VerifyBankInterface;
use App\Traits\JsonResponseTrait;
use Carbon\Carbon;
use Date;
use DB;
use Illuminate\Support\Facades\Hash;
use Log;

class UserService
{
    use JsonResponseTrait;

    public function __construct(
        protected BVNVerificationInterface $bvnVerification,
        protected NINVerificationInterface $ninVerification,
        protected MailService $mailService,
        // protected VerifyBankInterface $verifybankAccount
    ) {}

    /**
     * Add user to newsletter
     *
     * @param  string  $email
     * @return bool
     */


    /**
     * Get the authenticated user's profile details.
     *
     * @return array
     */
    public function getProfileDetails($authUser)
    {
        // Get the authenticated user
        // $user = $authUser;
        $user = auth('user')->user();

        return $this->successDataResponse(data: $user, message: "Profile fetched successful");

        // Return user details (you can customize the fields as needed)
        // return [
        //     'id' => $user->user_id,
        //     'firstname' => $user->firstname,
        //     'lastname' => $user->lastname,
        //     'email' => $user->email,
        //     'profile_pic' => $user->profile_pic,
        //     'wallet_balance' => $user->wallet_balance,
        //     'cashback_balance' => $user->cashback_balance,
        //     'referral_balance' => $user->referral_balance,
        //     'phone_verified' => $user->phone_verified,
        //     'email_verified' => $user->email_verified,
        // ];
    }

    /**
     * Change the authenticated user's password.
     *
     * @param  string  $currentPassword
     * @param  string  $newPassword
     * @return bool
     */
    public function changePassword(User $authUser, string $currentPassword, string $newPassword)
    {
        // Get the authenticated user
        // $user = auth('user')->user();
        $user = $authUser;

        // Verify the current password
        if (!Hash::check($currentPassword, $user->password)) {
            return $this->errorResponse(statusCode: 401, message: 'Invalid current password');
        }

        // Update the password
        $user->password = Hash::make($newPassword);
        $user->save();
        return $this->successDataResponse(data: $user, message: "Password changed successfully");
    }

    /**
     * Update the authenticated user's profile (excluding the password).
     *
     * @param  array  $data
     * @return bool
     */
    public function updateProfile(User $authUser, array $data)
    {
        // Check if 'username' exists in the input data
        if (isset($data['username'])) {
            // Find a user with the same username, but not the current user
            $existingUser = User::where('username', $data['username'])
                ->where('id', '!=', $authUser->id)
                ->first();

            // If another user with the same username exists, return an error
            if ($existingUser) {
                return $this->errorResponse(
                    statusCode: 400,
                    message: 'The username is already taken by another user.'
                );
            }
        }

        // Filter out null and empty values from the data
        $updateData = array_filter($data, function ($value) {
            return $value !== null && $value !== '';
        });

        // Only update if there's data to update
        if (!empty($updateData)) {
            $user = $authUser->update($updateData);
        } else {
            $user = $authUser; // No data to update, return the user as-is
        }

        return $this->successDataResponse(data: $user, message: "Profile updated successfully");
    }

    /**
     * Set a new PIN for the authenticated user.
     *
     * @param  string  $pin
     * @return bool
     */
    public function setPin(User $authUser, string $pin)
    {
        // Get the authenticated user
        $user = $authUser;

        // Update the user's pin
        $user->user_pin = Hash::make($pin); // Hash the pin for security
        $user->save();
        return $this->successDataResponse(data: $user, message: "Pin set successfully");
    }

    /**
     * Change PIN for the authenticated user.
     *
     * @param  string  $oldPin
     * @param  string  $newPin
     * @return bool
     */
    public function changePin(User $authUser, string $oldPin, $newPin)
    {
        // Get the authenticated user
        $user = $authUser;

        // Verify the current pin
        if (!Hash::check($oldPin, $user->user_pin)) {
            return $this->errorResponse(statusCode: 401, message: 'Invalid current pin');
        }

        // Update the user's pin
        $user->user_pin = Hash::make($newPin); // Hash the pin for security
        $user->save();
        return $this->successDataResponse(data: $user, message: "Pin changed successfully");
    }

    // /**
    //  * Verify authenticated user BVN.
    //  *
    //  * @param  string  $bvn
    //  * @return bool
    //  */
    // public function verifyBVN(User $authUser, string $bvn)
    // {
    //     // Get the authenticated user
    //     $user = $authUser;

    //     if ($user->bvn_verified) {
    //         return $this->errorResponse(statusCode: 40, message: 'Bvn already verified');
    //     }

    //     //get previously saved in userKyc table

    //     // Verify the BVN using the provided verification service
    //     $response = $this->bvnVerification->verifyBVN($bvn);

    //     // Check if the response contains an error
    //     if (isset($response->error)) {
    //         return $this->errorResponse(message: $response->error, statusCode: 500);
    //     }

    //     $bvnData = $response->entity;

    //     DB::beginTransaction();

    //     try {
    //         // Save or update the BVN details in the `user_kyc` table
    //         UserKyc::updateOrCreate(
    //             ['user_id' => $authUser->user_id], // Match on `user_id` to update existing records
    //             [
    //                 'firstname' => $bvnData['first_name'],
    //                 'lastname' => $bvnData['last_name'],
    //                 'middlename' => $bvnData['middle_name'],
    //                 'dob' => Carbon::parse($bvnData['date_of_birth'])->format('Y-m-d'),
    //                 'gender' => $bvnData['gender'],
    //                 'verification_provider' => 'doja', // Example: You can use the actual service name
    //                 'verification_response' => json_encode($response), // Save the full response for reference
    //                 'status' => 0, // Set status as 'pending'
    //                 'type' => 'bvn', // Indicate the type of verification
    //                 'phoneno' => $bvnData['phone_number1'],
    //                 'identity_number' => $bvnData['bvn']
    //             ]
    //         );

    //         $otp = random_int(100000, 999999);
    //         // Update the user's BVN verification status
    //         $authUser->update([
    //             'otp' => $otp,
    //             'otp_reason' => 'bvn_verification',
    //             'otp_expires_at' => now()->addMinutes(10)
    //         ]);

    //         DB::commit();

    //         // Send welcome email
    //         $welcomeSubject = 'BVN Verification - ABS Vendor!';
    //         $welcomeMessageContent = MessageContent::verifyBvnOtp($user->firstname, $otp);
    //         $this->mailService->sendEmail($user->email, $welcomeSubject, $welcomeMessageContent);

    //         return $this->successResponse(message: 'BVN verification OTP has been sent to your phone');
    //     } catch (\Exception $e) {
    //         DB::rollBack();

    //         // Log the exception for debugging
    //         Log::error('BVN verification failed: ' . $e->getMessage(), [
    //             'user_id' => $authUser->user_id,
    //             'bvn' => $bvn,
    //             'exception' => $e,
    //         ]);

    //         return $this->errorResponse(statusCode: 500, message: 'Failed to verify BVN. Please try again.');
    //     }
    // }

    // /**
    //  * BVN OTP verification
    //  */
    // public function verifyBvnOtp(User $authUser, int $token)
    // {
    //     $user = $authUser;
    //     if ($user->bvn_verified) {
    //         return $this->errorResponse(statusCode: 400, message: 'Bvn already verified');
    //     }

    //     // Check if OTP matches
    //     if ($user->otp !== $token) {
    //         return $this->errorResponse(statusCode: 401, message: 'Invalid OTP code');
    //     }

    //     // Check if OTP has expired
    //     if (Carbon::parse($user->otp_expires_at)->isPast()) {
    //         return $this->errorResponse(statusCode: 410, message: 'OTP code has expired, kindly generate another OTP Code');
    //     }

    //     DB::beginTransaction();

    //     try {
    //         // Update user's BVN verification status
    //         $user->update([
    //             'bvn_verified' => true,
    //             'otp' => null,
    //             'otp_expires_at' => null,
    //             'otp_reason' => null,
    //         ]);

    //         // Update the user_kyc table status
    //         UserKyc::where('user_id', $user->user_id)->update([
    //             'status' => 1, // Mark as verified
    //         ]);

    //         DB::commit();

    //         return $this->successResponse(message: 'BVN OTP verification successful');
    //     } catch (\Exception $e) {
    //         DB::rollBack();

    //         // Log the exception for debugging
    //         Log::error('BVN OTP verification failed: ' . $e->getMessage(), [
    //             'user_id' => $user->user_id,
    //             'otp' => $token,
    //             'exception' => $e,
    //         ]);

    //         return $this->errorResponse(statusCode: 500, message: 'Failed to verify BVN OTP. Please try again.');
    //     }
    // }

    public function resendOtp(User $authUser, string $reason)
    {
        $user = $authUser;

        //validate reason IN ENUM OtpReason
        $otpReason = OtpReason::tryFrom($reason);

        if ($otpReason === null) {
            return $this->errorResponse(statusCode: 400, message: 'Invalid OTP reason');
        }

        $otp = random_int(100000, 999999);
        // Update the user's OTP details
        $user->update([
            'otp' => $otp,
            'otp_reason' => $reason,
            'otp_expires_at' => now()->addMinutes(10)
        ]);

        // check reason and Send the OTP to the user's email
        if ($otpReason === OtpReason::BVN_VERIFICATION) {
            // Send welcome email
            $welcomeSubject = 'BVN Verification - ABS Vendor!';
            $welcomeMessageContent = MessageContent::verifyBvnOtp($user->firstname, $otp);
            $this->mailService->sendEmail($user->email, $welcomeSubject, $welcomeMessageContent);
        }

        // $this->smsService->sendOtp($user->phone, $otp);

        return $this->successResponse(message: 'OTP has been resent to your phone');
    }


    /**
     * Verify authenticated user BVN.
     *
     * @param  string  $accountno
     * @param  string  $bankId
     * @return bool
     */
    public function addBank(User $authUser, string $accountNumber, $bankId)
    {
        // Get the authenticated user
        $user = $authUser;

        $bank = Bank::whereBankId($bankId)->first();
        if (!$bank) {
            return $this->errorResponse(statusCode: 400, message: "Invalid bank passed");
        }
        //get default_payment_api from env
        //if monify, $bankCode = $bank[monnify_code]
        //get the bank code monnify_code, kora_code, safeHeaven_code, 

        // Get the payment provider from the .env or configuration
        //get the active bank provider from db
        $systemSettings = SystemSetting::whereId(1)->first();
        $activePaymentProvider = $systemSettings->activepaysystem; // Default to 'monnify' if not set
        $paymentProvider = BankProvider::getName($activePaymentProvider);
        // $paymentProvider = config('thirdparty.default_payment_provider', 'monnify'); // Default to 'monnify' if not set

        // Retrieve the corresponding bank code based on the selected payment provider
        $bankCode = match ($paymentProvider) {
            BankProvider::MONNIFY => $bank->monnify_code,
            BankProvider::KORA => $bank->kora_code,
            BankProvider::SH => $bank->safeheaven_code,
            BankProvider::BONI => $bank->bani_code,
            default => $bank->monnify_code, // Default to Monnify if the provider is not found
        };

        // Verify the account using the appropriate bank code
        // $verificationResponse = $this->verifybankAccount->verifyBankAccount($accountNumber, $bankCode);

        // if (!$verificationResponse->status) {
        //     return $this->errorResponse(statusCode: 400, message: $verificationResponse->message);
        // }

        DB::beginTransaction();

        try {
            // UserBank::create(
            //     [
            //         'user_id' => $authUser->user_id,
            //         'account_number' => $verificationResponse->accountNumber,
            //         'account_name' => $verificationResponse->accountName,
            //         'bank_id' => $bankId,
            //     ]
            // );

            $authUser->update([
                'bank_added' => true,
            ]);

            DB::commit();


            return $this->successResponse(message: 'Bank added successful');
        } catch (\Exception $e) {
            DB::rollBack();

            // Log the exception for debugging
            Log::error('Bank account verification failed: ' . $e->getMessage(), [
                'user_id' => $authUser->user_id,
                'account_number' => $accountNumber,
                'exception' => $e,
            ]);

            return $this->errorResponse(statusCode: 500, message: 'Failed to verify Bank account. Please try again.');
        }
    }
}
