<?php
namespace App\Core;

use RuntimeException;

class WalletService {
    public static function ensure(int $userId, string $type): int {
        $row=Database::fetchOne('SELECT id FROM wallets WHERE user_id=? AND wallet_type=? LIMIT 1',[$userId,$type]);
        if($row)return (int)$row['id'];
        Database::execute('INSERT INTO wallets (user_id,wallet_type,balance,created_at,updated_at) VALUES (?,?,0,NOW(),NOW())',[$userId,$type]);
        return Database::lastInsertId();
    }
    public static function balance(int $userId,string $type): float { $r=Database::safeFetchOne('SELECT balance FROM wallets WHERE user_id=? AND wallet_type=? LIMIT 1',[$userId,$type]);return (float)($r['balance']??0); }
    public static function credit(int $userId,string $type,float $amount,string $note='',?int $ref=null): bool {
        if($amount<=0)return false;$walletId=self::ensure($userId,$type);
        Database::execute('UPDATE wallets SET balance=balance+?,updated_at=NOW() WHERE id=?',[$amount,$walletId]);
        return Database::execute('INSERT INTO wallet_transactions (wallet_id,user_id,wallet_type,transaction_type,amount,fee,reference_type,reference_id,note,created_at) VALUES (?,?,?,?,?,0,?,?,?,NOW())',[$walletId,$userId,$type,'credit',$amount,'manual',$ref,$note]);
    }
    public static function debit(int $userId,string $type,float $amount,string $note='',?int $ref=null): bool {
        if($amount<=0)return false;$wallet=Database::fetchOne('SELECT * FROM wallets WHERE user_id=? AND wallet_type=? LIMIT 1 FOR UPDATE',[$userId,$type]);
        if(!$wallet||(float)$wallet['balance']+0.0001<$amount)return false;
        Database::execute('UPDATE wallets SET balance=balance-?,updated_at=NOW() WHERE id=?',[$amount,$wallet['id']]);
        return Database::execute('INSERT INTO wallet_transactions (wallet_id,user_id,wallet_type,transaction_type,amount,fee,reference_type,reference_id,note,created_at) VALUES (?,?,?,?,?,0,?,?,?,NOW())',[$wallet['id'],$userId,$type,'debit',$amount,'manual',$ref,$note]);
    }
    public static function transfer(int $userId,string $from,string $to,float $amount): bool {
        if($from!=='cash'||$to!=='purchase'||$amount<=0)return false;
        return (bool)Database::transaction(function()use($userId,$from,$to,$amount){if(!self::debit($userId,$from,$amount,'Transfer to '.$to))throw new RuntimeException('Insufficient wallet balance.');if(!self::credit($userId,$to,$amount,'Transfer from '.$from))throw new RuntimeException('Could not credit destination wallet.');return true;});
    }
    public static function withdrawNet(float $amount): array {$fee=round($amount*(WITHDRAWAL_CHARGE_PERCENT/100),2);return ['gross'=>$amount,'fee'=>$fee,'net'=>round($amount-$fee,2)];}
}
