<?php
// 本机随机临时表验证，不修改真实建议，不调用外部通知。
if (PHP_SAPI !== 'cli') exit;
require dirname(__DIR__).'/vendor/autoload.php';
use think\facade\Db;
use think\exception\HttpResponseException;
use app\mobile\controller\OmsSuggestion;

class SuggestionRejectCheck extends OmsSuggestion {
    public static $account;
    public static $notifications = 0;
    protected function current() { return self::$account; }
    protected function guarded($action) { return $action(); }
    protected function notify($row, $title, $recipients) { self::$notifications++; }
}
$app = new \think\App(dirname(__DIR__).'/');
$app->initialize();
$config = $app->config->get('database');
$connection = $config['connections'][$config['default']];
if (!in_array($connection['hostname'], ['localhost','127.0.0.1'], true)) throw new RuntimeException('Local database required');
$originalPrefix = $connection['prefix'];
$prefix = 'suggestion_test_'.bin2hex(random_bytes(4)).'_';
$connection['prefix'] = $prefix;
$config['connections']['suggestion_test'] = $connection; $config['default'] = 'suggestion_test';
$app->config->set($config, 'database'); Db::setConfig($app->config);
$table = $prefix.'onsite_suggestion_list'; $created = false;
function checkReject($condition, $message) { if (!$condition) throw new RuntimeException($message); }
function invokeReject($action, $data) {
    global $app;
    $request = new \think\Request();
    $request->withServer(['REQUEST_METHOD'=>$action === 'detail' ? 'GET' : 'POST']);
    if ($action === 'detail') $request->withGet($data); else $request->withPost($data);
    $app->instance('request', $request);
    try { $response = (new SuggestionRejectCheck($app))->$action(); }
    catch (HttpResponseException $e) { $response = $e->getResponse(); }
    return [$response->getCode(), json_decode($response->getContent(), true)];
}
try {
    Db::execute('CREATE TABLE `'.$table.'` LIKE `'.$originalPrefix.'onsite_suggestion_list`'); $created = true;
    $row = ['eid'=>900000001, 'ename'=>'测试提议人', 'status'=>1, 'adopt'=>0, 'selfshut'=>1, 'owner'=>0, 'due_dpt'=>0, 'title'=>'测试建议', 'suggestion'=>'测试内容', 'reason'=>'', 'creat_date'=>time()];
    foreach (Db::query('SHOW COLUMNS FROM `'.$table.'`') as $field) {
        if (!array_key_exists($field['Field'], $row) && $field['Null'] === 'NO' && $field['Default'] === null && $field['Extra'] !== 'auto_increment') {
            $row[$field['Field']] = preg_match('/int|float|decimal|double/', $field['Type']) ? 0 : '';
        }
    }
    $id = Db::name('onsite_suggestion_list')->insertGetId($row);
    $input = ['id'=>$id, 'action'=>'reject', 'reason'=>' 内容重复 <请核实> '];
    SuggestionRejectCheck::$account = ['username'=>'900000001', 'admin_id'=>0, 'user_id'=>1];
    checkReject(invokeReject('assign', $input)[0] === 403, 'Author without assignment rights cannot reject');
    SuggestionRejectCheck::$account = ['username'=>'900000002', 'admin_id'=>2, 'user_id'=>0];
    foreach (['', '   ', str_repeat('长', 1001)] as $reason) {
        $invalid = $input; $invalid['reason'] = $reason;
        checkReject(invokeReject('assign', $invalid)[0] === 400, 'Invalid rejection reason must be rejected');
    }
    $invalid = $input; $invalid['action'] = 'unknown';
    checkReject(invokeReject('assign', $invalid)[0] === 400, 'Unknown assignment action must be rejected');
    checkReject((int)Db::name('onsite_suggestion_list')->where('id',$id)->value('status') === 1, 'Invalid request must preserve status');
    checkReject(invokeReject('assign', $input)[0] === 200, 'Authorized assigner can reject');
    $saved = Db::name('onsite_suggestion_list')->find($id);
    checkReject((int)$saved['status'] === 4 && (int)$saved['adopt'] === 2, 'Rejected suggestion must finish as not adopted');
    checkReject($saved['reason'] === htmlspecialchars(trim($input['reason']), ENT_QUOTES, 'UTF-8'), 'Rejection reason must be preserved safely');
    checkReject((int)$saved['owner'] === 0 && (int)$saved['due_dpt'] === 0, 'Rejection must not assign a department');
    checkReject(SuggestionRejectCheck::$notifications === 0, 'Rejection must not send an assignment notification');
    checkReject(invokeReject('assign', $input)[0] === 409, 'Repeated rejection must be rejected');
    checkReject(invokeReject('assign', ['id'=>$id, 'departmentId'=>1])[0] === 409, 'Rejected suggestion cannot be assigned');
    SuggestionRejectCheck::$account = ['username'=>'900000001', 'admin_id'=>0, 'user_id'=>1];
    $detail = invokeReject('detail', ['id'=>$id])[1]['data'];
    checkReject($detail['reason'] === trim($input['reason']) && $detail['statusName'] === '未采纳', 'Author must see result and reason');
    checkReject(!$detail['canAssign'] && !$detail['canFeedback'] && !$detail['canConfirm'] && !$detail['canDelete'], 'Finished suggestion must expose no processing actions');
    echo "Suggestion rejection permissions, validation, final status and author visibility checks passed.\n";
} finally {
    if ($created) Db::execute('DROP TABLE IF EXISTS `'.$table.'`');
}
