<?php
// Arr (Sonarr / Radarr / Lidarr) data helpers

require_once __DIR__ . '/config.php';

// ── Conf helpers ──────────────────────────────────────────────────────────────

function vv_arr_scalar(string $raw, string $key): string {
    return preg_match('/^\s*' . preg_quote($key, '/') . '\s*=\s*"?([^"\n]*)"?/m', $raw, $m)
        ? trim($m[1]) : '';
}

// Returns all configured hosts found in master.conf as ['host1'=>'hostname', ...]
// Returns ['host1' => 'hostname', 'host2' => 'hostname', ...] from master.conf.
// Matches both HOST1="name" and HOST1_NAME="name" (either convention).
function vv_arr_known_hosts(): array {
    $vars  = vv_conf_vars();   // already parses HOST1="val" correctly
    $hosts = [];
    foreach ($vars as $k => $v) {
        if (preg_match('/^HOST(\d+)$/', $k, $m) && $v !== '') {
            $hosts['host' . $m[1]] = $v;
        }
    }
    ksort($hosts);
    return $hosts ?: ['host1' => 'HOST1'];
}

function vv_arr_node_names(): array {
    return array_map(fn($name) => $name, vv_arr_known_hosts());
}

// ── Discovery ─────────────────────────────────────────────────────────────────

function vv_discover_arrs(): array {
    $nodes = [];
    $defs  = [
        'sonarr' => ['SONARR_URL', 'SONARR_API_KEY', 'SONARR_TV_ROOT',     'v3'],
        'radarr' => ['RADARR_URL', 'RADARR_API_KEY', 'RADARR_MOVIES_ROOT', 'v3'],
        'lidarr' => ['LIDARR_URL', 'LIDARR_API_KEY', 'LIDARR_MUSIC_ROOT',  'v1'],
    ];
    foreach (array_keys(vv_arr_known_hosts()) as $h) {
        $raw = vv_read_conf_raw($h . '.conf');
        if (!$raw) continue;
        $pfx  = strtoupper($h) . '_';
        $get  = fn($k) => vv_arr_scalar($raw, $pfx . $k);
        $arrs = [];
        foreach ($defs as $type => [$uk, $ak, $rk, $api]) {
            $url = $get($uk);
            $key = $get($ak);
            if ($url && $key && !str_contains($key, 'your-')) {
                $arrs[] = ['type' => $type, 'url' => $url, 'key' => $key,
                           'root' => $get($rk), 'api' => $api];
            }
        }
        if ($arrs) $nodes[] = ['host' => $h, 'arrs' => $arrs];
    }
    return $nodes;
}

// ── HTTP ──────────────────────────────────────────────────────────────────────

function vv_arr_http(string $url, string $apiKey, string $path, int $timeout = 4): ?array {
    $ctx = stream_context_create(['http' => [
        'timeout'       => $timeout,
        'header'        => "X-Api-Key: $apiKey\r\nAccept: application/json\r\n",
        'ignore_errors' => true,
    ]]);
    $raw = @file_get_contents(rtrim($url, '/') . $path, false, $ctx);
    return $raw ? (json_decode($raw, true) ?: null) : null;
}

// ── Live arr data ─────────────────────────────────────────────────────────────

function vv_fetch_arr_live(array $arr): array {
    $url  = $arr['url'];
    $key  = $arr['key'];
    $base = '/api/' . $arr['api'];
    $type = $arr['type'];

    $out = ['online' => false, 'version' => null, 'health' => [],
            'queue'  => ['dl' => 0, 'warn' => 0, 'err' => 0], 'disk' => []];

    $sys = vv_arr_http($url, $key, "$base/system/status");
    if (!$sys) return $out;
    $out['online']  = true;
    $out['version'] = $sys['version'] ?? null;

    if ($type === 'sonarr') {
        $data = vv_arr_http($url, $key, "$base/series");
        if (is_array($data)) {
            $out['total']     = count($data);
            $out['monitored'] = count(array_filter($data, fn($x) => !empty($x['monitored'])));
            $out['episodes']  = array_sum(array_column($data, 'episodeFileCount'));
        }
    } elseif ($type === 'radarr') {
        $data = vv_arr_http($url, $key, "$base/movie");
        if (is_array($data)) {
            $out['total']     = count($data);
            $out['monitored'] = count(array_filter($data, fn($x) => !empty($x['monitored'])));
            $out['files']     = count(array_filter($data, fn($x) => !empty($x['hasFile'])));
        }
    } elseif ($type === 'lidarr') {
        $data = vv_arr_http($url, $key, "$base/artist");
        if (is_array($data)) {
            $out['total']     = count($data);
            $out['monitored'] = count(array_filter($data, fn($x) => !empty($x['monitored'])));
            $out['albums']    = array_sum(array_map(
                fn($a) => $a['statistics']['albumCount'] ?? $a['albumCount'] ?? 0, $data));
        }
    }

    $q = vv_arr_http($url, $key, "$base/queue?page=1&pageSize=500");
    if (is_array($q)) {
        foreach (($q['records'] ?? $q) as $r) {
            if (!is_array($r)) continue;
            $s   = $r['status'] ?? '';
            $tds = strtolower($r['trackedDownloadStatus'] ?? '');
            $tst = strtolower($r['trackedDownloadState']  ?? '');
            if ($s === 'downloading')                           $out['queue']['dl']++;
            if ($tds === 'warning' || $tst === 'downloadingstalled') $out['queue']['warn']++;
            if ($tds === 'error')                               $out['queue']['err']++;
        }
    }

    $h = vv_arr_http($url, $key, "$base/health");
    if (is_array($h)) $out['health'] = $h;

    $d = vv_arr_http($url, $key, "$base/diskspace");
    if (is_array($d)) $out['disk'] = $d;

    return $out;
}

// ── Log stats ─────────────────────────────────────────────────────────────────

function vv_arr_cleanup_stats(string $type): array {
    $slugs = ['sonarr' => 'Media/sonarr_cleanup',
              'radarr' => 'Media/radarr_cleanup',
              'lidarr' => 'Media/lidarr_cleanup'];
    $base = LOG_DIR . '/' . ($slugs[$type] ?? '');
    $out  = ['last_run' => null, 'end' => null, 'status' => null,
             'tracked'  => null, 'total' => null,
             'orphans'  => 0,    'orphans_sz' => '0B', 'junk' => 0];

    $jf = $base . '.json';
    if (!file_exists($jf)) return $out;
    $meta = json_decode(file_get_contents($jf), true) ?: [];
    $out['last_run'] = $meta['start']  ?? null;
    $out['end']      = $meta['end']    ?? null;
    $out['status']   = $meta['status'] ?? null;

    $lf = $base . '.log';
    if (!file_exists($lf)) return $out;
    $log   = file_get_contents($lf);
    $parts = preg_split('/━{3,}[^\n]*SUMMARY[^\n]*/u', $log);
    $blk   = count($parts) > 1 ? end($parts) : $log;

    if (preg_match('/Tracked:\s*([\d,]+)\s*files\s*\(([\d,]+)/u', $blk, $m)) {
        $out['tracked'] = (int)str_replace(',', '', $m[1]);
        $out['total']   = (int)str_replace(',', '', $m[2]);
    }
    if (preg_match('/Orphans:\s*([\d,]+)\s*files\s*\(([^)]+)\)/u', $blk, $m)) {
        $out['orphans']    = (int)str_replace(',', '', $m[1]);
        $out['orphans_sz'] = trim($m[2]);
    }
    if (preg_match('/Junk:\s*([\d,]+)\s*files/u', $blk, $m)) {
        $out['junk'] = (int)str_replace(',', '', $m[1]);
    }
    return $out;
}

function vv_arr_discovery_stats(string $type): array {
    $slugs = ['sonarr' => 'Media/playback_aware_sonarr_discovery',
              'radarr' => 'Media/playback_aware_radarr_discovery',
              'lidarr' => 'Media/playback_aware_lidarr_discovery'];
    $base = LOG_DIR . '/' . ($slugs[$type] ?? '');
    $out  = ['last_run' => null, 'status' => null, 'added' => null];

    $jf = $base . '.json';
    if (!file_exists($jf)) return $out;
    $meta = json_decode(file_get_contents($jf), true) ?: [];
    $out['last_run'] = $meta['start']  ?? null;
    $out['status']   = $meta['status'] ?? null;

    $lf = $base . '.log';
    if (file_exists($lf)) {
        $log = file_get_contents($lf);
        if (preg_match('/Added[:\s]+(\d+)/i', $log, $m)) $out['added'] = (int)$m[1];
        elseif (preg_match('/(\d+)\s+added/i', $log, $m)) $out['added'] = (int)$m[1];
    }
    return $out;
}

function vv_arr_sync_stats(): array {
    $base = LOG_DIR . '/Media/arr_sync';
    $out  = ['last_run' => null, 'status' => null, 'added' => null,
             'nodes'    => null, 'blocklist_count' => null];

    $jf = $base . '.json';
    if (file_exists($jf)) {
        $meta = json_decode(file_get_contents($jf), true) ?: [];
        $out['last_run'] = $meta['start']  ?? null;
        $out['status']   = $meta['status'] ?? null;
    }

    $master = vv_read_conf_raw('master.conf');
    if (preg_match('/ARR_SYNC_BLOCKLIST\s*=\s*"?([^"\n#]+)"?/m', $master, $m)) {
        $blPath = trim($m[1]);
        if (file_exists($blPath)) {
            $out['blocklist_count'] = count(array_filter(
                file($blPath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)));
        }
    }

    $lf = $base . '.log';
    if (file_exists($lf)) {
        $log = file_get_contents($lf);
        if (preg_match('/Total added[:\s]+(\d+)/i', $log, $m)) $out['added'] = (int)$m[1];
        if (preg_match('/Nodes?[:\s]+(\d+)/i',      $log, $m)) $out['nodes'] = (int)$m[1];
    }
    return $out;
}

function vv_arr_recovery_stats(): array {
    $base = LOG_DIR . '/Media/arrs_failed_stalled_recovery';
    $out  = ['last_run' => null, 'status' => null, 'fixed' => 0, 'searched' => 0];

    $jf = $base . '.json';
    if (!file_exists($jf)) return $out;
    $meta = json_decode(file_get_contents($jf), true) ?: [];
    $out['last_run'] = $meta['start']  ?? null;
    $out['status']   = $meta['status'] ?? null;

    $lf = $base . '.log';
    if (file_exists($lf)) {
        $log = file_get_contents($lf);
        if (preg_match('/Removed[:\s]+(\d+)/i',   $log, $m)) $out['fixed']    = (int)$m[1];
        if (preg_match('/Re-searched[:\s]+(\d+)/i',$log, $m)) $out['searched'] = (int)$m[1];
    }
    return $out;
}

// ── Entry point ───────────────────────────────────────────────────────────────

function vv_arrs_all(): array {
    $currentHost = vv_detect_host();
    $names       = vv_arr_node_names();
    $allNodes    = vv_discover_arrs();
    $result      = [];

    foreach ($allNodes as $node) {
        $h       = $node['host'];
        $isLocal = ($h === $currentHost || $currentHost === 'unknown');
        $nodeOut = ['host' => $h, 'name' => $names[$h] ?? strtoupper($h), 'local' => $isLocal, 'arrs' => []];

        foreach ($node['arrs'] as $arr) {
            $entry = ['type' => $arr['type'], 'root' => $arr['root']];
            if ($isLocal) {
                $entry = array_merge($entry, vv_fetch_arr_live($arr));
                $entry['cleanup']   = vv_arr_cleanup_stats($arr['type']);
                $entry['discovery'] = vv_arr_discovery_stats($arr['type']);
            } else {
                $entry['online'] = false;
                $entry['remote'] = true;
            }
            $nodeOut['arrs'][] = $entry;
        }
        $result[] = $nodeOut;
    }

    return [
        'nodes'    => $result,
        'sync'     => vv_arr_sync_stats(),
        'recovery' => vv_arr_recovery_stats(),
        'host'     => $currentHost,
        'ts'       => time(),
    ];
}
