<?php
// +----------------------------------------------------------------------
// | onezan-admin 快速开发的管理平台
// +----------------------------------------------------------------------
// | 官方网址：https://www.onezan.cn
// +----------------------------------------------------------------------
// | onezan团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: 543885307@qq.com
// +----------------------------------------------------------------------
namespace app\repository\user;

use app\model\User;
use app\repository\BaseRepository;
use think\facade\Db;


/**
 * User Repository
 * @package app\repository\user
 */
class UserRepository extends BaseRepository
{

    /**
     * Paginate users for admin panel
     * @param array $filters Filter conditions (user_id, keyword, status, level_id, user_type, exclude_id)
     * @param int $limit Per-page limit
     * @return array
     */
    public function paginateForAdmin(array $filters, int $limit): array
    {
        $query = User::with(['level', 'verifyProfile'])->order('id', 'desc');

        if (is_numeric($filters['exclude_id'] ?? null)) {
            $query->where('id', '<>', (int)$filters['exclude_id']);
        }
        if (is_numeric($filters['user_id'] ?? null)) {
            $query->where('id', (int)$filters['user_id']);
        }
        $keyword = trim((string)($filters['keyword'] ?? ''));
        if ($keyword !== '') {
            $query->where('username|phone|nickname|invite_code', 'like', "%{$keyword}%");
        }
        if (is_numeric($filters['status'] ?? null)) {
            $query->where('verify_status', (int)$filters['status']);
        }
        if (is_numeric($filters['level_id'] ?? null)) {
            $query->where('level_id', (int)$filters['level_id']);
        }
        if (is_numeric($filters['user_type'] ?? null)) {
            $userType = (int)$filters['user_type'];
            $query->whereHas('verifyProfile', function ($q) use ($userType) {
                $q->where('user_type', $userType);
            });
        }

        return $query->paginate($limit)->toArray();
    }


    /**
     * 按用户名查找用户
     * @param string $username
     * @return User|null
     */
    public function findByUsername(string $username): ?User
    {
        $user = User::where('username', $username)->find();
        return $user instanceof User ? $user : null;
    }


    /**
     * Find user by primary key
     * @param int $id User ID
     * @return User|null
     */
    public function findById(int $id): ?User
    {
        $user = User::find($id);
        return $user instanceof User ? $user : null;
    }


    /**
     * Find user by ID with level and verifyProfile relations eager-loaded
     * @param int $id User ID
     * @return User|null
     */
    public function findWithRelations(int $id): ?User
    {
        $user = User::with(['level', 'verifyProfile'])->find($id);
        return $user instanceof User ? $user : null;
    }


    /**
     * Find user by phone number
     * @param string $phone Phone number
     * @return User|null
     */
    public function findByPhone(string $phone): ?User
    {
        $user = User::where('phone', $phone)->find();
        return $user instanceof User ? $user : null;
    }


    /**
     * Find user by ID with a pessimistic write lock
     * @param int $id User ID
     * @return User|null
     */
    public function lockById(int $id): ?User
    {
        $user = User::where('id', $id)->lock(true)->find();
        return $user instanceof User ? $user : null;
    }


    /**
     * Get a user's invite code
     * @param int $userId User ID
     * @return string
     */
    public function getInviteCode(int $userId): string
    {
        return (string)Db::name('sys_users')->where('id', $userId)->value('invite_code');
    }


    /**
     * Update a user's invite code
     * @param int $userId User ID
     * @param string $inviteCode New invite code
     * @return void
     */
    public function updateInviteCode(int $userId, string $inviteCode): void
    {
        Db::name('sys_users')->where('id', $userId)->update(['invite_code' => $inviteCode]);
    }


    /**
     * Create a new user record
     * @param array $data User attributes
     * @return User
     */
    public function create(array $data): User
    {
        $user = new User();
        $user->save($data);
        return $user;
    }


    /**
     * 获取用户消费统计
     * @param int $userId
     * @return array
     */
    public function consumeStats(int $userId): array
    {
        return ['count' => 0, 'amount' => 0.0];
    }


    /**
     * Get user money balance statistics (total in/out)
     * @param int $userId User ID
     * @return array
     */
    public function moneyStats(int $userId): array
    {
        try {
            return [
                'total_in' => (string)Db::name('sys_user_balance_logs')->where('user_id', $userId)->where('type', 'money_in')->sum('amount'),
                'total_out' => (string)Db::name('sys_user_balance_logs')->where('user_id', $userId)->where('type', 'money_out')->sum('amount'),
            ];
        } catch (\Throwable $e) {
            return ['total_in' => '0', 'total_out' => '0'];
        }
    }


    /**
     * Get user points statistics (total recharge/deduct)
     * @param int $userId User ID
     * @return array
     */
    public function pointsStats(int $userId): array
    {
        try {
            return [
                'total_in' => (string)Db::name('sys_user_points_logs')->where('user_id', $userId)->where('type', 'recharge')->sum('amount'),
                'total_out' => (string)Db::name('sys_user_points_logs')->where('user_id', $userId)->where('type', 'deduct')->sum('amount'),
            ];
        } catch (\Throwable $e) {
            return ['total_in' => '0', 'total_out' => '0'];
        }
    }


    /**
     * 按邀请码查找用户
     * @param string $inviteCode
     * @return User|null
     */
    public function findByInviteCode(string $inviteCode): ?User
    {
        $user = User::where('invite_code', $inviteCode)->find();
        return $user instanceof User ? $user : null;
    }


    /**
     * Find parent user info for a given user
     * @param int $userId User ID
     * @return array|null
     */
    public function findParentInfo(int $userId): ?array
    {
        $parentId = (int)Db::name('sys_users')->where('id', $userId)->value('parent_user_id');
        if ($parentId <= 0) {
            return null;
        }

        $parent = User::field(['id', 'nickname', 'username', 'avatar'])->find($parentId);
        if (!$parent) {
            return null;
        }

        return [
            'id' => (int)$parent->id,
            'nickname' => (string)$parent->nickname,
            'username' => (string)$parent->username,
            'avatar' => (string)$parent->avatar,
        ];
    }


    /**
     * Bind a parent user to a child user
     * @param int $userId Child user ID
     * @param int $parentUserId Parent user ID
     * @return void
     */
    public function bindParent(int $userId, int $parentUserId): void
    {
        Db::name('sys_users')->where('id', $userId)->update(['parent_user_id' => $parentUserId]);
    }


    /**
     * Count direct children of a user
     * @param int $userId User ID
     * @return int
     */
    public function countChildren(int $userId): int
    {
        return (int)Db::name('sys_users')->where('parent_user_id', $userId)->count();
    }
}