<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
header('Content-Type: application/json');

$dataFile=__DIR__.'/data.json';

function loadEnv(){
    $env=[];
    $file=__DIR__.'/.env';
    if(!file_exists($file))return $env;
    $lines=file($file,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
    foreach($lines as $line){
        if(strpos(trim($line),'#')===0)continue;
        list($key,$val)=explode('=',$line,2);
        $env[trim($key)]=trim($val);
    }
    return $env;
}

function loadData(){
    global $dataFile;
    if(!file_exists($dataFile)){
        file_put_contents($dataFile,json_encode(['keys'=>[],'payments'=>[],'pending'=>[]]));
    }
    return json_decode(file_get_contents($dataFile),true);
}

function resolveKey($input,$data){
    if(isset($data['keys'][$input])){
        return $input;
    }
    foreach($data['keys'] as $plain=>$info){
        if(hash_equals(hash('sha256',$plain),$input)){
            return $plain;
        }
    }
    return null;
}

function saveData($data){
    global $dataFile;
    file_put_contents($dataFile,json_encode($data,JSON_PRETTY_PRINT));
}

function autoFlagKey($key,$reason='abuse'){
    $data=loadData();
    if(!isset($data['keys'][$key]))return;
    
    $now=time();
    $flagCount=($data['keys'][$key]['flag_count']??0)+1;
    
    $durations=[300,900,3600,7200,21600,43200,86400];
    $durationIndex=min($flagCount-1,count($durations)-1);
    $duration=$durations[$durationIndex];
    
    $data['keys'][$key]['flagged']=true;
    $data['keys'][$key]['flag_type']='auto';
    $data['keys'][$key]['flag_until']=$now+$duration;
    $data['keys'][$key]['flag_count']=$flagCount;
    $data['keys'][$key]['flag_reason']=$reason;
    $data['keys'][$key]['flag_history'][]=['time'=>$now,'duration'=>$duration,'reason'=>$reason];
    
    saveData($data);
    
    if(isset($data['keys'][$key]['email'])){
        require_once __DIR__.'/email.php';
        sendFlagEmail($data['keys'][$key]['email'],$key,'auto',$now+$duration,$reason);
    }
    
    error_log("Auto-flagged key $key for $duration seconds (offense #$flagCount): $reason");
}

function checkExpiredFlags(){
    $data=loadData();
    $now=time();
    $updated=false;
    
    foreach($data['keys']as$key=>$info){
        if(isset($info['flagged'])&&$info['flagged']&&isset($info['flag_type'])&&$info['flag_type']==='auto'){
            if(isset($info['flag_until'])&&$info['flag_until']<=$now){
                $data['keys'][$key]['flagged']=false;
                unset($data['keys'][$key]['flag_until']);
                unset($data['keys'][$key]['flag_type']);
                unset($data['keys'][$key]['flag_reason']);
                $updated=true;
            }
        }
    }
    
    if($updated)saveData($data);
}

function detectAbuse($key,$keyData){
    $now=time();
    $history=$keyData['request_history']??[];
    
    $last60s=array_filter($history,fn($t)=>$t>=($now-60));
    if(count($last60s)>100){
        autoFlagKey($key,'Rate limit: '.count($last60s).' requests in 60s');
        return true;
    }
    
    $last300s=array_filter($history,fn($t)=>$t>=($now-300));
    if(count($last300s)>300){
        autoFlagKey($key,'Rate limit: '.count($last300s).' requests in 5min');
        return true;
    }
    
    return false;
}

function respond($data,$code=200){
    http_response_code($code);
    $json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PARTIAL_OUTPUT_ON_ERROR);
    if ($json === false) {
        $data = ['error' => 'JSON Encode Error: ' . json_last_error_msg()];
        $json = json_encode($data);
    }
    echo $json;
    exit;
}

function getClientIp() {
    return $_SERVER['HTTP_CLIENT_IP'] 
        ?? $_SERVER['HTTP_X_FORWARDED_FOR'] 
        ?? $_SERVER['HTTP_X_REAL_IP'] 
        ?? $_SERVER['REMOTE_ADDR'];
}

function detectGuestAbuse($ip, $guestData) {
    $now = time();
    $history = $guestData['request_history'] ?? [];
    
    $last60s = array_filter($history, fn($t) => $t >= ($now - 60));
    if (count($last60s) > 5) return true;
    
    $lastHour = array_filter($history, fn($t) => $t >= ($now - 3600));
    if (count($lastHour) > 50) return true;
    
    return false;
}

function validateKey($keyInput){
    checkExpiredFlags();
    $data=loadData();
    
    if(empty($keyInput)){
        $ip=getClientIp();
        
        if(!isset($data['guests']))$data['guests']=[];
        
        if(!isset($data['guests'][$ip])){
            $data['guests'][$ip]=[
                'created'=>time(),
                'requests'=>0,
                'request_history'=>[],
                'last_used'=>time(),
                'is_guest'=>true
            ];
        }
        
        if(detectGuestAbuse($ip, $data['guests'][$ip])){
            respond(['error'=>'Free tier rate limit exceeded (5 req/min). Buy a key.'], 429);
        }
        
        $now=time();
        $data['guests'][$ip]['requests']++;
        $data['guests'][$ip]['last_used']=$now;
        if(!isset($data['guests'][$ip]['request_history']))$data['guests'][$ip]['request_history']=[];
        $data['guests'][$ip]['request_history'][]=$now;
        $data['guests'][$ip]['request_history']=array_slice($data['guests'][$ip]['request_history'],-50);
        
        saveData($data);
        return $data['guests'][$ip];
    }

    $key=resolveKey($keyInput,$data);
    if(!$key){
        respond(['error'=>'Invalid API key'],401);
    }
    
    $keyData=$data['keys'][$key];
    
    if(isset($keyData['flagged'])&&$keyData['flagged']){
        $flagInfo=['error'=>'API key flagged'];
        
        if(isset($keyData['flag_type'])){
            $flagInfo['flag_type']=$keyData['flag_type'];
            
            if($keyData['flag_type']==='auto'&&isset($keyData['flag_until'])){
                $flagInfo['flagged_until']=$keyData['flag_until'];
                $flagInfo['seconds_remaining']=$keyData['flag_until']-time();
                $flagInfo['unflag_time']=date('Y-m-d H:i:s',$keyData['flag_until']);
            }else{
                $flagInfo['flagged_until']='unknown';
                $flagInfo['message']='Manual flag - contact support';
            }
            
            if(isset($keyData['flag_reason'])){
                $flagInfo['reason']=$keyData['flag_reason'];
            }
        }
        
        respond($flagInfo,403);
    }
    
    if(detectAbuse($key,$keyData)){
        $data=loadData();
        $keyData=$data['keys'][$key];
        
        $flagInfo=['error'=>'API key auto-flagged for abuse'];
        if(isset($keyData['flag_until'])){
            $flagInfo['flagged_until']=$keyData['flag_until'];
            $flagInfo['seconds_remaining']=$keyData['flag_until']-time();
            $flagInfo['unflag_time']=date('Y-m-d H:i:s',$keyData['flag_until']);
        }
        respond($flagInfo,403);
    }
    
    $now=time();
    $data['keys'][$key]['requests']++;
    $data['keys'][$key]['last_used']=$now;
    if(!isset($data['keys'][$key]['request_history']))$data['keys'][$key]['request_history']=[];
    $data['keys'][$key]['request_history'][]=$now;
    $data['keys'][$key]['request_history']=array_slice($data['keys'][$key]['request_history'],-5000);
    saveData($data);
    return $data['keys'][$key];
}

function checkAdmin(){
    $env=loadEnv();
    $headers=getallheaders();
    $adminKey=$headers['X-Admin-Key']??$_GET['admin_key']??null;
    if($adminKey!==$env['ADMIN_KEY']){
        respond(['error'=>'Unauthorized'],401);
    }
}

$method=$_SERVER['REQUEST_METHOD'];
$path=parse_url($_SERVER['REQUEST_URI'],PHP_URL_PATH);
$segments=array_filter(explode('/',$path));
$endpoint=end($segments);

if(!$endpoint || $endpoint === 'api.php') {
    if(isset($_GET['action'])) {
        $endpoint = $_GET['action'];
    } elseif(isset($_GET['endpoint'])) {
        $endpoint = $_GET['endpoint'];
    } elseif(isset($_GET['q']) || isset($_GET['query'])) {
        $endpoint = 'search';
    } elseif(isset($_GET['id'])) {
        $endpoint = 'paste';
    } elseif(isset($_GET['key'])) {
        $endpoint = 'validate'; 
    }
}

if($endpoint==='status'){
    $metadataFile=__DIR__.'/doxbin-db/metadata.json';
    $progressFile=__DIR__.'/doxbin-db/scraper_progress.json';
    
    $stats=[
        'status'=>'online',
        'api_version'=>'1.0.0',
        'server_time'=>date('c'),
        'total_pastes'=>0,
        'database_last_updated'=>null,
        'scraper_status'=>'unknown'
    ];
    
    if(file_exists($metadataFile)){
        $stats['database_last_updated']=date('c',filemtime($metadataFile));
    }
    
    $pastesDir = __DIR__.'/doxbin-db/pastes';
    if(is_dir($pastesDir) || is_link($pastesDir)) {
        // Appending a trailing slash ensures symlinks to directories are dereferenced correctly by 'ls'
        $stats['total_pastes'] = exec('ls -1q '.escapeshellarg($pastesDir.'/').' | wc -l');
        $stats['total_pastes'] = (int)trim($stats['total_pastes']);
    } else if(file_exists($metadataFile)) {
        $meta=json_decode(file_get_contents($metadataFile),true);
        if(is_array($meta)){
            $stats['total_pastes']=count($meta);
        }
    }
    
    if(file_exists($progressFile)){
        $prog=json_decode(file_get_contents($progressFile),true);
        if($prog){
            $stats['scraper_status']=[
                'current_page'=>$prog['front_next']??0,
                'last_run'=>isset($prog['last_run'])?date('c',$prog['last_run']):'never'
            ];
        }
    }
    
    respond($stats);
}

if($endpoint==='validate'){
    $key=$_GET['key']??'';
    $keyData=validateKey($key);
    respond([
        'valid'=>true,
        'requests'=>$keyData['requests'],
        'created'=>date('Y-m-d',$keyData['created']),
        'tier'=> (isset($keyData['is_guest']) && $keyData['is_guest']) ? 'free' : 'premium'
    ]);
}

if($endpoint==='search'){
    $key=$_GET['key']??'';
    $userData=validateKey($key);
    $isGuest=isset($userData['is_guest'])&&$userData['is_guest'];
    
    require_once __DIR__.'/doxbin-db/search.php';
    
    $query=$_GET['q']??$_GET['query']??'';
    if(empty($query)){
        respond(['error'=>'Query parameter required'],400);
    }
    
    $limit=(int)($_GET['limit']??50);
    $offset=(int)($_GET['offset']??0);
    
    if($isGuest) {
        $limit = min($limit, 5);
        if($offset > 20) {
            respond(['error'=>'Free tier cannot paginate deep. Buy a key.'], 403);
        }
    }
    
    $limit=min(max($limit,1),100);
    
    $results=searchPastes($query,$limit,$offset);
    respond($results);
}

if($endpoint==='paste'){
    $key=$_GET['key']??'';
    validateKey($key);
    
    require_once __DIR__.'/doxbin-db/search.php';
    
    $id=(int)($_GET['id']??0);
    if(!$id){
        respond(['error'=>'Paste ID required'],400);
    }
    
    $paste=getPaste($id);
    if(!$paste){
        respond(['error'=>'Paste not found'],404);
    }
    
    respond($paste);
}

if($endpoint==='dbstats'){
    $key=$_GET['key']??'';
    validateKey($key);
    
    require_once __DIR__.'/doxbin-db/search.php';
    
    $stats=getStats();
    respond($stats);
}

if($endpoint==='users'){
    $key=$_GET['key']??'';
    $userData=validateKey($key);
    $isGuest=isset($userData['is_guest'])&&$userData['is_guest'];
    
    $usersFile=__DIR__.'/doxbin-db/users_data.json';
    if(!file_exists($usersFile)){
        respond(['error'=>'Users data not available yet'], 404);
    }
    
    $users=json_decode(file_get_contents($usersFile),true);
    if(!$users) $users=[];
    
    if(isset($_GET['username']) || isset($_GET['id'])){
        $identifier = $_GET['username'] ?? $_GET['id'];
        
        // Helper to rewrite PFP URLs
        $rewritePfp = function($u) {
            if (isset($u['pfp_url']) && strpos($u['pfp_url'], 'doxbin.com/attachment/') !== false) {
                $u['pfp_url'] = preg_replace('#^https?://doxbin\.com/attachment/#', 'https://dox.li/proxy/', $u['pfp_url']);
            }
            return $u;
        };

        // 1. Direct username match
        if(isset($users[$identifier])){
            respond($rewritePfp($users[$identifier]));
        }
        
        // 2. ID match
        foreach($users as $u){
            if(isset($u['uid']) && (string)$u['uid'] === (string)$identifier){
                respond($rewritePfp($u));
            }
        }
        
        // 3. Case-insensitive username match
        foreach($users as $username => $u){
            if(strtolower($username) === strtolower($identifier)){
                respond($rewritePfp($u));
            }
        }
        
        respond(['error'=>'User not found'], 404);
    }
    
    $limit=(int)($_GET['limit']??50);
    $offset=(int)($_GET['offset']??0);
    
    if($isGuest) {
        $limit = min($limit, 5);
        if($offset > 20) {
            respond(['error'=>'Free tier cannot paginate deep. Buy a key.'], 403);
        }
    } else {
        $limit = min($limit, 100);
    }
    
    $userList = array_values($users);
    $total = count($userList);
    $subset = array_slice($userList, $offset, $limit);
    
    // Rewrite PFPs in list
    foreach ($subset as &$u) {
        if (isset($u['pfp_url']) && strpos($u['pfp_url'], 'doxbin.com/attachment/') !== false) {
            $u['pfp_url'] = preg_replace('#^https?://doxbin\.com/attachment/#', 'https://dox.li/proxy/', $u['pfp_url']);
        }
    }

    respond([
        'total'=>$total,
        'limit'=>$limit,
        'offset'=>$offset,
        'users'=>$subset
    ]);
}

if($endpoint === 'api' || $endpoint === 'api.php') {
    respond(['available'=>[
        'validate - GET ?key=xxx',
        'search - GET ?key=xxx&q=query&limit=50&offset=0',
        'paste - GET ?key=xxx&id=123',
        'dbstats - GET ?key=xxx',
        'users - GET ?key=xxx&limit=50&offset=0',
        'user - GET ?key=xxx&username=username'
    ]]);
}

respond(['error'=>'Endpoint not found','available'=>[
    'validate - GET ?key=xxx',
    'search - GET ?key=xxx&q=query&limit=50&offset=0',
    'paste - GET ?key=xxx&id=123',
    'dbstats - GET ?key=xxx',
    'users - GET ?key=xxx&limit=50&offset=0',
    'user - GET ?key=xxx&username=username'
]],404);
