<?php
namespace App\Controller;
use App\Admin\Entity\StdGeoMap;
use App\Service\StdGeoLocationService;
use App\Service\StdTrackingService;
use App\Utils\Functions;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
class StdGeoLocationController
{
private StdGeoLocationService $geoLocationService;
private StdTrackingService $stdTrackingService;
public function __construct(StdGeoLocationService $geoLocationService, StdTrackingService $stdTrackingService)
{
$this->geoLocationService = $geoLocationService;
$this->stdTrackingService = $stdTrackingService;
}
/**
* Verify if the user's current location matches the session-stored location.
* Returns whether the location is still valid and if an update is needed.
*/
#[Route('/geo-location/verify', methods: ['GET'])]
public function verifyLocation(Request $request): JsonResponse
{
$lon = $request->query->get('lon');
$lat = $request->query->get('lat');
if (!$lon || !$lat) {
return new JsonResponse(['error' => 'Missing parameters: lon and lat'], 400);
}
$sessionLocationIds = $request->getSession()->get('close_location_ids', []);
$sessionCity = $request->getSession()->get('city');
$sessionIsInPortugal = $request->getSession()->get('isInPortugal');
// Get current location based on coordinates
$currentLocation = $this->geoLocationService->getAllLocationsByProximity((float)$lon, (float)$lat, 500);
$currentCity = null;
$currentIsInPortugal = false;
$currentLocationIds = [];
if (!empty($currentLocation['userLocation']) && $currentLocation['userLocation']->getDistrictName() !== 'Fora de Portugal') {
$currentCity = $currentLocation['userLocation']->getMunicipalityName();
$currentIsInPortugal = true;
if (isset($currentLocation['closeLocations']) && is_array($currentLocation['closeLocations'])) {
foreach ($currentLocation['closeLocations'] as $closeLocation) {
if ($closeLocation && method_exists($closeLocation, 'getDomainValue')) {
$currentLocationIds[] = $closeLocation->getDomainValue()->getId();
}
}
}
}
// Check if location has changed
$needsUpdate = false;
$reason = null;
// Compare city
if ($currentCity !== $sessionCity) {
$needsUpdate = true;
$reason = 'city_changed';
}
// Compare Portugal status
if ($currentIsInPortugal !== $sessionIsInPortugal) {
$needsUpdate = true;
$reason = 'country_status_changed';
}
// Compare first location ID (primary location)
if (!empty($currentLocationIds) && !empty($sessionLocationIds)) {
if ($currentLocationIds[0] !== $sessionLocationIds[0]) {
$needsUpdate = true;
$reason = 'primary_location_changed';
}
} elseif (empty($currentLocationIds) !== empty($sessionLocationIds)) {
$needsUpdate = true;
$reason = 'location_availability_changed';
}
return new JsonResponse([
'valid' => !$needsUpdate,
'needs_update' => $needsUpdate,
'reason' => $reason,
'session_city' => $sessionCity,
'current_city' => $currentCity,
'session_is_in_portugal' => $sessionIsInPortugal,
'current_is_in_portugal' => $currentIsInPortugal
]);
}
#[Route('/geo-location/accept', methods: ['GET'])]
public function getLocation(Request $request): JsonResponse
{
$encryptionKey = getenv('ANALYTICS_ENCRYPTION_KEY');
if (!$encryptionKey) {
throw new \RuntimeException("Missing ANALYTICS_ENCRYPTION_KEY");
}
$lon = $request->query->get('lon');
$lat = $request->query->get('lat');
$distance = $request->query->get('distance');
if (!$lon || !$lat) {
return new JsonResponse(['error' => 'Missing parameters: lon and lat'], 400);
}
$distanceThreshold = $distance ? (float)$distance : 0;
if ($distanceThreshold > 100000) {
return new JsonResponse(['error' => 'Distance threshold exceeds the maximum allowed value of 100 km'], 400);
}
$location = $this->geoLocationService->getAllLocationsByProximity((float)$lon, (float)$lat, $distanceThreshold);
if (empty($location['userLocation'])) {
$location['userLocation'] = new StdGeoMap();
$location['userLocation']->setDistrictName('Fora de Portugal');
$location['userLocation']->setMunicipalityName('Fora de Portugal');
}
$this->stdTrackingService->addPreciseLocationToUser(
Functions::encryptSha256($request->getClientIp(), getenv('ANALYTICS_ENCRYPTION_KEY')),
$location['userLocation']->getMunicipalityName(), $location['userLocation']->getDistrictName());
$closeLocationIds = [];
if (isset($location['closeLocations']) && is_array($location['closeLocations'])) {
foreach ($location['closeLocations'] as $closeLocation) {
if ($closeLocation && method_exists($closeLocation, 'getId')) {
$closeLocationIds[] = $closeLocation->getDomainValue()->getId();
}
}
}
if($location['userLocation']->getDistrictName() != 'Fora de Portugal') {
$request->getSession()->set('isInPortugal', true);
$request->getSession()->set('country', 'Portugal');
$request->getSession()->set('city', $location['userLocation']->getMunicipalityName());
$request->getSession()->set('close_location_ids', $closeLocationIds);
} else {
$request->getSession()->set('isInPortugal', false);
}
return new JsonResponse($closeLocationIds);
}
}