<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;

function Mirai_referralIsEnabled() {
    $options = Mirai_opt();
    return isset($options->referralEnable) && $options->referralEnable === '1';
}

function Mirai_referralGetLink($uid = 0, $url = '') {
    if (!$uid) {
        $user = Mirai_user();
        if ($user->hasLogin()) $uid = (int)$user->uid;
    }
    if (!$uid) return '';
    if (!$url) {
        $url = rtrim(Mirai_opt()->siteUrl, '/');
    }
    $separator = (strpos($url, '?') !== false) ? '&' : '?';
    $options = Mirai_opt();
    $codeFormat = isset($options->referralCodeFormat) ? $options->referralCodeFormat : 'uid';
    if ($codeFormat === 'custom' && function_exists('Mirai_referralGetCode')) {
        $code = Mirai_referralGetCode($uid);
        if ($code !== '' && $code !== (string)$uid) return $url . $separator . 'ref=' . $code;
    }
    return $url . $separator . 'ref=' . $uid;
}

function Mirai_referralParseRefParam() {
    $ref = isset($_GET['ref']) ? trim((string)$_GET['ref']) : '';
    if ($ref === '') return 0;

    $referrerUid = 0;
    if (ctype_digit($ref)) {
        $referrerUid = (int)$ref;
    } else {
        try {
            $db = \Typecho\Db::get();
            $row = $db->fetchRow($db->select('uid')->from(Mirai_pointsTable('mirai_referrals'))->where('invite_code = ?', $ref)->limit(1));
            if ($row) $referrerUid = (int)$row['uid'];
        } catch (\Exception $e) {}
    }
    if ($referrerUid <= 0) return 0;

    if (session_status() !== PHP_SESSION_ACTIVE) {
        @session_start();
    }
    $_SESSION['mirai_referrer_uid'] = $referrerUid;
    return $referrerUid;
}

function Mirai_referralGetReferrerUid($uid = 0) {
    if (!Mirai_referralIsEnabled()) return 0;

    $options = Mirai_opt();
    $bindMode = isset($options->referralBindMode) ? $options->referralBindMode : 'register';

    if ($bindMode === 'register' && $uid > 0) {
        $db = \Typecho\Db::get();
        $row = $db->fetchRow($db->select('referrer_uid')->from('table.users')->where('uid = ?', $uid));
        $referrerUid = (int)($row['referrer_uid'] ?? 0);
        if ($referrerUid > 0) {
            $selfPurchase = isset($options->referralSelfPurchase) ? $options->referralSelfPurchase : '1';
            if ($selfPurchase !== '1' && $referrerUid == $uid) return 0;
            return $referrerUid;
        }
    }

    if (session_status() !== PHP_SESSION_ACTIVE) {
        @session_start();
    }
    $sessionRef = (int)($_SESSION['mirai_referrer_uid'] ?? 0);
    if ($sessionRef > 0) {
        $selfPurchase = isset($options->referralSelfPurchase) ? $options->referralSelfPurchase : '1';
        if ($selfPurchase !== '1' && $sessionRef == $uid) return 0;
        return $sessionRef;
    }

    return 0;
}

function Mirai_referralBindUser($uid, $referrerUid = 0) {
    if (!$uid) return false;
    if (!Mirai_referralIsEnabled()) return false;

    if ($referrerUid <= 0) {
        if (session_status() !== PHP_SESSION_ACTIVE) {
            @session_start();
        }
        $referrerUid = (int)($_SESSION['mirai_referrer_uid'] ?? 0);
    }
    if ($referrerUid <= 0) return false;
    if ($referrerUid == $uid) return false;

    $db = \Typecho\Db::get();
    $refTable = Mirai_pointsTable('mirai_referrals');

    $exists = $db->fetchRow($db->select('id')->from($refTable)->where('uid = ?', $uid));
    if ($exists) return false;

    try {
        $inviteCode = '';
        $_opts = Mirai_opt();
        if (isset($_opts->referralCodeFormat) && $_opts->referralCodeFormat === 'custom') {
            for ($i = 0; $i < 10; $i++) {
                $inviteCode = substr(md5($uid . '_' . time() . '_' . mt_rand(1000, 9999) . '_' . $i), 0, 8);
                $dup = $db->fetchRow($db->select('id')->from($refTable)->where('invite_code = ?', $inviteCode)->limit(1));
                if (!$dup) break;
            }
        }
        $db->query($db->insert($refTable)->rows([
            'uid' => $uid,
            'referrer_uid' => $referrerUid,
            'bind_type' => 'register',
            'ip_address' => $_SERVER['REMOTE_ADDR'] ?? '',
            'invite_code' => $inviteCode,
            'created' => time(),
        ]));

        $db->query($db->update('table.users')->rows(['referrer_uid' => $referrerUid])->where('uid = ?', $uid));

        return true;
    } catch (\Exception $e) {
        return false;
    }
}

function Mirai_referralGetCode($uid = 0) {
    if (!$uid) {
        $user = Mirai_user();
        if ($user->hasLogin()) $uid = (int)$user->uid;
    }
    if (!$uid) return '';
    
    $options = Mirai_opt();
    $codeFormat = isset($options->referralCodeFormat) ? $options->referralCodeFormat : 'uid';
    
    if ($codeFormat === 'custom') {
        try {
            $db = \Typecho\Db::get();
            $refTable = Mirai_pointsTable('mirai_referrals');
            $row = $db->fetchRow($db->select('invite_code')->from($refTable)->where('uid = ?', $uid)->limit(1));
            if ($row && !empty($row['invite_code'])) return $row['invite_code'];
            for ($i = 0; $i < 10; $i++) {
                $newCode = substr(md5($uid . '_inv_' . time() . '_' . mt_rand(1000, 9999) . '_' . $i), 0, 8);
                $dup = $db->fetchRow($db->select('id')->from($refTable)->where('invite_code = ?', $newCode)->limit(1));
                if (!$dup) break;
            }
            $exists = $db->fetchRow($db->select('id')->from($refTable)->where('uid = ?', $uid)->limit(1));
            if ($exists) {
                $db->query($db->update($refTable)->rows(['invite_code' => $newCode])->where('uid = ?', $uid));
            } else {
                $db->query($db->insert($refTable)->rows(['uid' => $uid, 'referrer_uid' => 0, 'bind_type' => 'session', 'ip_address' => '', 'invite_code' => $newCode, 'created' => time()]));
            }
            return $newCode;
        } catch (\Exception $e) {}
        return (string)$uid;
    }
    
    return (string)$uid;
}

function Mirai_referralCommissionRate() {
    if (!Mirai_referralIsEnabled()) return 0;
    
    $user = Mirai_user();
    $uid = $user->hasLogin() ? (int)$user->uid : 0;
    
    return Mirai_referralGetRebateRatio($uid) / 100;
}

function Mirai_referralGetRecords($uid, $page = 1, $pageSize = 10) {
    if (!Mirai_referralIsEnabled() || !$uid) {
        return ['list' => [], 'total' => 0, 'page' => $page, 'pageSize' => $pageSize];
    }
    
    $db = \Typecho\Db::get();
    $refTable = Mirai_pointsTable('mirai_referrals');
    
    try {
        $countRow = $db->fetchRow($db->select(['COUNT(*)' => 'cnt'])->from($refTable)->where('referrer_uid = ?', $uid));
        $total = (int)($countRow['cnt'] ?? 0);
        
        if ($total === 0) {
            return ['list' => [], 'total' => 0, 'page' => $page, 'pageSize' => $pageSize];
        }
        
        $offset = ($page - 1) * $pageSize;
        $records = $db->fetchAll($db->select()->from($refTable)
            ->where('referrer_uid = ?', $uid)
            ->order('created', \Typecho\Db::SORT_DESC)
            ->limit($pageSize)
            ->offset($offset));
        
        return [
            'list' => $records ?: [],
            'total' => $total,
            'page' => $page,
            'pageSize' => $pageSize
        ];
    } catch (\Exception $e) {
        return ['list' => [], 'total' => 0, 'page' => $page, 'pageSize' => $pageSize];
    }
}
