#!/usr/bin/env php
<?php

/**
 * DB-IP Lite database downloader & binary converter for CodePress CMS
 */

if (php_sapi_name() !== 'cli' && (!isset($_SESSION['admin_user']))) {
    // Can also be included from admin handler
}

function updateGeoIPDatabase(): array
{
    $baseDir = dirname(__DIR__) . '/admin/storage/geoip';
    if (!is_dir($baseDir)) {
        @mkdir($baseDir, 0755, true);
    }

    $currentDate = new DateTime('first day of this month');
    $urls = [];
    for ($i = 0; $i < 3; $i++) {
        $ym = $currentDate->format('Y-m');
        $urls[] = "https://download.db-ip.com/free/dbip-country-lite-{$ym}.csv.gz";
        $currentDate->modify('-1 month');
    }

    $downloadUrl = null;
    $gzContent = null;

    foreach ($urls as $url) {
        $ctx = stream_context_create(['http' => ['timeout' => 15, 'user_agent' => 'CodePressCMS/1.9.0']]);
        $data = @file_get_contents($url, false, $ctx);
        if ($data !== false && strlen($data) > 1000) {
            $downloadUrl = $url;
            $gzContent = $data;
            break;
        }
    }

    if (!$gzContent) {
        return ['success' => false, 'message' => 'Kon DB-IP Lite database niet downloaden vanaf DB-IP.com.'];
    }

    $csvData = @gzdecode($gzContent);
    if (!$csvData) {
        return ['success' => false, 'message' => 'Kon gecomprimeerde DB-IP database niet uitpakken.'];
    }

    $ipv4BinPath = $baseDir . '/ipv4.bin';
    $ipv6BinPath = $baseDir . '/ipv6.bin';
    $v4Handle = fopen($ipv4BinPath, 'wb');
    $v6Handle = fopen($ipv6BinPath, 'wb');

    $lines = explode("\n", $csvData);
    $v4Count = 0;
    $v6Count = 0;

    foreach ($lines as $line) {
        $line = trim($line);
        if ($line === '' || $line[0] === '#') continue;

        $parts = str_getcsv($line);
        if (count($parts) < 3) continue;

        $startIp = trim($parts[0]);
        $endIp = trim($parts[1]);
        $country = strtoupper(trim($parts[2]));

        if (strlen($country) !== 2) continue;

        if (filter_var($startIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
            $startLong = ip2long($startIp);
            $endLong = ip2long($endIp);
            if ($startLong !== false && $endLong !== false) {
                // Pack 4-byte uint32 start, 4-byte uint32 end, 2-byte country code
                $record = pack('NNa2', $startLong, $endLong, $country);
                fwrite($v4Handle, $record);
                $v4Count++;
            }
        } elseif (filter_var($startIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
            $startBin = inet_pton($startIp);
            $endBin = inet_pton($endIp);
            if ($startBin !== false && $endBin !== false) {
                // Pack 16-byte start, 16-byte end, 2-byte country code
                $record = $startBin . $endBin . $country;
                fwrite($v6Handle, $record);
                $v6Count++;
            }
        }
    }

    fclose($v4Handle);
    fclose($v6Handle);

    $meta = [
        'source' => 'DB-IP Lite',
        'attribution' => 'IP geolocation by DB-IP (https://dbip.com)',
        'updated' => date('Y-m-d H:i:s'),
        'url' => $downloadUrl,
        'ipv4_records' => $v4Count,
        'ipv6_records' => $v6Count,
        'ipv4_size' => filesize($ipv4BinPath),
        'ipv6_size' => filesize($ipv6BinPath),
    ];

    file_put_contents($baseDir . '/meta.json', json_encode($meta, JSON_PRETTY_PRINT));

    return [
        'success' => true,
        'message' => "GeoIP database succesvol bijgewerkt! ({$v4Count} IPv4, {$v6Count} IPv6 records)",
        'meta' => $meta
    ];
}

if (php_sapi_name() === 'cli' && basename(__FILE__) === basename($_SERVER['SCRIPT_FILENAME'])) {
    echo "DB-IP Lite database bijwerken...\n";
    $res = updateGeoIPDatabase();
    echo $res['message'] . "\n";
}
