<?php

namespace App\CentralLogics;

use App\Models\RegistrationBonusHistory;
use App\Models\BonusClaimLog;
use App\Models\User;

class RegistrationBonusLogic
{
    public static function defaultResponse(): array
    {
        return [
            'registration_bonus_granted' => 0,
            'registration_bonus_amount' => 0,
            'registration_bonus_popup_message' => null,
        ];
    }

    public static function process(User $user, ?string $deviceIdentifier = null): array
    {
        $settings = self::getSettings();
        $response = self::defaultResponse();
        $response['registration_bonus_popup_message'] = $settings['popup_message'];

        $history = RegistrationBonusHistory::firstOrNew(['user_id' => $user->id]);
        $history->email = self::normalizeEmail($user->email);
        $history->phone = self::normalizePhone($user->phone);
        $history->device_identifier = self::normalizeDeviceIdentifier($deviceIdentifier);
        $history->bonus_amount = $settings['amount'];

        if ($history->exists && (int) $history->granted_status === 1) {
            self::logAttempt($history, false, 'already_claimed');
            return $response;
        }

        if (!$settings['status']) {
            self::saveRejectedHistory($history, 'bonus_disabled');
            return $response;
        }

        if ($settings['amount'] <= 0) {
            self::saveRejectedHistory($history, 'invalid_bonus_amount');
            return $response;
        }

        if ((int) Helpers::get_business_settings('wallet_status') !== 1) {
            self::saveRejectedHistory($history, 'wallet_disabled');
            return $response;
        }

        if (!$history->device_identifier) {
            self::saveRejectedHistory($history, 'device_identifier_missing');
            return $response;
        }

        if (self::hasGrantedBonusDuplicate($history)) {
            self::saveRejectedHistory($history, self::getDuplicateReason($history));
            return $response;
        }

        $walletTransaction = CustomerLogic::create_wallet_transaction(
            $user->id,
            (float) $settings['amount'],
            'registration_bonus',
            'registration_bonus_' . $user->id
        );

        if (!$walletTransaction) {
            self::saveRejectedHistory($history, 'wallet_transaction_failed');
            return $response;
        }

        $history->granted_status = 1;
        $history->rejected_reason = null;
        $history->granted_at = now();
        $history->save();
        self::logAttempt($history, true);

        Helpers::expenseCreate(
            amount: (float) $settings['amount'],
            type: 'registration_bonus',
            datetime: now(),
            created_by: 'admin',
            user_id: $user->id,
            description: 'Registration welcome bonus'
        );

        $response['registration_bonus_granted'] = 1;
        $response['registration_bonus_amount'] = (float) $settings['amount'];

        return $response;
    }

    private static function getSettings(): array
    {
        $status = (int) (Helpers::get_business_settings('registration_bonus_status') ?? 0);
        $amount = (float) (Helpers::get_business_settings('registration_bonus_amount') ?? 0);
        $popupMessage = trim((string) (Helpers::get_business_settings('registration_bonus_popup_message') ?? ''));

        return [
            'status' => $status,
            'amount' => $amount,
            'popup_message' => $popupMessage !== ''
                ? $popupMessage
                : 'Congratulations! Your welcome bonus has been added to your wallet.',
        ];
    }

    private static function hasGrantedBonusDuplicate(RegistrationBonusHistory $history): bool
    {
        return self::getDuplicateReason($history) !== null;
    }

    private static function getDuplicateReason(RegistrationBonusHistory $history): ?string
    {
        if ($history->email && RegistrationBonusHistory::where('granted_status', 1)->where('email', $history->email)->where('user_id', '!=', $history->user_id)->exists()) {
            return 'duplicate_email';
        }

        if ($history->phone && RegistrationBonusHistory::where('granted_status', 1)->where('phone', $history->phone)->where('user_id', '!=', $history->user_id)->exists()) {
            return 'duplicate_phone';
        }

        if ($history->device_identifier && RegistrationBonusHistory::where('granted_status', 1)->where('device_identifier', $history->device_identifier)->where('user_id', '!=', $history->user_id)->exists()) {
            return 'duplicate_device';
        }

        return null;
    }

    private static function saveRejectedHistory(RegistrationBonusHistory $history, string $reason): void
    {
        $history->granted_status = 0;
        $history->granted_at = null;
        $history->rejected_reason = $reason;
        $history->save();
        self::logAttempt($history, false, $reason);
    }

    private static function logAttempt(RegistrationBonusHistory $history, bool $granted, ?string $reason = null): void
    {
        BonusClaimLog::safeCreate([
            'bonus_type' => 'signup',
            'user_id' => $history->user_id,
            'review_id' => null,
            'email' => $history->email,
            'phone' => $history->phone,
            'device_identifier' => $history->device_identifier,
            'bonus_amount' => (float) ($history->bonus_amount ?? 0),
            'bonus_points' => 0,
            'granted_status' => $granted ? 1 : 0,
            'block_reason' => $granted ? null : $reason,
            'attempted_at' => now(),
            'granted_at' => $granted ? ($history->granted_at ?? now()) : null,
            'context' => [
                'history_id' => $history->id,
            ],
        ]);
    }

    public static function normalizeEmailForBonus(?string $email): ?string
    {
        return self::normalizeEmail($email);
    }

    public static function normalizePhoneForBonus(?string $phone): ?string
    {
        return self::normalizePhone($phone);
    }

    public static function normalizeDeviceIdentifierForBonus(?string $deviceIdentifier): ?string
    {
        return self::normalizeDeviceIdentifier($deviceIdentifier);
    }

    private static function normalizeEmail(?string $email): ?string
    {
        $email = strtolower(trim((string) $email));

        if ($email === '' || !str_contains($email, '@')) {
            return $email !== '' ? $email : null;
        }

        [$localPart, $domain] = explode('@', $email, 2);

        if (in_array($domain, ['gmail.com', 'googlemail.com'])) {
            $localPart = explode('+', $localPart, 2)[0];
            $localPart = str_replace('.', '', $localPart);
            $domain = 'gmail.com';
        }

        return $localPart . '@' . $domain;
    }

    private static function normalizePhone(?string $phone): ?string
    {
        $phone = preg_replace('/\D+/', '', trim((string) $phone));

        if ($phone === '') {
            return null;
        }

        if (str_starts_with($phone, '8801') && strlen($phone) === 13) {
            return $phone;
        }

        if (str_starts_with($phone, '01') && strlen($phone) === 11) {
            return '88' . $phone;
        }

        if (str_starts_with($phone, '1') && strlen($phone) === 10) {
            return '880' . $phone;
        }

        return $phone;
    }

    private static function normalizeDeviceIdentifier(?string $deviceIdentifier): ?string
    {
        $deviceIdentifier = strtolower(trim((string) $deviceIdentifier));
        return $deviceIdentifier !== '' ? $deviceIdentifier : null;
    }
}
