<?php
require __DIR__ . '/bootstrap.php';

use App\Core\Auth;
use App\Core\Csrf;
use App\Core\Database;
use App\Core\Response;
use App\Services\UploadService;
use App\Services\PhotoVotingService;

$pdo = Database::connection();
$input = request_input();
$svc = new PhotoVotingService();


function pyrk_photo_float_in_range(mixed $value, float $min, float $max): ?float
{
    if ($value === null || $value === '') return null;
    $value = str_replace(',', '.', (string)$value);
    if (!is_numeric($value)) return null;
    $float = (float)$value;
    return ($float >= $min && $float <= $max) ? round($float, 7) : null;
}

function pyrk_photo_location_from_input(array $input, array $stored): array
{
    $lat = pyrk_photo_float_in_range($input['photo_latitude'] ?? null, -90, 90);
    $lng = pyrk_photo_float_in_range($input['photo_longitude'] ?? null, -180, 180);

    if ($lat !== null && $lng !== null) {
        $accuracy = pyrk_photo_float_in_range($input['photo_location_accuracy'] ?? null, 0, 100000);
        $source = preg_replace('/[^a-z0-9_ -]/i', '', (string)($input['photo_location_source'] ?? 'browser_geolocation')) ?: 'browser_geolocation';
        $capturedAt = trim((string)($input['photo_location_captured_at'] ?? ''));
        return [
            'latitude' => $lat,
            'longitude' => $lng,
            'accuracy' => $accuracy,
            'source' => substr(str_replace(' ', '_', strtolower($source)), 0, 40),
            'captured_at' => $capturedAt,
        ];
    }

    $gps = $stored['gps'] ?? [];
    if (is_array($gps) && isset($gps['latitude'], $gps['longitude'])) {
        return $gps;
    }

    return [];
}


if ($_SERVER['REQUEST_METHOD'] === 'GET') {
    // Contest privacy changes must be visible immediately; never reuse a stale gallery response.
    header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
    header('Pragma: no-cache');

    $walkId = (int)($input['walk_id'] ?? 0);
    if ($walkId <= 0) Response::error('walk_id is required.');

    $settings = $svc->contestSettings($walkId);
    $showOwnerName = (int)($settings['show_photo_owner_name'] ?? 0) === 1;

    $stmt = $pdo->prepare('SELECT p.id, p.walk_id, p.title, p.caption, p.file_path, p.thumbnail_path, p.status, p.votes_count, p.uploaded_at,
                                  u.full_name AS owner_name, u.profile_photo_path AS owner_avatar
                           FROM walk_photos p
                           JOIN users u ON u.id = p.user_id
                           WHERE p.walk_id = ? AND p.status IN ("approved", "winner")
                           ORDER BY p.status = "winner" DESC, p.votes_count DESC, p.uploaded_at DESC');
    $stmt->execute([$walkId]);
    $photos = $stmt->fetchAll(PDO::FETCH_ASSOC);

    foreach ($photos as $idx => &$photo) {
        $photo['anonymous_label'] = 'Photo #' . ($idx + 1);
        $photo['owner_name_visible'] = $showOwnerName ? 1 : 0;

        if ($showOwnerName) {
            $photo['uploaded_by'] = $photo['owner_name'] ?: 'Member';
            $photo['uploaded_avatar'] = $photo['owner_avatar'] ?: '';
        } else {
            // Public/member gallery is anonymous for objective voting.
            // Do NOT expose owner identity when masking is enabled.
            $photo['uploaded_by'] = 'Anonymous participant';
            $photo['uploaded_avatar'] = '';
        }

        unset($photo['owner_name'], $photo['owner_avatar']);
    }
    unset($photo);

    $user = Auth::user();
    $voteMeta = $user ? $svc->userCanVoteMeta($walkId, (int)$user['id']) : ['can_vote' => false, 'reason' => 'Login required to vote.', 'settings' => $settings];

    $myVotes = [];
    if ($user) {
        $voteStmt = $pdo->prepare('SELECT photo_id FROM photo_votes WHERE walk_id = ? AND user_id = ?');
        $voteStmt->execute([$walkId, (int)$user['id']]);
        $myVotes = array_map('intval', array_column($voteStmt->fetchAll(PDO::FETCH_ASSOC), 'photo_id'));
    }

    Response::ok([
        'photos' => $photos,
        'contest' => $voteMeta['settings'],
        'can_vote' => (bool)$voteMeta['can_vote'],
        'vote_reason' => $voteMeta['reason'],
        'my_votes' => $myVotes,
        'upload_policy' => $user ? $svc->uploadPolicy($walkId, (int)$user['id']) : null,
    ]);
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $user = Auth::requireUser();
    Csrf::validateFromRequest();
    if (empty($_POST['walk_id'])) Response::error('walk_id is required.');
    if (empty($_FILES['photo'])) Response::error('Photo file is required.');

    $walkId = (int)$_POST['walk_id'];
    $userId = (int)$user['id'];
    $replacePhotoId = (int)($_POST['replace_photo_id'] ?? 0);
    $replaceExisting = !empty($_POST['replace_existing']);

    try {
        $policy = $svc->uploadPolicy($walkId, $userId);
        if (!empty($policy['limit_reached']) && !$replaceExisting) {
            Response::error(
                'This walk allows ' . (int)$policy['max_photos_per_participant'] . ' photo' . ((int)$policy['max_photos_per_participant'] === 1 ? '' : 's') . ' per participant. Please confirm if you want to replace your existing photo.',
                409,
                ['code' => 'photo_limit_reached', 'data' => ['upload_policy' => $policy]]
            );
        }

        if ($replaceExisting && $replacePhotoId <= 0) {
            $existing = $policy['existing_photos'] ?? [];
            if (count($existing) === 1) {
                $replacePhotoId = (int)($existing[0]['id'] ?? 0);
            }
        }

        $uploadService = new UploadService();
        $stored = $uploadService->storePhoto($_FILES['photo']);
        try {
            $location = pyrk_photo_location_from_input($input, $stored);
            $id = $svc->registerPhoto($walkId, $userId, trim($_POST['title'] ?? 'Walk photo'), trim($_POST['caption'] ?? ''), $stored, $location, $replaceExisting ? $replacePhotoId : null);
            $newPolicy = $svc->uploadPolicy($walkId, $userId);
            Response::ok([
                'photo_id' => $id,
                'upload_policy' => $newPolicy,
                'replaced_photo' => $replaceExisting ? 1 : 0,
                'location_saved' => !empty($location),
                'map_url' => !empty($location) ? ('https://www.google.com/maps?q=' . rawurlencode((string)$location['latitude'] . ',' . (string)$location['longitude'])) : '',
            ], $replaceExisting ? 'Photo replaced successfully. The new photo will appear after admin approval.' : (!empty($location) ? 'Photo registered with location. It will appear after admin approval.' : 'Photo registered. It will appear after admin approval.'));
        } catch (Throwable $e) {
            $uploadService->deleteStoredPhoto($stored);
            throw $e;
        }
    } catch (Throwable $e) {
        Response::error($e->getMessage());
    }
}

Response::error('Unsupported photos action.', 404);
