<?php
// lib/generate_data.php
// Trigger the bin/generate_data.sh script for a given in-dir job. Requires admin login.
require __DIR__ . '/../auth.php';
mvlog_require_login();

$MVLOG_ROOT = dirname(__DIR__);
header('Content-Type: application/json; charset=utf-8');

$job = $_POST['job'] ?? '';
$max_frames = isset($_POST['max_frames']) ? intval($_POST['max_frames']) : 16;

if (!preg_match('/^[0-9]{8}[-_][A-Za-z0-9._-]+$/', $job)) {
    http_response_code(400);
    echo json_encode(['status'=>'error','message'=>'invalid job']);
    exit;
}

$jobdir = $MVLOG_ROOT . '/in-dir/' . $job;
if (!is_dir($jobdir)) {
    http_response_code(404);
    echo json_encode(['status'=>'error','message'=>'job not found']);
    exit;
}

// Read existing data.txt for Title and Location (case-insensitive aliases)
$data_file = $jobdir . '/data.txt';
$title = '';
$location = '';
if (is_file($data_file)) {
    $lines = file($data_file, FILE_IGNORE_NEW_LINES);
    $i = 0;
    while ($i < count($lines)) {
        $raw = $lines[$i];
        $line = trim($raw);
        if ($line === '' || str_starts_with($line, '#')) { $i++; continue; }
        if (!str_contains($line, ':')) { $i++; continue; }
        [$key, $value] = array_map('trim', explode(':', $line, 2));
        $low = strtolower($key);
        if ($value === '|' && in_array($low, ['description','desc','synopsis'], true)) {
            // Skip indented block
            $i++;
            while ($i < count($lines)) {
                $next = $lines[$i];
                if (trim($next) !== '' && $next[0] !== ' ' && $next[0] !== "\t") break;
                $i++;
            }
            continue;
        }
        if (in_array($low, ['title','name'], true) && $title === '') $title = $value;
        if (in_array($low, ['place','location','where'], true) && $location === '') $location = $value;
        $i++;
    }
}

// If no location in data.txt, attempt to extract GPS from media files and reverse-geocode with Nominatim.
if ($location === '') {
    $ffprobe = file_exists($MVLOG_ROOT . '/ffmpeg/ffprobe') ? $MVLOG_ROOT . '/ffmpeg/ffprobe' : trim((string)shell_exec('command -v ffprobe 2>/dev/null'));
    if ($ffprobe) {
        $candidates = array_values(array_filter(scandir($jobdir), function($f) use ($jobdir) { return is_file($jobdir . '/' . $f); }));
        usort($candidates, 'strnatcasecmp');
        $last_country = '';
        $exts = ['jpg','jpeg','png','webp','gif','mp4','mov','m4v','webm','mkv'];
        foreach ($candidates as $f) {
            $ext = strtolower(pathinfo($f, PATHINFO_EXTENSION));
            if (!in_array($ext, $exts, true)) continue;
            $path = $jobdir . '/' . $f;
            $cmd = escapeshellcmd($ffprobe) . ' -v error -show_format -show_streams -of json ' . escapeshellarg($path) . ' 2>/dev/null';
            $out = @shell_exec($cmd);
            if (!$out) continue;
            $json = json_decode($out, true);
            if (!is_array($json)) continue;

            $values = [];
            $collect = function($obj) use (&$collect, &$values) {
                if (is_array($obj)) {
                    foreach ($obj as $k => $v) {
                        if (is_string($k) && (stripos($k, 'location') !== false || stripos($k, 'gps') !== false)) {
                            if (is_string($v)) $values[] = $v;
                        }
                        $collect($v);
                    }
                }
            };
            $collect($json);
            if (empty($values)) continue;

            foreach ($values as $val) {
                $lat = $lon = null;
                if (preg_match('/([+\\-]\d+(?:\\.\\d+)?)([+\\-]\d+(?:\\.\\d+)?)/', $val, $m)) {
                    $lat = floatval($m[1]); $lon = floatval($m[2]);
                } elseif (preg_match('/([+\\-]?\\d+(?:\\.\\d+)?)[,;\\s]+([+\\-]?\\d+(?:\\.\\d+)?)/', $val, $m)) {
                    $lat = floatval($m[1]); $lon = floatval($m[2]);
                } else {
                    continue;
                }

                for ($zoom = 18; $zoom >= 3; $zoom--) {
                    $query = http_build_query([
                        'format' => 'jsonv2',
                        'lat' => sprintf('%.8f', $lat),
                        'lon' => sprintf('%.8f', $lon),
                        'zoom' => $zoom,
                        'addressdetails' => 1,
                    ]);
                    $opts = ['http' => ['header' => "User-Agent: movmaker/1.0 (reverse geocoding for local movie metadata)\r\n", 'timeout' => 10]];
                    $ctx = stream_context_create($opts);
                    $url = 'https://nominatim.openstreetmap.org/reverse?' . $query;
                    $resp = @file_get_contents($url, false, $ctx);
                    if (!$resp) continue;
                    $obj = json_decode($resp, true);
                    if (!is_array($obj) || !isset($obj['address'])) continue;
                    $address = $obj['address'];
                    $country = $address['country'] ?? '';
                    $last_country = $country ?: $last_country;
                    $city = '';
                    foreach (['city','town','village'] as $k) { if (!empty($address[$k])) { $city = $address[$k]; break; } }
                    if ($city) {
                        $location = trim($city . ($country ? ', ' . $country : ''));
                        break 3;
                    }
                }
            }
        }
        if ($location === '') $location = $last_country ?: '';
    }
}

$script = $MVLOG_ROOT . '/bin/generate_data.sh';
if (!is_file($script)) {
    http_response_code(500);
    echo json_encode(['status' => 'error', 'message' => 'generate_data.sh not found']);
    exit;
}

$log = $jobdir . '/generate_data.log';
$bash = '/bin/bash';
$cmd = escapeshellcmd($bash) . ' ' . escapeshellarg($script) . ' ' . escapeshellarg($jobdir) . ' ' . escapeshellarg($title) . ' ' . escapeshellarg($location) . ' ' . escapeshellarg((string)$max_frames) . ' >> ' . escapeshellarg($log) . ' 2>&1 & echo $!';

$pid = trim(@shell_exec($cmd));

echo json_encode(['status' => 'ok', 'pid' => $pid, 'log' => $log, 'message' => 'started']);
exit;
