src/Controller/PublicApiController.php line 50

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\C2IntegrationBundle\Service\C2Service;
  4. use Carbon\Carbon;
  5. use Knp\Snappy\Pdf;
  6. use Knp\Snappy\Image;
  7. use Pimcore\Model\Asset;
  8. use App\Service\RedisCache;
  9. use App\Model\ReportLogModel;
  10. use App\Service\EmailService;
  11. use App\Service\ReportService;
  12. use DateTime;
  13. use Pimcore\Log\ApplicationLogger;
  14. use App\Model\EwsNotificationModel;
  15. use App\Service\NotificationService;
  16. use Pimcore\Model\DataObject\Report;
  17. use App\Service\MeteomaticApiService;
  18. use App\Model\WeatherForecastCityModel;
  19. use PhpOffice\PhpSpreadsheet\Spreadsheet;
  20. use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
  21. use App\Service\CustomNotificationService;
  22. use App\Service\MeteomaticsWeatherService;
  23. use Pimcore\Controller\FrontendController;
  24. use Knp\Component\Pager\PaginatorInterface;
  25. use App\Service\PublicUserPermissionService;
  26. use App\Service\NCMWeatherAPIService;
  27. use GuzzleHttp\Client;
  28. use App\Model\ReportingPortalModel;
  29. use Symfony\Component\HttpFoundation\Request;
  30. use Symfony\Component\HttpFoundation\Response;
  31. use Symfony\Component\Routing\Annotation\Route;
  32. use Pimcore\Model\DataObject\ReportWeatherSymbols;
  33. use Symfony\Component\HttpFoundation\JsonResponse;
  34. use Symfony\Contracts\Translation\TranslatorInterface;
  35. use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
  36. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  37. use Symfony\Component\Templating\EngineInterface;
  38. use App\Service\InsuranceIndustryService;
  39. use App\Model\WeatherStationModel;
  40. use App\Service\WeatherStationService;
  41. use Pimcore\Model\DataObject\HistoricalDataParameters;
  42. use App\Model\AgricultureModel;
  43. use App\Service\ChillUnitService;
  44. use Pimcore\Model\DataObject;
  45. use App\Model\LocationModel;
  46. use App\Model\WeatherParameterModel;
  47. use Pimcore\Model\DataObject\WeatherParameterLocationTags;
  48. class PublicApiController extends FrontendController
  49. {
  50.     private $ewsNotificationModel;
  51.     private $reportModel;
  52.     private $c2Service;
  53.     private $reportingPortalModel;
  54.     private $weatherStationModel;
  55.     private $agricultureModel;
  56.     private $chillUnitService;
  57.     private $locationModel;
  58.     private $weatherParameterModel;
  59.     public function __construct(
  60.         private TokenStorageInterface $tokenStorageInterface,
  61.         private JWTTokenManagerInterface $jwtManager,
  62.         private PublicUserPermissionService $publicUserPermissionService,
  63.         protected TranslatorInterface $translator,
  64.         private ApplicationLogger $logger,
  65.         private MeteomaticApiService $meteomaticApiService,
  66.         private \Doctrine\DBAL\Connection $connection,
  67.         private RedisCache $redisCache,
  68.         private MeteomaticsWeatherService $meteomaticsWeatherService,
  69.         private Pdf $snappy,
  70.         private CustomNotificationService $customNotificationService,
  71.         private ReportService $reportService,
  72.         private NotificationService $notificationService,
  73.         private Image $snappyImage,
  74.         private EmailService $emailService,
  75.         private EngineInterface $templating,
  76.         private NCMWeatherAPIService $ncmWeatherApiService,
  77.         private InsuranceIndustryService $insuranceIndustryService,
  78.         private WeatherStationService $weatherStationService,
  79.     ) {
  80.         header('Content-Type: application/json; charset=UTF-8');
  81.         header("Access-Control-Allow-Origin: *");
  82.         $this->meteomaticApiService $meteomaticApiService;
  83.         $this->publicUserPermissionService $publicUserPermissionService;
  84.         $this->ewsNotificationModel = new EwsNotificationModel();
  85.         $this->reportModel = new ReportLogModel();
  86.         $this->c2Service = new C2Service();
  87.         $this->templating =  $templating;
  88.         $this->reportingPortalModel = new ReportingPortalModel();
  89.         $this->weatherStationModel = new WeatherStationModel();
  90.         $this->agricultureModel = new AgricultureModel();
  91.         $this->chillUnitService = new ChillUnitService();
  92.         $this->locationModel = new LocationModel();
  93.         $this->weatherParameterModel = new WeatherParameterModel();
  94.     }
  95.     /**
  96.      * @Route("/api/public/{startdate}/{enddate}/{resolution}/{parameter}/{coordinate}/{format}", name="api_public_route_query", methods={"GET"})
  97.      */
  98.     public function publicRouteQueryData(Request $request): JsonResponse
  99.     {
  100.         try {
  101.             // check user credentials and expiry
  102.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  103.             if ($response['success'] !== true) {
  104.                 return $this->json($response);
  105.             }
  106.             $startDate $request->get('startdate');
  107.             $endDate $request->get('enddate');
  108.             $resolution $request->get('resolution');
  109.             $parameter $request->get('parameter');
  110.             $coordinate $request->get('coordinate');
  111.             $format $request->get('format');
  112.             // Optional Parameter
  113.             $source $request->get('source');
  114.             $onInvalid $request->get('on_invalid');
  115.             $model $request->get('model');
  116.             if (!$startDate) {
  117.                 throw new \InvalidArgumentException("Missing mandatory parameter: start date");
  118.             }
  119.             if (!$endDate) {
  120.                 throw new \InvalidArgumentException("Missing mandatory parameter: end date");
  121.             }
  122.             if (!$resolution) {
  123.                 throw new \InvalidArgumentException("Missing mandatory parameter: resolution");
  124.             }
  125.             if (!$parameter) {
  126.                 throw new \InvalidArgumentException("Missing mandatory parameter: parameters");
  127.             }
  128.             if (!$coordinate) {
  129.                 throw new \InvalidArgumentException("Missing mandatory parameter: coordinate");
  130.             }
  131.             if (!$format) {
  132.                 throw new \InvalidArgumentException("Missing mandatory parameter: format");
  133.             }
  134.             $startDate = new DateTime($startDate);
  135.             $endDate = new DateTime($endDate);
  136.             $user $response['user'];
  137.             $parametersArray explode(','$parameter);
  138.             // Varify user allowed permissions
  139.             // $reslult = $this->publicUserPermissionService->publicUserPermissionCheck($user, $parametersArray, $this->translator);
  140.             // if ($reslult['success'] !== true) {
  141.             //     return $this->json($reslult);
  142.             // }
  143.             $response $this->meteomaticApiService->publicRouteQuery(
  144.                 $startDate,
  145.                 $endDate,
  146.                 $resolution,
  147.                 $parametersArray,
  148.                 $coordinate,
  149.                 $format,
  150.                 $model,
  151.                 $source,
  152.                 $onInvalid
  153.             );
  154.             // For demonstration purposes, we will just return a JSON response
  155.             return $this->json($response);
  156.         } catch (\Exception $ex) {
  157.             $this->logger->error($ex->getMessage());
  158.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  159.         }
  160.     }
  161.     /**
  162.      * @Route("/api/public/cfo-report", name="public_cfo_report", methods={"POST"})
  163.      */
  164.     public function getCfoReport(Request $request): JsonResponse
  165.     {
  166.         try {
  167.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  168.             if ($permissions['success'] !== true) {
  169.                 return $this->json($permissions);
  170.             }
  171.             $params json_decode($request->getContent(), true) ?: [];
  172.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  173.             $reportType '10-day-forecast-report';
  174.             // Pull raw airport/station forecast (weatherinfo) for first 6 days
  175.             $ccode $params['ccode'] ?? null;
  176.             $baseUrl rtrim(NCM_WEATHER_API_URL'/');
  177.             $url $baseUrl '/api/weather/getweatherinfo';
  178.             $client = new Client(['verify' => false]);
  179.             $options = [];
  180.             if ($ccode !== null && $ccode !== '') {
  181.                 $options['query'] = ['ccode' => $ccode];
  182.             }
  183.             $wxRes $client->request('GET'$url$options);
  184.             $wxBody $wxRes->getBody()->getContents();
  185.             $wxData json_decode($wxBodytrue);
  186.             // Normalize weatherinfo items array
  187.             $wxItems = [];
  188.             if (is_array($wxData)) {
  189.                 $wxItems = isset($wxData[0]) ? $wxData : [$wxData];
  190.             }
  191.             // Index weatherinfo by Arabic and English city names (normalized with synonyms)
  192.             $wxByCityAr = [];
  193.             $wxByCityEn = [];
  194.             $norm = function ($v) {
  195.                 return $v !== null trim(mb_strtolower((string)$v)) : null;
  196.             };
  197.             $normAr = function ($v) use ($norm) {
  198.                 $s $norm($v);
  199.                 if ($s === null) { return null; }
  200.                 // strip common prefixes
  201.                 $s preg_replace('/^(مدينة|محافظة)\s+/u'''$s);
  202.                 // normalize spaces
  203.                 $s preg_replace('/\s+/u'' '$s);
  204.                 return trim($s);
  205.             };
  206.             $normEn = function ($v) use ($norm) {
  207.                 $s $norm($v);
  208.                 if ($s === null) { return null; }
  209.                 // remove Arabic article transliterations anywhere: al, ar, ad, as, at
  210.                 $s preg_replace('/\b(al|ar|ad|as|at)\s+/u'''$s);
  211.                 $s str_replace(['-''_'], ' '$s);
  212.                 $s preg_replace('/\s+/u'' '$s);
  213.                 return trim($s);
  214.             };
  215.             foreach ($wxItems as $it) {
  216.                 if (!is_array($it)) { continue; }
  217.                 $ar $normAr($it['city_Ar'] ?? null);
  218.                 $en $normEn($it['city_En'] ?? null);
  219.                 if ($ar) { $wxByCityAr[$ar] = $it; }
  220.                 if ($en) { $wxByCityEn[$en] = $it; }
  221.             }
  222.             // Latest 10-day report (full jsonData kept for fallback and for last 4 days)
  223.             $latest $this->reportingPortalModel->getLatestReport([
  224.                 'reportType' => $reportType
  225.             ]);
  226.             if (!is_array($latest) || !isset($latest['success']) || $latest['success'] !== true || !isset($latest['data'])) {
  227.                 return $this->json(['success' => false'message' => 'Failed to fetch latest report']);
  228.             }
  229.             $latestData $latest['data'];
  230.             $jsonDataFull = isset($latestData['jsonData']) && is_array($latestData['jsonData']) ? $latestData['jsonData'] : [];
  231.             if (empty($jsonDataFull)) {
  232.                 return $this->json(['success' => false'message' => 'Empty jsonData in latest report']);
  233.             }
  234.             // Helpers to extract first 6 days from weatherinfo
  235.             $dayKeys = [
  236.                 ['date' => 'todayDate',   'max' => 'todayMaxTemperature',   'min' => 'todayMinTemperature',   'hum' => 'humidity',            'icon' => 'todayIcon'],
  237.                 ['date' => 'firstDate',   'max' => 'firstdayMaxTemperature','min' => 'firstdayMinTemperature','hum' => 'firstdayHumidity',    'icon' => 'firstdayIcon'],
  238.                 ['date' => 'secondDate',  'max' => 'seconddayMaxTemperature','min' => 'seconddayMinTemperature','hum' => 'seconddayHumidity''icon' => 'seconddayIcon'],
  239.                 ['date' => 'thirdDate',   'max' => 'thirddayMaxTemperature','min' => 'thirddayMinTemperature','hum' => 'thirddayHumidity',    'icon' => 'thirddayIcon'],
  240.                 ['date' => 'fourthDate',  'max' => 'fourthdayMaxTemperature','min' => 'fourthdayMinTemperature','hum' => 'fourthdayHumidity''icon' => 'fourthdayIcon'],
  241.                 ['date' => 'fifthDate',   'max' => 'fifthdayMaxTemperature','min' => 'fifthdayMinTemperature','hum' => 'fifthdayHumidity',    'icon' => 'fifthdayIcon'],
  242.             ];
  243.             $toIso = function ($s) {
  244.                 if (!$s) { return null; }
  245.                 try {
  246.                     $dt = new \DateTime($s);
  247.                     return $dt->format('Y-m-d\TH:i:s\Z');
  248.                 } catch (\Throwable $e) {
  249.                     return null;
  250.                 }
  251.             };
  252.             $extractIconIdx = function ($iconStr) {
  253.                 if (!is_string($iconStr) || $iconStr === '') { return null; }
  254.                 if (preg_match('/wt_([0-9]+)/'$iconStr$m)) {
  255.                     return (int)$m[1];
  256.                 }
  257.                 return null;
  258.             };
  259.             $first6FromWx = function (array $wxItemstring $param) use ($toIso$extractIconIdx) {
  260.                 $getNum = function ($v) {
  261.                     if ($v === null) { return null; }
  262.                     if (is_string($v)) { $v trim($v); }
  263.                     return is_numeric($v) ? (float)$v null;
  264.                 };
  265.                 $rows = [];
  266.                 // Today (always use today* keys)
  267.                 $date $toIso($wxItem['todayDate'] ?? null);
  268.                 if ($date) {
  269.                     $value null;
  270.                     if ($param === 't_max_2m_24h:C') {
  271.                         $value $getNum($wxItem['todayMaxTemperature'] ?? null);
  272.                     } elseif ($param === 't_min_2m_24h:C') {
  273.                         $value $getNum($wxItem['todayMinTemperature'] ?? null);
  274.                     } elseif ($param === 'relative_humidity_2m:p') {
  275.                         $value $getNum($wxItem['humidity'] ?? null);
  276.                     } elseif ($param === 'weather_symbol_24h:idx') {
  277.                         $value $extractIconIdx($wxItem['todayIcon'] ?? null);
  278.                     }
  279.                     $rows[] = ['date' => $date'value' => $value'weatherinfo' => true];
  280.                 }
  281.                 // Next 5 days (first..fifth)
  282.                 $map = [
  283.                     ['date' => 'firstDate',  'max' => 'firstdayMaxTemperature',  'min' => 'firstdayMinTemperature',  'hum' => 'firstdayHumidity',  'icon' => 'firstdayIcon'],
  284.                     ['date' => 'secondDate''max' => 'seconddayMaxTemperature''min' => 'seconddayMinTemperature''hum' => 'seconddayHumidity''icon' => 'seconddayIcon'],
  285.                     ['date' => 'thirdDate',  'max' => 'thirddayMaxTemperature',  'min' => 'thirddayMinTemperature',  'hum' => 'thirddayHumidity',  'icon' => 'thirddayIcon'],
  286.                     ['date' => 'fourthDate''max' => 'fourthdayMaxTemperature''min' => 'fourthdayMinTemperature''hum' => 'fourthdayHumidity''icon' => 'fourthdayIcon'],
  287.                     ['date' => 'fifthDate',  'max' => 'fifthdayMaxTemperature',  'min' => 'fifthdayMinTemperature',  'hum' => 'fifthdayHumidity',  'icon' => 'fifthdayIcon'],
  288.                 ];
  289.                 foreach ($map as $dk) {
  290.                     $d $toIso($wxItem[$dk['date']] ?? null);
  291.                     if (!$d) { continue; }
  292.                     $value null;
  293.                     if ($param === 't_max_2m_24h:C') {
  294.                         $value $getNum($wxItem[$dk['max']] ?? null);
  295.                     } elseif ($param === 't_min_2m_24h:C') {
  296.                         $value $getNum($wxItem[$dk['min']] ?? null);
  297.                     } elseif ($param === 'relative_humidity_2m:p') {
  298.                         $value $getNum($wxItem[$dk['hum']] ?? null);
  299.                     } elseif ($param === 'weather_symbol_24h:idx') {
  300.                         $value $extractIconIdx($wxItem[$dk['icon']] ?? null);
  301.                     }
  302.                     $rows[] = ['date' => $d'value' => $value'weatherinfo' => true];
  303.                 }
  304.                 return $rows;
  305.             };
  306.             // Build merged jsonData
  307.             $mergedJsonData = [];
  308.             foreach ($jsonDataFull as $cityRowFull) {
  309.                 $cityEn $cityRowFull['cityEn'] ?? null;
  310.                 $cityAr $cityRowFull['cityAr'] ?? null;
  311.                 $keyAr $normAr($cityAr);
  312.                 $keyEn $normEn($cityEn);
  313.                 $wxItem null;
  314.                 if ($keyAr && isset($wxByCityAr[$keyAr])) {
  315.                     $wxItem $wxByCityAr[$keyAr];
  316.                 } elseif ($keyEn && isset($wxByCityEn[$keyEn])) {
  317.                     $wxItem $wxByCityEn[$keyEn];
  318.                 } else {
  319.                     // Fallback: substring/containment match (English first, then Arabic)
  320.                     if (!$wxItem && $keyEn) {
  321.                         foreach ($wxByCityEn as $wxKey => $candidate) {
  322.                             if ($wxKey !== '' && (str_contains($keyEn$wxKey) || str_contains($wxKey$keyEn))) {
  323.                                 $wxItem $candidate;
  324.                                 break;
  325.                             }
  326.                         }
  327.                     }
  328.                     if (!$wxItem && $keyAr) {
  329.                         foreach ($wxByCityAr as $wxKey => $candidate) {
  330.                             if ($wxKey !== '' && (str_contains($keyAr$wxKey) || str_contains($wxKey$keyAr))) {
  331.                                 $wxItem $candidate;
  332.                                 break;
  333.                             }
  334.                         }
  335.                     }
  336.                 }
  337.                 // Build a map of param -> dates from full report for fallback and for last 4 days
  338.                 $paramToDates = [];
  339.                 foreach (($cityRowFull['parameters'] ?? []) as $p) {
  340.                     $pName $p['parameter'] ?? null;
  341.                     if (!$pName || !isset($p['dates']) || !is_array($p['dates'])) { continue; }
  342.                     $paramToDates[$pName] = $p['dates'];
  343.                 }
  344.                 $newParams = [];
  345.                 foreach (($cityRowFull['parameters'] ?? []) as $p) {
  346.                     $pName $p['parameter'] ?? null;
  347.                     if (!$pName) { continue; }
  348.                     // First 6 from weatherinfo (if available), else fallback to first 6 from original
  349.                     $first6 = [];
  350.                     if ($wxItem) {
  351.                         $first6 $first6FromWx($wxItem$pName);
  352.                     }
  353.                     if (empty($first6)) {
  354.                         $orig $paramToDates[$pName] ?? [];
  355.                         $slice array_slice($orig06);
  356.                         $first6 array_map(function ($d) {
  357.                             return [
  358.                                 'date' => $d['date'] ?? null,
  359.                                 'value' => $d['value'] ?? null,
  360.                                 'weatherinfo' => false
  361.                             ];
  362.                         }, $slice);
  363.                     }
  364.                     // Last 4 from original report
  365.                     $origDates $paramToDates[$pName] ?? [];
  366.                     $last4 array_slice($origDates, -4);
  367.                     $last4 array_map(function ($d) {
  368.                         return [
  369.                             'date' => $d['date'] ?? null,
  370.                             'value' => $d['value'] ?? null,
  371.                             'weatherinfo' => false
  372.                         ];
  373.                     }, $last4);
  374.                     $newParams[] = [
  375.                         'parameter' => $pName,
  376.                         'dates' => array_values(array_merge($first6$last4)),
  377.                     ];
  378.                 }
  379.                 // Build currentParameters from weatherinfo (flat object), or null if not matched
  380.                 $currentParams null;
  381.                 if ($wxItem) {
  382.                     $trimScalar = function ($v) {
  383.                         return is_string($v) ? trim($v) : $v;
  384.                     };
  385.                     $abbrWindEn = function ($v) {
  386.                         if (!is_string($v) || $v === '') { return $v; }
  387.                         $s trim($v);
  388.                         $s str_replace(['-''_'], ' '$s);
  389.                         $s preg_replace('/\s+/u'' '$s);
  390.                         $lower mb_strtolower($s);
  391.                         $map = [
  392.                             'north' => 'N',
  393.                             'south' => 'S',
  394.                             'east' => 'E',
  395.                             'west' => 'W',
  396.                             'northeast' => 'NE',
  397.                             'north east' => 'NE',
  398.                             'northwest' => 'NW',
  399.                             'north west' => 'NW',
  400.                             'southeast' => 'SE',
  401.                             'south east' => 'SE',
  402.                             'southwest' => 'SW',
  403.                             'south west' => 'SW',
  404.                         ];
  405.                         if (isset($map[$lower])) {
  406.                             return $map[$lower];
  407.                         }
  408.                         $words explode(' '$lower);
  409.                         $abbr '';
  410.                         foreach ($words as $w) {
  411.                             if ($w === 'north') { $abbr .= 'N'; }
  412.                             elseif ($w === 'south') { $abbr .= 'S'; }
  413.                             elseif ($w === 'east') { $abbr .= 'E'; }
  414.                             elseif ($w === 'west') { $abbr .= 'W'; }
  415.                         }
  416.                         return $abbr !== '' $abbr $s;
  417.                     };
  418.                     $currentParams = [
  419.                         'currentDate' => $trimScalar($wxItem['currentDate'] ?? null),
  420.                         'currentIcon' => $extractIconIdx($wxItem['currentIcon'] ?? null),
  421.                         'currentWeather_PhenomenonAr' => $trimScalar($wxItem['currentWeather_PhenomenonAr'] ?? ($wxItem['weather_PhenomenonAr'] ?? null)),
  422.                         'currentWeather_PhenomenonEn' => $trimScalar($wxItem['currentWeather_PhenomenonEn'] ?? ($wxItem['weather_PhenomenonEn'] ?? null)),
  423.                         'currentHumidity' => $trimScalar($wxItem['currentHumidity'] ?? ($wxItem['humidity'] ?? null)),
  424.                         'pressure' => $trimScalar($wxItem['pressure'] ?? null),
  425.                         'currentTemperature' => $trimScalar($wxItem['currentTemperature'] ?? null),
  426.                         'windspeed' => $trimScalar($wxItem['windspeed'] ?? null),
  427.                         'winddirection_Ar' => $trimScalar($wxItem['winddirection_Ar'] ?? ($wxItem['winddirection_AR'] ?? null)),
  428.                         'winddirection_EN' => $abbrWindEn($wxItem['winddirection_EN'] ?? null),
  429.                         'visibility' => $trimScalar($wxItem['visibility'] ?? null),
  430.                         'dewpoint' => $trimScalar($wxItem['dewpoint'] ?? null),
  431.                     ];
  432.                 }
  433.                 $mergedJsonData[] = [
  434.                     'cityEn' => $cityEn,
  435.                     'cityAr' => $cityAr,
  436.                     'lat' => $cityRowFull['lat'] ?? null,
  437.                     'lon' => $cityRowFull['lon'] ?? null,
  438.                     'parameters' => $newParams,
  439.                     'currentParameters' => $currentParams,
  440.                 ];
  441.             }
  442.             // Build final payload matching 10-day report schema
  443.             $finalData $latestData;
  444.             $finalData['jsonData'] = $mergedJsonData;
  445.             return $this->json([
  446.                 'success' => true,
  447.                 'data' => $finalData
  448.             ]);
  449.         } catch (\Exception $ex) {
  450.             $this->logger->error($ex->getMessage());
  451.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  452.         }
  453.     }
  454.     /**
  455.      * @Route("/api/public/wms/tile", name="api_public_wms_tile", methods={"GET"})
  456.      */
  457.     public function getPublicWmsTile(Request $request): Response
  458.     {
  459.         try {
  460.             $layers $request->query->get('layers');
  461.             $time $request->query->get('time');
  462.             $bbox $request->query->get('bbox');
  463.             if (empty($layers) || empty($time) || empty($bbox)) {
  464.                 return $this->json([
  465.                     'success' => false,
  466.                     'message' => 'Missing required parameters: layers, time, bbox'
  467.                 ], 400);
  468.             }
  469.             $format $request->query->get('format''image/webp');
  470.             $width = (int) $request->query->get('width'256);
  471.             $height = (int) $request->query->get('height'256);
  472.             $crs $request->query->get('crs''EPSG:3857');
  473.             $version $request->query->get('version''1.3.0');
  474.             $service $request->query->get('service''WMS');
  475.             $wmsRequest $request->query->get('request''GetMap');
  476.             $styles $request->query->get('styles''');
  477.             $transparent $request->query->get('transparent''true');
  478.             $model $request->query->get('model');
  479.             $webpQuality $request->query->get('webp_quality_factor');
  480.             // Build query string for upstream WMS
  481.             $queryParams = [
  482.                 'service' => $service,
  483.                 'request' => $wmsRequest,
  484.                 'layers' => $layers,
  485.                 'styles' => $styles,
  486.                 'format' => $format,
  487.                 'transparent' => $transparent,
  488.                 'version' => $version,
  489.                 'time' => $time,
  490.                 'width' => $width,
  491.                 'height' => $height,
  492.                 'crs' => $crs,
  493.                 'bbox' => $bbox,
  494.             ];
  495.             if (!empty($model)) {
  496.                 $queryParams['model'] = $model;
  497.             }
  498.             if (!empty($webpQuality)) {
  499.                 $queryParams['webp_quality_factor'] = $webpQuality;
  500.             }
  501.             // Ensure RFC3986 encoding for characters like "/" and ":"
  502.             $paramString http_build_query($queryParams'''&'PHP_QUERY_RFC3986);
  503.             // Fetch from Meteomatics service (auth handled by service)
  504.             $binary $this->meteomaticsWeatherService->getWms(['param' => $paramString]);
  505.             // Determine content type
  506.             $contentType strtolower($format);
  507.             if (strpos($contentType'image/') !== 0) {
  508.                 $contentType 'image/' ltrim($contentType'/');
  509.             }
  510.             $response = new Response($binary);
  511.             $response->headers->set('Content-Type'$contentType);
  512.             $response->headers->set('Cache-Control''public, max-age=300');
  513.             return $response;
  514.         } catch (\Throwable $ex) {
  515.             return $this->json(['success' => false'message' => $ex->getMessage()], 500);
  516.         }
  517.     }
  518.     /**
  519.      * @Route("/api/public/get-report-detail", name="public_get_report_detail")
  520.      */
  521.     public function getReportDetails(Request $request)
  522.     {
  523.         try {
  524.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  525.             if ($response['success'] !== true) {
  526.                 return $this->json($response);
  527.             }
  528.             $user $response['user'];
  529.             // $params = json_decode($request->getContent(), true);
  530.             $requestUri $request->getRequestUri();
  531.             // Extract the last segment from the URL
  532.             $segments explode('/'trim($requestUri'/'));
  533.             $action end($segments);
  534.             $action str_replace("-""_"$action);
  535.             $params[] = $action;
  536.             // $reslult = $this->publicUserPermissionService->publicUserPermissionCheck($user, $params, $this->translator);
  537.             // if ($reslult['success'] !== true) {
  538.             //     return $this->json($reslult);
  539.             // }
  540.             $latestReport Report::getList([
  541.                 "limit" => 1,
  542.                 "orderKey" => "createdOn",
  543.                 "order" => "desc"
  544.             ]);
  545.             if ($latestReport->getCount() <= 0) {
  546.                 throw new \Exception('no_latest_report_found');
  547.             } else {
  548.                 $data = [];
  549.                 foreach ($latestReport as $report) {
  550.                     $data = [
  551.                         'name' => $report->getCreatedBy()?->getName(),
  552.                         'email' => $report->getCreatedBy()?->getEmail(),
  553.                         'jsonData' => json_decode($report->getJsonData(), true),
  554.                         'createdOn' => $report->getCreatedOn()
  555.                     ];
  556.                 }
  557.                 return $this->json(['success' => true'data' => $data]);
  558.             }
  559.         } catch (\Exception $ex) {
  560.             $this->logger->error($ex->getMessage());
  561.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  562.         }
  563.     }
  564.     /**
  565.      * @Route("/api/public/ews-analytics", methods={"POST"})
  566.      */
  567.     public function ewsAnalyticsAction(Request $request): JsonResponse
  568.     {
  569.         try {
  570.             $params json_decode($request->getContent(), true);
  571.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  572.             $lang = ($request->headers->has('lang')) ? $request->headers->get('lang') : "en";
  573.             $result $this->ewsNotificationModel->ewsAnalytics($params$this->connection$lang);
  574.             return $this->json($result);
  575.         } catch (\Exception $ex) {
  576.             $this->logger->error($ex->getMessage());
  577.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  578.         }
  579.     }
  580.     /**
  581.      * @Route("/api/public/generate-report", methods={"POST"})
  582.      */
  583.     public function generateReport(Request $request): JsonResponse
  584.     {
  585.         try {
  586.             $response = [];
  587.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  588.             if ($permissions['success'] !== true) {
  589.                 return $this->json($permissions);
  590.             }
  591.             $params json_decode($request->getContent(), true);
  592.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  593.             if (
  594.                 !isset($params['from_date']) ||
  595.                 !isset($params['to_date']) ||
  596.                 !isset($params['hours']) ||
  597.                 !isset($params['parameters'])  ||
  598.                 !isset($params['locations'])
  599.             ) {
  600.                 throw new \Exception('Missing required parameters');
  601.             }
  602.             if (empty($params['parameters'] || !is_array($params['parameters']))) {
  603.                 throw new \Exception('Parameters should be non empty array');
  604.             }
  605.             if (empty($params['locations'] || !is_array($params['locations']))) {
  606.                 throw new \Exception('Locations should be non empty array');
  607.             }
  608.             $model = isset($params['model']) ? $params['model'] : 'mix';
  609.             $redisKey md5('generate_city_report-' $params['from_date'] . '-' $params['to_date'] . '-' $params['hours'] . '-' implode('_'$params['locations'])) . '-' implode('_'$params['parameters']) . '-' $model;
  610.             $data $this->redisCache->get($redisKey);
  611.             if (!$data) {
  612.                 $cities = new \Pimcore\Model\DataObject\City\Listing();
  613.                 if (!empty($params['locations'])) {
  614.                     $cities->setCondition('o_id IN (?)', [$params['locations']]);
  615.                 }
  616.                 $cities->load();
  617.                 if ($cities->getCount() > 0) {
  618.                     $params['coordinates'] = []; // Initialize an empty array for coordinates
  619.                     $result = [];
  620.                     $citiesArr = [];
  621.                     foreach ($cities as $city) {
  622.                         $params['coordinates'][] = [$city->getLatitude(), $city->getLongitude()];
  623.                         // Append the coordinates for each city
  624.                         $long number_format($city->getLongitude(), 6'.''');
  625.                         $lat number_format($city->getLatitude(), 6'.''');
  626.                         $citiesArr[$lat '|' $long]["en"] =  $city->getCityName("en");
  627.                         $citiesArr[$lat '|' $long]["ar"] =  $city->getCityName("ar");
  628.                     }
  629.                     $result $this->meteomaticsWeatherService->getReportForecastData($params['coordinates'], $params['from_date'], $params['to_date'], $params['hours'], $model$params['parameters'], $this->translator$citiesArr$params);
  630.                     $response[] = $result;
  631.                     $jsonResponse = ['success' => true'data' => $response];
  632.                     $this->redisCache->set($redisKey$jsonResponseREDIS_CACHE_TIME);
  633.                     return $this->json($jsonResponse);
  634.                 } else {
  635.                     return $this->json(['success' => true'message' => $this->translator->trans('no_city_found')]);
  636.                 }
  637.             } else {
  638.                 return $this->json($data);
  639.             }
  640.         } catch (\Exception $ex) {
  641.             $this->logger->error($ex->getMessage());
  642.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  643.         }
  644.     }
  645.     /**
  646.      * @Route("/api/public/update-report", methods={"POST"})
  647.      */
  648.     public function updateReport(Request $request)
  649.     {
  650.         try {
  651.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  652.             if ($permissions['success'] !== true) {
  653.                 return $this->json($permissions);
  654.             }
  655.             $user $permissions['user'];
  656.             $params  json_decode($request->getContent(), true);
  657.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  658.             // Perform parameter validation here
  659.             // || !isset($params['locations'])
  660.             if (!isset($params['data'])  || !isset($params['start_date']) || !isset($params['end_date']) || !isset($params['lang'])) {
  661.                 return $this->json(['success' => false'message' =>  $this->translator->trans('missing_required_parameters')]);
  662.             }
  663.             if (isset($params['organizations'])) {
  664.                 if (!is_array($params['organizations'])) {
  665.                     throw new \Exception($this->translator->trans('Organizations should be non empty array'), 400);
  666.                 }
  667.             }
  668.             if (isset($params['channels'])) {
  669.                 if (!is_array($params['channels']) || empty($params['channels'])) {
  670.                     throw new \Exception($this->translator->trans('Channels should be non empty array'), 400);
  671.                 }
  672.                 if (in_array('email'$params['channels'])) {
  673.                     if (!isset($params['emails']) || !is_array($params['emails']) || empty($params['emails'])) {
  674.                         throw new \Exception($this->translator->trans('Emails should be non empty array'), 400);
  675.                     }
  676.                 }
  677.             }
  678.             $result $this->reportModel->editReport($user$params$this->translator$this->logger);
  679.             return $this->json($result);
  680.         } catch (\Exception $ex) {
  681.             $this->logger->error($ex->getMessage());
  682.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  683.         }
  684.     }
  685.     /**
  686.      * @Route("/api/public/get-city-list", name="public-city-listing")
  687.      */
  688.     public function getCityListAction(Request $request)
  689.     {
  690.        
  691.         try {
  692.             $result = [];
  693.             $lang = ($request->headers->has('lang')) ? $request->headers->get('lang') : "en";
  694.             $params  json_decode($request->getContent(), true);
  695.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  696.             $reportTypeId $params['report_type_id'] ?? null;
  697.             $cities = new \Pimcore\Model\DataObject\City\Listing();
  698.             $cities->setOrderKey('cityName');
  699.             $cities->setOrder("ASC");
  700.             if ($reportTypeId) {
  701.                 $cities->setCondition("reportType REGEXP CONCAT('(^|,)', REPLACE('" $reportTypeId "', ',', '|'), '(,|$)')");
  702.             } else {
  703.                 $db \Pimcore\Db::get();
  704.                 $selectedLocalities $db->fetchAllAssociative("SELECT oo_id  FROM `object_query_ReportType` WHERE (`isAutomaticReport` = 0)");
  705.                 $ooIds array_column($selectedLocalities'oo_id');
  706.                 $cities->setCondition("reportType REGEXP CONCAT('(^|,)', REPLACE('" implode(','$ooIds) . "', ',', '|'), '(,|$)')");
  707.             }
  708.             $cities->load();
  709.             if ($cities->getCount() > 0) {
  710.                 foreach ($cities as $city) {
  711.                     $result[] = [
  712.                         "id" => $city->getId(),
  713.                         "name" => $city->getCityName($lang),
  714.                         "nameEn" => $city->getCityName('en'),
  715.                         "nameAr" => $city->getCityName('ar'),
  716.                         "lat" => $city->getLatitude(),
  717.                         "long" => $city->getLongitude(),
  718.                         "googlePlaceName" => $city->getGooglePlaceName(),
  719.                     ];
  720.                 }
  721.                 return $this->json(["success" => true"data" => $result]);
  722.             }
  723.             return $this->json(["success" => false"message" => $this->translator->trans("no_city_is_available")]);
  724.         } catch (\Exception $ex) {
  725.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  726.         }
  727.     }
  728.     /**
  729.      * @Route("/api/public/list-report", name="public-report-listing")
  730.      */
  731.     public function getReportListAction(Request $requestPaginatorInterface $paginator)
  732.     {
  733.         try {
  734.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  735.             if ($permissions['success'] !== true) {
  736.                 return $this->json($permissions);
  737.             }
  738.             $user $permissions['user'];
  739.             $params  json_decode($request->getContent(), true);
  740.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  741.             if (!isset($params['page']) || !isset($params['limit'])) {
  742.                 throw new \Exception('Missing required params: page or limit');
  743.             }
  744.             $report_type = isset($params['report_type']) ? $params['report_type'] : null;
  745.             $lang = isset($params['lang']) ? $params['lang'] : DEFAULT_LOCALE;
  746.             $isPublicReports = isset($params['publicReports']) ? $params['publicReports'] : false// sending this flag from public portal to get all reports accordong to our needs
  747.             $page $params['page'];
  748.             $limit $params['limit'];
  749.             $result $this->reportModel->reportList($params$page$limit$this->translator$paginator$report_type$user$lang$isPublicReports);
  750.             return $this->json($result);
  751.         } catch (\Exception $ex) {
  752.             $this->logger->error($ex->getMessage());
  753.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  754.         }
  755.     }
  756.     /**
  757.      * @Route("/api/public/generate-report-pdf", name="public-report-pdf")
  758.      */
  759.     public function generateReportPdf(Request $request)
  760.     {
  761.         try {
  762.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  763.             if ($permissions['success'] !== true) {
  764.                 return $this->json($permissions);
  765.             }
  766.             $user $permissions['user'];
  767.             $params  json_decode($request->getContent(), true);
  768.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  769.             return $this->getPdfReport($request$user'pdf/report_pdf_template.html.twig'$this->translator'_manned_forecast_report.pdf');
  770.         } catch (\Exception $ex) {
  771.             $this->logger->error($ex->getMessage());
  772.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  773.         }
  774.     }
  775.     /**
  776.      * @Route("/api/public/get-report-types", name="public-report-types-listing")
  777.      */
  778.     public function getReportTypes(Request $request)
  779.     {
  780.         try {
  781.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  782.             if ($permissions['success'] !== true) {
  783.                 return $this->json($permissions);
  784.             }
  785.             $params  json_decode($request->getContent(), true);
  786.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  787.             if (!isset($params['automatic'])) {
  788.                 throw new \Exception('missing_required_parameters');
  789.             }
  790.             $result = [];
  791.             $automatic $params['automatic'] ? true false;
  792.             $reportTypes = new \Pimcore\Model\DataObject\ReportType\Listing();
  793.             $reportTypes->setCondition('isAutomaticReport = ?', [$automatic]);
  794.             $reportTypes->load();
  795.             if ($reportTypes->getCount() > 0) {
  796.                 foreach ($reportTypes as $reportType) {
  797.                     $result[] = [
  798.                         "id" => $reportType->getId(),
  799.                         "key" => $reportType->getReportKey(),
  800.                         "nameEn" => $reportType->getName('en'),
  801.                         "nameAr" => $reportType->getName('ar'),
  802.                         "descriptionEn" => $reportType->getDescription('en'),
  803.                         "descriptionAr" => $reportType->getDescription('ar'),
  804.                         "titleEn" => $reportType->getTitle('en'),
  805.                         "titleAr" => $reportType->getTitle('ar'),
  806.                         "automatic" => $reportType->getIsAutomaticReport()
  807.                     ];
  808.                 }
  809.                 return $this->json(["success" => true"data" => $result]);
  810.             }
  811.             return $this->json(["success" => false"message" => $this->translator->trans("no_reportType_is_available")]);
  812.         } catch (\Exception $ex) {
  813.             $this->logger->error($ex->getMessage());
  814.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  815.         }
  816.     }
  817.     /**
  818.      * @Route("/api/public/get-weather-params-list", name="public-weather-params-listing")
  819.      */
  820.     public function getWeatherParamsListAction(Request $request)
  821.     {
  822.         try {
  823.             $result = [];
  824.             $lang = ($request->headers->has('lang')) ? $request->headers->get('lang') : "en";
  825.             $params  json_decode($request->getContent(), true);
  826.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  827.             if (!isset($params['report_type_id'])) {
  828.                 return $this->json(['success' => false'message' =>  $this->translator->trans('missing_required_parameters')]);
  829.             }
  830.             $reportTypeId $params['report_type_id'];
  831.             $parameters = new \Pimcore\Model\DataObject\ReportWeatherParameters\Listing();
  832.             $parameters->setCondition("reportType REGEXP CONCAT('(^|,)', REPLACE('" $reportTypeId "', ',', '|'), '(,|$)')");
  833.             $parameters->load();
  834.             if ($parameters->getCount() > 0) {
  835.                 foreach ($parameters as $paramter) {
  836.                     $result[] = [
  837.                         "id" => $paramter->getId(),
  838.                         "nameEn" => $paramter->getName('en'),
  839.                         "nameAr" => $paramter->getName('ar'),
  840.                         "meteoMaticsKey" => $paramter->getMeteoMaticsKey(),
  841.                         "units" => $paramter->getUnits(),
  842.                         "unitTitle" => $paramter->getUnitTitle()
  843.                     ];
  844.                 }
  845.                 return $this->json(["success" => true"data" => $result]);
  846.             }
  847.             return $this->json(["success" => false"message" => $this->translator->trans("no_weather_parameter_is_available")]);
  848.         } catch (\Exception $ex) {
  849.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  850.         }
  851.     }
  852.     /**
  853.      * @Route("/api/public/generate-excel", name="public-generate-excel")
  854.      */
  855.     public function generateExcelReport(Request $request)
  856.     {
  857.         $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  858.         if ($permissions['success'] !== true) {
  859.             return $this->json($permissions);
  860.         }
  861.         $user $permissions['user'];
  862.         $params  json_decode($request->getContent(), true);
  863.         $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  864.         if (!isset($params['id'])) {
  865.             throw new \Exception('missing_required_parameters');
  866.         }
  867.         $report Report::getById($params['id'], true);
  868.         if (!$report instanceof Report) {
  869.             throw new \Exception('no_report_found');
  870.         }
  871.         // Replace this with the actual data you want to use
  872.         $jsonData json_decode($report->getJsonData(), true);
  873.         // Create a new PhpSpreadsheet instance
  874.         $spreadsheet = new Spreadsheet();
  875.         // Create a worksheet
  876.         $sheet $spreadsheet->getActiveSheet();
  877.         // Determine headers dynamically based on the first item in the data
  878.         $firstItem reset($jsonData);
  879.         $parameters $firstItem['parameters'] ?? [];
  880.         $headers = ['City''Lat''Lon''Date']; // Initialize headers with common columns
  881.         // Extract parameter names and add them to headers
  882.         foreach ($parameters as $parameter) {
  883.             $headers[] = $parameter['parameter'];
  884.         }
  885.         // Add headers to the worksheet
  886.         foreach ($headers as $index => $header) {
  887.             $sheet->setCellValueByColumnAndRow($index 11$header);
  888.         }
  889.         // Initialize row counter
  890.         $row 2;
  891.         foreach ($jsonData as $item) {
  892.             // Extract city-related data
  893.             $cityData = [$item['city'] ?? ''$item['lat'] ?? ''$item['lon'] ?? ''];
  894.             // Loop through each date for all parameters
  895.             foreach ($item['parameters'][0]['dates'] as $dateIndex => $date) {
  896.                 // Initialize row data with city-related data and date
  897.                 $rowData array_merge($cityData, [date('Y-m-d'strtotime($date['date']))]);
  898.                 // Loop through each parameter
  899.                 foreach ($item['parameters'] as $parameter) {
  900.                     // Check if the value is set for the current date, otherwise set it to 0
  901.                     $value = isset($parameter['dates'][$dateIndex]['value']) ? $parameter['dates'][$dateIndex]['value'] : 0;
  902.                     // Add parameter value for the current date to the row data
  903.                     $rowData[] = $value;
  904.                 }
  905.                 // Set cell values explicitly
  906.                 foreach ($rowData as $colIndex => $cellValue) {
  907.                     $sheet->setCellValueByColumnAndRow($colIndex 1$row$cellValue);
  908.                 }
  909.                 // Increment the row counter
  910.                 $row++;
  911.             }
  912.         }
  913.         // Save the Excel file to a temporary file
  914.         $tempFile tempnam(sys_get_temp_dir(), 'weather_report');
  915.         $writer = new Xlsx($spreadsheet);
  916.         $writer->save($tempFile);
  917.         // Store the file in Pimcore Assets
  918.         $assetFolder '/report/ExcelReports'// Change this to your actual asset folder path
  919.         $filename $user->getId() . '_' time() . '_' 'weather_report.xlsx';
  920.         $assetPath =  API_BASE_URL '/' $assetFolder '/' $filename;
  921.         // Create a new asset
  922.         $asset = new \Pimcore\Model\Asset();
  923.         $asset->setFilename($filename);
  924.         $asset->setData(file_get_contents($tempFile));
  925.         $asset->setParent(\Pimcore\Model\Asset\Service::createFolderByPath($assetFolder));
  926.         $asset->save();
  927.         // Remove the temporary file
  928.         unlink($tempFile);
  929.         $report->setAsset($asset);
  930.         $report->setIsHistorical(true);
  931.         $report->save();
  932.         // Return the path to the stored Excel file in Pimcore
  933.         return $this->json(['success' => true'data' => $assetPath]);
  934.     }
  935.     /**
  936.      * @Route("/api/public/generate-historical-report", methods={"POST"})
  937.      */
  938.     public function generateHistoricalReport(Request $request): JsonResponse
  939.     {
  940.         try {
  941.             $response = [];
  942.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  943.             if ($permissions['success'] !== true) {
  944.                 return $this->json($permissions);
  945.             }
  946.             $params json_decode($request->getContent(), true);
  947.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  948.             if (
  949.                 !isset($params['from_date']) ||
  950.                 !isset($params['to_date']) ||
  951.                 !isset($params['hours']) ||
  952.                 !isset($params['parameters'])  ||
  953.                 !isset($params['locations'])
  954.             ) {
  955.                 throw new \Exception('Missing required parameters');
  956.             }
  957.             if (empty($params['parameters'] || !is_array($params['parameters']))) {
  958.                 throw new \Exception('Parameters should be non empty array');
  959.             }
  960.             if (empty($params['locations'] || !is_array($params['locations']))) {
  961.                 throw new \Exception('Locations should be non empty array');
  962.             }
  963.             if ($params['to_date'] > date('Y-m-d'strtotime(Carbon::now()))) {
  964.                 $daysadd date('Y-m-d'strtotime(Carbon::now()->addDays('17')));
  965.                 if ($params['to_date'] >= $daysadd) {
  966.                     throw new \Exception('End date limit exceeded');
  967.                 }
  968.             }
  969.             $model = isset($params['model']) ? $params['model'] : 'mix';
  970.             $redisKey md5('generate_city_report-' $params['from_date'] . '-' $params['to_date'] . '-' $params['hours'] . '-' implode('_'$params['locations'])) . '-' implode('_'$params['parameters']) . '-' $model;
  971.             $data $this->redisCache->get($redisKey);
  972.             if (!$data) {
  973.                 $cities = new \Pimcore\Model\DataObject\Location\Listing();
  974.                 if (!empty($params['locations'])) {
  975.                     $cities->setCondition('o_id IN (?)', [$params['locations']]);
  976.                 }
  977.                 $cities->load();
  978.                 if ($cities->getCount() > 0) {
  979.                     $params['coordinates'] = []; // Initialize an empty array for coordinates
  980.                     $result = [];
  981.                     $citiesArr = [];
  982.                     foreach ($cities as $city) {
  983.                         $cityLocations json_decode($city->getCoordinates(), true);
  984.                         foreach ($cityLocations as $coordinates) {
  985.                             $long number_format($coordinates[1], 6'.''');
  986.                             $lat number_format($coordinates[0], 6'.''');
  987.                             $params['coordinates'][] = $coordinates;
  988.                             $citiesArr[$lat '|' $long] =  $city->getName();
  989.                         }
  990.                     }
  991.                     $result $this->meteomaticsWeatherService->getReportForecastData($params['coordinates'], $params['from_date'], $params['to_date'], $params['hours'], $model$params['parameters'], $this->translator$citiesArr$params);
  992.                     $response[] = $result;
  993.                     $jsonResponse = ['success' => true'data' => $response];
  994.                     $this->redisCache->set($redisKey$jsonResponseREDIS_CACHE_TIME);
  995.                     return $this->json($jsonResponse);
  996.                 } else {
  997.                     return $this->json(['success' => true'message' => $this->translator->trans('no_city_found')]);
  998.                 }
  999.             } else {
  1000.                 return $this->json($data);
  1001.             }
  1002.         } catch (\Exception $ex) {
  1003.             $this->logger->error($ex->getMessage());
  1004.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  1005.         }
  1006.     }
  1007.     /**
  1008.      * @Route("/api/public/get-latest-report", name="public-get-latest-report")
  1009.      */
  1010.     public function getLatestReport(Request $request)
  1011.     {
  1012.         try {
  1013.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1014.             if ($permissions['success'] !== true) {
  1015.                 return $this->json($permissions);
  1016.             }
  1017.             $params  json_decode($request->getContent(), true);
  1018.             $reportType = (isset($params['report_type']) && !empty($params['report_type'])) ? $params['report_type'] : 'ten-day-forecast-report';
  1019.             $result $this->reportModel->getLatestReport($reportType$this->translatorfalse);
  1020.             return $this->json($result);
  1021.         } catch (\Exception $ex) {
  1022.             $this->logger->error($ex->getMessage());
  1023.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  1024.         }
  1025.     }
  1026.     /**
  1027.      * @Route("/api/public/get-automatic-reports", name="public_get_automatic_reports")
  1028.      */
  1029.     public function getAutomaticReports(Request $requestPaginatorInterface $paginator)
  1030.     {
  1031.         try {
  1032.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1033.             if ($permissions['success'] !== true) {
  1034.                 return $this->json($permissions);
  1035.             }
  1036.             $user $permissions['user'];
  1037.             $params  json_decode($request->getContent(), true);
  1038.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  1039.             if (!isset($params['page']) || !isset($params['limit']) || !isset($params['lang'])) {
  1040.                 throw new \Exception('Missing required parameters');
  1041.             }
  1042.             $search = isset($params['search']) ? $params['search'] : null;
  1043.             $orderKey = isset($params['orderKey']) ? $params['orderKey'] : 'createdOn';
  1044.             $order = isset($params['order']) ? $params['order'] : 'desc';
  1045.             $result $this->reportModel->listAutomaticReports($params$user$search$orderKey$order$this->translator$paginator);
  1046.             return $this->json($result);
  1047.         } catch (\Exception $ex) {
  1048.             $this->logger->error($ex->getMessage());
  1049.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  1050.         }
  1051.     }
  1052.     /**
  1053.      * @Route("/api/public/generate-automatic-report-pdf", name="public-automatic-report-pdf")
  1054.      */
  1055.     public function generateAutomaticReportPdf(Request $request)
  1056.     {
  1057.         try {
  1058.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1059.             if ($permissions['success'] !== true) {
  1060.                 return $this->json($permissions);
  1061.             }
  1062.             $user $permissions['user'];
  1063.             $result $this->reportModel->generatePdfReport($request$user$this->snappy$this->translator);
  1064.             return  $this->json($result);
  1065.         } catch (\Exception $ex) {
  1066.             $this->logger->error($ex->getMessage());
  1067.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  1068.         }
  1069.     }
  1070.     public function getPdfReport($request$user$template$translator$report_type)
  1071.     {
  1072.         $params  json_decode($request->getContent(), true);
  1073.         if (!isset($params['id'])) {
  1074.             return $this->json(["success" => false"message" => $translator->trans("missing_required_parameters")]);
  1075.         }
  1076.         $report Report::getById($params['id'], true);
  1077.         $lang = isset($params['lang']) ? $params['lang'] : "en";
  1078.         if (!$report instanceof Report) {
  1079.             return $this->json(["success" => false"message" => $translator->trans("no_report_found")]);
  1080.         }
  1081.         $asset $lang == 'ar' $report->getAssetAr() : $report->getAsset();
  1082.         if ($asset) {
  1083.             $pdfasset API_BASE_URL $asset->getPath() . $asset->getFilename();
  1084.             return $this->json(['success' => true'data' => $pdfasset]);
  1085.         }
  1086.         //$template=$report->getReportType()?->getKey() == 'MannForecastReport'?'pdf/report_pdf_template.html.twig':'pdf/automatic_report_pdf_template.html.twig';
  1087.         $fileName '_custom_weather_report.pdf';
  1088.         $reportPath '/report/ReportPdf';
  1089.         if ($report->getReportType()?->getKey() == 'MannForecastReport') {
  1090.             $template =  'pdf/report_pdf_template.html.twig';
  1091.         } elseif ($report->getReportType()?->getKey() == 'advance-custom-weather-report') {
  1092.             $template 'pdf/advance_custom_report_pdf_template.html.twig';
  1093.             $fileName '_advance_custom_weather_report.pdf';
  1094.             $reportPath '/report/advanceCustomReportPdf';
  1095.         } else {
  1096.             $template 'pdf/automatic_report_pdf_template.html.twig';
  1097.         }
  1098.         $parameter = [
  1099.             'data' => $report,
  1100.             'reportTitleEn' => $report->getReportTitle('en'),
  1101.             'reportTitleAr' => $report->getReportTitle('ar'),
  1102.             'reportDescriptionEn' => $report->getDescription('en'),
  1103.             'reportDescriptionAr' => $report->getDescription('ar'),
  1104.             'reportDisclaimerEn' => $report->getReportDisclaimer('en'), // new 
  1105.             'reportDisclaimerAr' => $report->getReportDisclaimer('ar'), // new 
  1106.             'additionalNoteEn' => $report->getAdditionalNote('en'), // new 
  1107.             'additionalNoteAr' => $report->getAdditionalNote('ar'), // new 
  1108.             'template' => $template,
  1109.             'lang' => $lang
  1110.         ];
  1111.         // return $this->render('pdf/automatic_report_pdf_template_copy.html.twig',$parameter);
  1112.         $pdf \App\Lib\Utility::generatePdf($parameter$this->snappy);
  1113.         // $tempFilePath = tempnam(sys_get_temp_dir(), 'image_');
  1114.         // file_put_contents($tempFilePath, $pdf);
  1115.         // Create a BinaryFileResponse and set headers
  1116.         //    $response = new BinaryFileResponse($tempFilePath);
  1117.         //    $response->headers->set('Content-Type', 'application/pdf');
  1118.         //    $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_INLINE, 'image.pdf');
  1119.         // Return the response
  1120.         //    return $response;
  1121.         $asset \App\Lib\Utility::createAsset($pdf$user->getId() . '_' time() . $report_type,  $reportPath);
  1122.         $pdfasset '';
  1123.         if ($asset instanceof Asset) {
  1124.             $pdfasset API_BASE_URL $asset->getPath() . $asset->getFilename();
  1125.         }
  1126.         if ($lang == 'ar') {
  1127.             $report->setAssetAr($asset);
  1128.         } else {
  1129.             $report->setAsset($asset);
  1130.         }
  1131.         $report->save();
  1132.         return $this->json(['success' => true'data' => $pdfasset]);
  1133.     }
  1134.     /**
  1135.      * @Route("/api/public/get-today-weather-report", name="public_get_today_weather_report")
  1136.      */
  1137.     public function getTodayWeatherReports(Request $requestPaginatorInterface $paginator)
  1138.     {
  1139.         try {
  1140.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1141.             if ($permissions['success'] !== true) {
  1142.                 return $this->json($permissions);
  1143.             }
  1144.             $user $permissions['user'];
  1145.             $params  json_decode($request->getContent(), true);
  1146.             if (!isset($params['page']) || !isset($params['limit']) || !isset($params['lang'])) {
  1147.                 throw new \Exception('Missing required parameters');
  1148.             }
  1149.             $result $this->reportModel->getTodayWeatherReports($params$this->translator$paginator);
  1150.             return $this->json($result);
  1151.         } catch (\Exception $ex) {
  1152.             $this->logger->error($ex->getMessage());
  1153.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  1154.         }
  1155.     }
  1156.     /**
  1157.      * @Route("/api/public/get-report-weather-symbols", name="public_get_report_weather_symbols")
  1158.      */
  1159.     public function getReportWeatherSymbols(Request $request): JsonResponse
  1160.     {
  1161.         try {
  1162.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1163.             if ($permissions['success'] !== true) {
  1164.                 return $this->json($permissions);
  1165.             }
  1166.             $user $permissions['user'];
  1167.             $data = [];
  1168.             $weatherSymbols = new ReportWeatherSymbols\Listing();
  1169.             foreach ($weatherSymbols as $weatherSymbol) {
  1170.                 if ($weatherSymbol) {
  1171.                     $weatherSymbolNames $weatherSymbol->getWeatherSymbols();
  1172.                     $weatherSymbolIcons $weatherSymbol->getWeatherIcons();
  1173.                     if ($weatherSymbolNames) {
  1174.                         foreach ($weatherSymbolNames as $weatherSymbolName) {
  1175.                             $response['symbols'][] = [
  1176.                                 'nameEn' => $weatherSymbolName->getSymbolName('en'),
  1177.                                 'nameAr' => $weatherSymbolName->getSymbolName('ar'),
  1178.                             ];
  1179.                         }
  1180.                     }
  1181.                     if ($weatherSymbolIcons) {
  1182.                         foreach ($weatherSymbolIcons as $weatherSymbolIcon) {
  1183.                             $response['icons'][] = [
  1184.                                 'iconValue' => $weatherSymbolIcon->getIconValue(),
  1185.                             ];
  1186.                         }
  1187.                     }
  1188.                 }
  1189.                 $data[] = $response;
  1190.             }
  1191.             return $this->json(['success' => true'data' => $data]);
  1192.         } catch (\Exception $ex) {
  1193.             $this->logger->error($ex->getMessage());
  1194.             return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  1195.         }
  1196.     }
  1197.     /**
  1198.      * @Route("/api/public/get-forecast-cities", methods={"POST"})
  1199.      */
  1200.     public function getForecastCities(Request $request): Response
  1201.     {
  1202.         try {
  1203.             $params json_decode($request->getContent(), true);
  1204.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  1205.             // check user credentials and expiry
  1206.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1207.             if ($response['success'] !== true) {
  1208.                 return $this->json($response);
  1209.             }
  1210.             $forecastCityModel = new WeatherForecastCityModel();
  1211.             $cities $forecastCityModel->getWeatherForecastCities();
  1212.             return $this->json(['success' => true'data' => $cities]);
  1213.         } catch (\Exception $ex) {
  1214.             $this->logger->error($ex->getMessage());
  1215.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  1216.         }
  1217.     }
  1218.     /**
  1219.      * @Route("/api/public/get-regions-bbox", name="get-regions-bbox")
  1220.      */
  1221.     public function getRegionsBbox(Request $request)
  1222.     {
  1223.         try {
  1224.             $params json_decode($request->getContent(), true);
  1225.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  1226.             // check user credentials and expiry
  1227.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1228.             if ($response['success'] !== true) {
  1229.                 return $this->json($response);
  1230.             }
  1231.             $data REGIONS_BBOX;
  1232.             return $this->json(['success' => true'data' => $data]);
  1233.         } catch (\Exception $ex) {
  1234.             $this->logger->error($ex->getMessage());
  1235.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  1236.         }
  1237.     }
  1238.     /**
  1239.      * @Route("/api/public/get-station-data", methods={"GET"})
  1240.      */
  1241.     public function getWeatherStationDataAction(Request $request)
  1242.     {
  1243.         try {
  1244.             $params json_decode($request->getContent(), true);
  1245.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  1246.             // check user credentials and expiry
  1247.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1248.             if ($response['success'] !== true) {
  1249.                 return $this->json($response);
  1250.             }
  1251.             $typeName $request->get('type_name');
  1252.             $parameters $request->get('parameters');
  1253.             $dateTime $request->get('date_time');
  1254.             $bBox $request->get('b_box');
  1255.             if (!$typeName) {
  1256.                 throw new \InvalidArgumentException("Missing mandatory parameter: type_name");
  1257.             }
  1258.             if (!$parameters) {
  1259.                 throw new \InvalidArgumentException("Missing mandatory parameter: parameters");
  1260.             }
  1261.             if (!$dateTime) {
  1262.                 throw new \InvalidArgumentException("Missing mandatory parameter: date_time");
  1263.             }
  1264.             if (!$bBox) {
  1265.                 throw new \InvalidArgumentException("Missing mandatory parameter: b_box");
  1266.             }
  1267.             $result $this->meteomaticsWeatherService->getWeatherStationData($typeName$parameters$dateTime$bBox);
  1268.             return $result;
  1269.         } catch (\Exception $ex) {
  1270.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  1271.         }
  1272.     }
  1273.     /**
  1274.      * @Route("/api/public/daily-forecast", methods={"POST"})
  1275.      */
  1276.     public function dailyForecast(Request $request): JsonResponse
  1277.     {
  1278.         try {
  1279.             $params json_decode($request->getContent(), true);
  1280.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  1281.             // check user credentials and expiry
  1282.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1283.             if ($response['success'] !== true) {
  1284.                 return $this->json($response);
  1285.             }
  1286.             $requiredParameters = ['coordinates''from_date''to_date''model'];
  1287.             foreach ($requiredParameters as $param) {
  1288.                 if (!isset($params[$param])) {
  1289.                     $missingParams[] = $param;
  1290.                 }
  1291.             }
  1292.             if (!empty($missingParams)) {
  1293.                 // Throw an exception with a message that includes the missing parameters
  1294.                 $parameterList implode(", "$missingParams);
  1295.                 return $this->json(['success' => false'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
  1296.             }
  1297.             $result $this->meteomaticsWeatherService->getForecastData($params['coordinates'], $params['from_date'], $params['to_date'], $params['hours'], $params['model'], $this->translator);
  1298.             return $this->json($result);
  1299.         } catch (\Exception $ex) {
  1300.             $this->logger->error($ex->getMessage());
  1301.             return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  1302.         }
  1303.     }
  1304.     /**
  1305.      * @Route("/api/public/weather/{path}", name="api_meteomatics", requirements={"path"=".+"}, methods={"GET"})
  1306.      */
  1307.     public function getDynamicWeatherData(Request $requeststring $path): Response
  1308.     {
  1309.         try {
  1310.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1311.             if ($response['success'] !== true) {
  1312.                 return $this->json($response);
  1313.             }
  1314.             $user $response['user'];
  1315.             $queryParams $request->query->all();
  1316.             $weatherData $this->meteomaticApiService->getDynamicWeatherData($path$queryParams$user);
  1317.             return $weatherData;
  1318.         } catch (\Exception $ex) {
  1319.             $this->logger->error($ex->getMessage());
  1320.             return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  1321.         }
  1322.     }
  1323.     /**
  1324.      * @Route("/api/public/create-manned-alert-subscription", methods={"POST"})
  1325.      */
  1326.     public function mannedAlertSubscription(Request $request): JsonResponse
  1327.     {
  1328.         try {
  1329.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1330.             if ($response['success'] !== true) {
  1331.                 return $this->json($response);
  1332.             }
  1333.             $user $response['user'];
  1334.             $params json_decode($request->getContent(), true);
  1335.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  1336.             // $requiredParameters = ['region_id', 'governorate_id', 'alert_type_id'];
  1337.             // foreach ($requiredParameters as $param) {
  1338.             //     if (!isset($params[$param]) || empty($params[$param])) {
  1339.             //         $missingParams[] = $param;
  1340.             //     }
  1341.             // }
  1342.             // if (!empty($missingParams)) {
  1343.             //     // Throw an exception with a message that includes the missing parameters
  1344.             //     $parameterList = implode(", ", $missingParams);
  1345.             //     return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
  1346.             // }
  1347.             $result $this->customNotificationService->mannedAlertSubscription($user$params$this->translator);
  1348.             return $this->json($result);
  1349.         } catch (\Exception $ex) {
  1350.             $this->logger->error($ex->getMessage());
  1351.             return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  1352.         }
  1353.     }
  1354.     /**
  1355.      * @Route("/api/public/upload-bulk-locations", methods={"POST"})
  1356.      */
  1357.     public function uploadBulkLocations(Request $request): JsonResponse
  1358.     {
  1359.         try {
  1360.             $lang $request->request->get('lang');
  1361.             $email $request->request->get('email''umer.wasi@centricdxb.com');
  1362.             $name $request->request->get('name''User');
  1363.             $reason $request->request->get('request_reason''N/A');
  1364.             $file $request->files->get('file');
  1365.             $this->translator->setlocale(isset($lang) ? $lang DEFAULT_LOCALE);
  1366.             if (!$file || !$file->isValid()) {
  1367.                 return new JsonResponse(['success' => false'message' => 'Invalid or missing file'], 400);
  1368.             }
  1369.             // Upload file to c2service and get asset ID
  1370.             $assetId $this->c2Service->uploadToC2service($file);
  1371.             if (!$assetId) {
  1372.                 throw new \Exception('Failed to upload to c2service');
  1373.             }
  1374.             $html $this->templating->render('web2print/_request_location.html.twig', ['name' => $name'reason' => $reason]);
  1375.             $result $this->c2Service->sendWeatherDashboardEmail($_ENV['WEATHER_DASHBOARD_LOCATIONS'], $email$html''$assetId);
  1376.             return $this->json(['success' => true'message' => $this->translator->trans('file_successfully_submitted')]);
  1377.         } catch (\Exception $ex) {
  1378.             $this->logger->error($ex->getMessage());
  1379.             return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  1380.         }
  1381.     }
  1382.     /**
  1383.      * @Route("/api/public/get-token", methods={"POST"})
  1384.      */
  1385.     public function getToken(Request $request): JsonResponse
  1386.     {
  1387.         try {
  1388.             $result $this->meteomaticApiService->getToken();
  1389.             return $this->json($result);
  1390.         } catch (\Exception $ex) {
  1391.             $this->logger->error($ex->getMessage());
  1392.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  1393.         }
  1394.     }
  1395.     /**
  1396.      * @Route("/api/public/weather/get-solar-power", methods={"POST"})
  1397.      */
  1398.     public function getSolarPowerAction(Request $request)
  1399.     {
  1400.         try {
  1401.             
  1402.             $params json_decode($request->getContent(), true);
  1403.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  1404.             // check user credentials and expiry// check user credentials and expiry
  1405.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1406.             if ($response['success'] !== true) {
  1407.                 return $this->json($response);
  1408.             }
  1409.             $mandatoryParams = ['latitude''longitude''hour''specification''interval_in_hours''start_date''end_date''unit'];
  1410.             foreach ($mandatoryParams as $param) {
  1411.                 if (!isset($params[$param]) || empty($params[$param])) {
  1412.                     $missingParams[] = $param;
  1413.                 }
  1414.             }
  1415.             if (!empty($missingParams)) {
  1416.                 // Throw an exception with a message that includes the missing parameters
  1417.                 $parameterList implode(", "$missingParams);
  1418.                 throw new \InvalidArgumentException(sprintf($this->translator->trans("missing_or_empty_mandatory_parameter: %s"), $parameterList));
  1419.             }
  1420.             // Extract the necessary parameters for getWeatherWarnings function  
  1421.             $coordinates = [[$params['latitude'], $params['longitude']]];
  1422.             $startDate $params['start_date'];
  1423.             $endDate $params['end_date'];
  1424.             $specification $params['specification'];
  1425.             $intervalInHours $params['interval_in_hours'];
  1426.             $hour $params['hour'];
  1427.             $unit $params['unit'];
  1428.             // Call the getWindPower function with validated parameters
  1429.             $result $this->meteomaticsWeatherService->getSolarPower($coordinates$startDate$endDate$intervalInHours$hour$unit$specification$this->translator);
  1430.             return $this->json($result);
  1431.         } catch (\Exception $ex) {
  1432.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  1433.         }
  1434.     }
  1435.     /**
  1436.      * @Route("/api/public/weather/air-density", methods={"POST"})
  1437.      */
  1438.     public function airdensityData(Request $request): JsonResponse
  1439.     {
  1440.         try {
  1441.             // check user credentials and expiry
  1442.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1443.             if ($response['success'] !== true) {
  1444.                 return $this->json($response);
  1445.             }
  1446.             $params json_decode($request->getContent(), true);
  1447.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  1448.             $requiredParameters = ['hour''start_date''end_date''coordinates''level''unit''format'];
  1449.             foreach ($requiredParameters as $param) {
  1450.                 if (!isset($params[$param])) {
  1451.                     $missingParams[] = $param;
  1452.                 }
  1453.             }
  1454.             if (!empty($missingParams)) {
  1455.                 // Throw an exception with a message that includes the missing parameters
  1456.                 $parameterList implode(", "$missingParams);
  1457.                 return $this->json(['success' => false'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
  1458.             }
  1459.             $hour $params['hour'];
  1460.             $startDate $params['start_date'];
  1461.             $endDate $params['end_date'];
  1462.             $coordinates $params['coordinates'];
  1463.             $level $params['level'];
  1464.             $unit $params['unit'];
  1465.             $format $params['format'];
  1466.             $response $this->meteomaticsWeatherService->getAirdensity(
  1467.                 $hour,
  1468.                 $startDate,
  1469.                 $endDate,
  1470.                 $coordinates,
  1471.                 $level,
  1472.                 $unit,
  1473.                 $format
  1474.             );
  1475.             // You can return or process the $data as needed
  1476.             // For demonstration purposes, we will just return a JSON response
  1477.             return $this->json($response);
  1478.         } catch (\Exception $ex) {
  1479.             $this->logger->error($ex->getMessage());
  1480.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  1481.         }
  1482.     }
  1483.     /**
  1484.      * @Route("/api/public/weather/get-metar-data", methods={"POST"})
  1485.      */
  1486.     public function getMetarData(Request $request): JsonResponse
  1487.     {
  1488.         try {
  1489.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1490.             if ($response['success'] !== true) {
  1491.                 return $this->json($response);
  1492.             }
  1493.             $params json_decode($request->getContent(), true);
  1494.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  1495.             $requiredParameters = ['startDate''endDate''metar''duration'];
  1496.             foreach ($requiredParameters as $param) {
  1497.                 if (!isset($params[$param])) {
  1498.                     $missingParams[] = $param;
  1499.                 }
  1500.             }
  1501.             if (!empty($missingParams)) {
  1502.                 // Throw an exception with a message that includes the missing parameters
  1503.                 $parameterList implode(", "$missingParams);
  1504.                 return $this->json(['success' => false'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
  1505.             }
  1506.             $startDate $params['startDate'];
  1507.             $endDate $params['endDate'];
  1508.             $metar $params['metar'];
  1509.             $duration $params['duration'];
  1510.             $parameters $params['parameter'] ?? null;
  1511.             $genExcel $request->get('gen_excel'false);
  1512.             $metarData $this->meteomaticsWeatherService->getMetarData($startDate$endDate$metar$duration$this->translator$parameters$genExcel);
  1513.             return $this->json(['success' => true'message' => $this->translator->trans("excel_file_downloaded_successfully"), 'data' => $metarData]);
  1514.         } catch (\Exception $ex) {
  1515.             $this->logger->error($ex->getMessage());
  1516.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  1517.         }
  1518.     }
  1519.     /**
  1520.      * @Route("/api/public/weather/frost-thaw-depth", methods={"POST"})
  1521.      */
  1522.     public function frostThawAndDepthData(Request $request): JsonResponse
  1523.     {
  1524.         try {
  1525.             // check user credentials and expiry
  1526.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1527.             if ($response['success'] !== true) {
  1528.                 return $this->json($response);
  1529.             }
  1530.             $params json_decode($request->getContent(), true);
  1531.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  1532.             $requiredParameters = ['hour''start_date''end_date''unit''coordinates''format'];
  1533.             foreach ($requiredParameters as $param) {
  1534.                 if (!isset($params[$param])) {
  1535.                     $missingParams[] = $param;
  1536.                 }
  1537.             }
  1538.             if (!empty($missingParams)) {
  1539.                 // Throw an exception with a message that includes the missing parameters
  1540.                 $parameterList implode(", "$missingParams);
  1541.                 return $this->json(['success' => false'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
  1542.             }
  1543.             $hour $params['hour'];
  1544.             $startDate $params['start_date'];
  1545.             $endDate $params['end_date'];
  1546.             $unit $params['unit'];
  1547.             $coordinates $params['coordinates'];
  1548.             $format $params['format'];
  1549.             $response $this->meteomaticsWeatherService->getFrostThawAndDepth(
  1550.                 $hour,
  1551.                 $startDate,
  1552.                 $endDate,
  1553.                 $unit,
  1554.                 $coordinates,
  1555.                 $format
  1556.             );
  1557.             // You can return or process the $data as needed
  1558.             // For demonstration purposes, we will just return a JSON response
  1559.             return $this->json($response);
  1560.         } catch (\Exception $ex) {
  1561.             $this->logger->error($ex->getMessage());
  1562.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  1563.         }
  1564.     }
  1565.     /**
  1566.      * @Route("/api/public/weather/get-hail-index", methods={"POST"})
  1567.      */
  1568.     public function getHailIndexAction(Request $request): JsonResponse
  1569.     {
  1570.         try {
  1571.             // check user credentials and expiry
  1572.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1573.             if ($response['success'] !== true) {
  1574.                 return $this->json($response);
  1575.             }
  1576.             $params json_decode($request->getContent(), true);
  1577.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  1578.             $mandatoryParams = ['coordinates''start_date''end_date''duration''interval_type'];
  1579.             foreach ($mandatoryParams as $param) {
  1580.                 if (!isset($params[$param]) || empty($params[$param])) {
  1581.                     $missingParams[] = $param;
  1582.                 }
  1583.             }
  1584.             if (!empty($missingParams)) {
  1585.                 // Throw an exception with a message that includes the missing parameters
  1586.                 $parameterList implode(", "$missingParams);
  1587.                 return $this->json(['success' => false'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
  1588.             }
  1589.             // Extract the necessary parameters for getWeatherWarnings function
  1590.             $coordinates $params['coordinates'];
  1591.             $startDate $params['start_date'];
  1592.             $endDate $params['end_date'];
  1593.             $intervalType $params['interval_type'];
  1594.             $duration $params['duration'] ?? '5';
  1595.             $format $params['format'] ?? 'json';
  1596.             // Call the getWeatherWarnings function with validated parameters
  1597.             $result $this->meteomaticsWeatherService->getHailIndex($coordinates$startDate$endDate$duration$intervalType$format$this->translator);
  1598.             return $this->json($result);
  1599.         } catch (\Exception $ex) {
  1600.             $this->logger->error($ex->getMessage());
  1601.             return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  1602.         }
  1603.     }
  1604.     /**
  1605.      * @Route("/api/public/weather/soil-moisture-index", methods={"POST"})
  1606.      */
  1607.     public function soilMoistureIndexData(Request $request): JsonResponse
  1608.     {
  1609.         try {
  1610.             // check user credentials and expiry
  1611.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1612.             if ($response['success'] !== true) {
  1613.                 return $this->json($response);
  1614.             }
  1615.             $params json_decode($request->getContent(), true);
  1616.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  1617.             $requiredParameters = ['hour''start_date''end_date''coordinates''level''unit''format'];
  1618.             foreach ($requiredParameters as $param) {
  1619.                 if (!isset($params[$param])) {
  1620.                     $missingParams[] = $param;
  1621.                 }
  1622.             }
  1623.             if (!empty($missingParams)) {
  1624.                 // Throw an exception with a message that includes the missing parameters
  1625.                 $parameterList implode(", "$missingParams);
  1626.                 return $this->json(['success' => false'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
  1627.             }
  1628.             $hour $params['hour'];
  1629.             $startDate $params['start_date'];
  1630.             $endDate $params['end_date'];
  1631.             $coordinates $params['coordinates'];
  1632.             $level $params['level'];
  1633.             $unit $params['unit'];
  1634.             $format $params['format'];
  1635.             $response $this->meteomaticsWeatherService->getSoilMoistureIndex(
  1636.                 $hour,
  1637.                 $startDate,
  1638.                 $endDate,
  1639.                 $coordinates,
  1640.                 $level,
  1641.                 $unit,
  1642.                 $format
  1643.             );
  1644.             // You can return or process the $data as needed
  1645.             // For demonstration purposes, we will just return a JSON response
  1646.             return $this->json($response);
  1647.         } catch (\Exception $ex) {
  1648.             $this->logger->error($ex->getMessage());
  1649.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  1650.         }
  1651.     }
  1652.     /**
  1653.      * @Route("/api/public/weather/get-moving-average", methods={"POST"})
  1654.      */
  1655.     public function getMovingAverage(Request $request): JsonResponse
  1656.     {
  1657.         try {
  1658.             // check user credentials and expiry
  1659.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1660.             if ($response['success'] !== true) {
  1661.                 return $this->json($response);
  1662.             }
  1663.             $params  json_decode($request->getContent(), true);
  1664.             $requiredParameters = ['start_from''days''location'"name"];
  1665.             foreach ($requiredParameters as $param) {
  1666.                 if (!isset($params[$param])) {
  1667.                     $missingParams[] = $param;
  1668.                 }
  1669.             }
  1670.             if (!empty($missingParams)) {
  1671.                 $parameterList implode(", "$missingParams);
  1672.                 return $this->json(['success' => false'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
  1673.             }
  1674.             switch ($params['name']) {
  1675.                 case 'temperature_day':
  1676.                     $data $this->insuranceIndustryService->mmTemperatureDay($params['start_from'], $params['days'], $params['location']);
  1677.                     break;
  1678.                 case 'temperature_night':
  1679.                     $data $this->insuranceIndustryService->mmTemperatureNight($params['start_from'], $params['days'], $params['location']);
  1680.                     break;
  1681.                 case 'wind_speed':
  1682.                     $data $this->insuranceIndustryService->mmWindSpeed($params['start_from'], $params['days'], $params['location']);
  1683.                     break;
  1684.                 case 'soil_water_content':
  1685.                     $data $this->insuranceIndustryService->mmSoilWaterContent($params['start_from'], $params['days'], $params['location']);
  1686.                     break;
  1687.                 default:
  1688.                     // Handle invalid function name
  1689.                     return $this->json(['success' => false'message' => 'Invalid name']);
  1690.             }
  1691.             return $this->json(['success' => true'data' => $data]);
  1692.         } catch (\Exception $ex) {
  1693.             $this->logger->error($ex->getMessage());
  1694.             return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  1695.         }
  1696.     }
  1697.     /**
  1698.      * @Route("/api/public/weather/heat-index", methods={"POST"})
  1699.      */
  1700.     public function heatIndexData(Request $request): JsonResponse
  1701.     {
  1702.         try {
  1703.             // check user credentials and expiry
  1704.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1705.             if ($response['success'] !== true) {
  1706.                 return $this->json($response);
  1707.             }
  1708.             $params json_decode($request->getContent(), true);
  1709.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  1710.             $requiredParameters = ['hour''start_date''end_date''coordinates''unit''format''model'];
  1711.             foreach ($requiredParameters as $param) {
  1712.                 if (!isset($params[$param])) {
  1713.                     $missingParams[] = $param;
  1714.                 }
  1715.             }
  1716.             if (!empty($missingParams)) {
  1717.                 // Throw an exception with a message that includes the missing parameters
  1718.                 $parameterList implode(", "$missingParams);
  1719.                 return $this->json(['success' => false'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
  1720.             }
  1721.             $hour $params['hour'];
  1722.             $startDate $params['start_date'];
  1723.             $endDate $params['end_date'];
  1724.             $coordinates $params['coordinates'];
  1725.             $unit $params['unit'];
  1726.             $format $params['format'];
  1727.             $model $params['model'];
  1728.             $response $this->meteomaticsWeatherService->getHeatIndex(
  1729.                 $hour,
  1730.                 $startDate,
  1731.                 $endDate,
  1732.                 $coordinates,
  1733.                 $unit,
  1734.                 $format,
  1735.                 $model
  1736.             );
  1737.             // You can return or process the $data as needed
  1738.             // For demonstration purposes, we will just return a JSON response
  1739.             return $this->json($response);
  1740.         } catch (\Exception $ex) {
  1741.             $this->logger->error($ex->getMessage());
  1742.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  1743.         }
  1744.     }
  1745.     /**
  1746.      * @Route("/api/public/weather/get-seasonal-average", methods={"POST"})
  1747.      */
  1748.     public function getSeasonalAverager(Request $request): JsonResponse
  1749.     {
  1750.         try {
  1751.             // check user credentials and expiry
  1752.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1753.             if ($response['success'] !== true) {
  1754.                 return $this->json($response);
  1755.             }
  1756.             $params  json_decode($request->getContent(), true);
  1757.             $requiredParameters = ['date''day_time''parameter''location'];
  1758.             foreach ($requiredParameters as $param) {
  1759.                 if (!isset($params[$param])) {
  1760.                     $missingParams[] = $param;
  1761.                 }
  1762.             }
  1763.             if (!empty($missingParams)) {
  1764.                 $parameterList implode(", "$missingParams);
  1765.                 return $this->json(['success' => false'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
  1766.             }
  1767.             $data $this->insuranceIndustryService->seasonalAverage($params['date'], $params['day_time'], $params['parameter'], $params['location']);
  1768.             return $this->json(['success' => true'data' => $data]);
  1769.         } catch (\Exception $ex) {
  1770.             $this->logger->error($ex->getMessage());
  1771.             return $this->json(['success' => false$this->translator->trans(USER_ERROR_MESSAGE)]);
  1772.         }
  1773.     }
  1774.     /**
  1775.      * @Route("/api/public/weather/get-threats-table", methods={"POST"})
  1776.      */
  1777.     public function getThreatTable(Request $request): JsonResponse
  1778.     {
  1779.         try {
  1780.             // check user credentials and expiry
  1781.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1782.             if ($response['success'] !== true) {
  1783.                 return $this->json($response);
  1784.             }
  1785.             $params  json_decode($request->getContent(), true);
  1786.             $requiredParameters = ['date''day_deep''location'];
  1787.             foreach ($requiredParameters as $param) {
  1788.                 if (!isset($params[$param])) {
  1789.                     $missingParams[] = $param;
  1790.                 }
  1791.             }
  1792.             if (!empty($missingParams)) {
  1793.                 $parameterList implode(", "$missingParams);
  1794.                 return $this->json(['success' => false'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
  1795.             }
  1796.             $data $this->insuranceIndustryService->threatTable($params['date'], $params['day_deep'], $params['location']);
  1797.             return $this->json(['success' => true'data' => $data]);
  1798.         } catch (\Exception $ex) {
  1799.             $this->logger->error($ex->getMessage());
  1800.             return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  1801.         }
  1802.     }
  1803.     /**
  1804.      * @Route("/api/public/weather/high-low-tide-times", methods={"POST"})
  1805.      */
  1806.     public function highLowTideTimesData(Request $request): JsonResponse
  1807.     {
  1808.         try {
  1809.             // check user credentials and expiry
  1810.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1811.             if ($response['success'] !== true) {
  1812.                 return $this->json($response);
  1813.             }
  1814.             $params json_decode($request->getContent(), true);
  1815.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  1816.             $requiredParameters = ['hour''start_date''end_date''coordinates''model''format'];
  1817.             foreach ($requiredParameters as $param) {
  1818.                 if (!isset($params[$param])) {
  1819.                     $missingParams[] = $param;
  1820.                 }
  1821.             }
  1822.             if (!empty($missingParams)) {
  1823.                 // Throw an exception with a message that includes the missing parameters
  1824.                 $parameterList implode(", "$missingParams);
  1825.                 return $this->json(['success' => false'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
  1826.             }
  1827.             $hour $params['hour'];
  1828.             $startDate $params['start_date'];
  1829.             $endDate $params['end_date'];
  1830.             $coordinates $params['coordinates'];
  1831.             $model $params['model'];
  1832.             $format $params['format'];
  1833.             $response $this->meteomaticsWeatherService->getHighLowTideTimes(
  1834.                 $hour,
  1835.                 $startDate,
  1836.                 $endDate,
  1837.                 $coordinates,
  1838.                 $model,
  1839.                 $format
  1840.             );
  1841.             // You can return or process the $data as needed
  1842.             // For demonstration purposes, we will just return a JSON response
  1843.             return $this->json($response);
  1844.         } catch (\Exception $ex) {
  1845.             $this->logger->error($ex->getMessage());
  1846.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  1847.         }
  1848.     }
  1849.     /**
  1850.      * @Route("/api/public/weather/tidal-amplitude", methods={"POST"})
  1851.      */
  1852.     public function tidalAmplitudeData(Request $request): JsonResponse
  1853.     {
  1854.         try {
  1855.             // check user credentials and expiry
  1856.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1857.             if ($response['success'] !== true) {
  1858.                 return $this->json($response);
  1859.             }
  1860.             $params json_decode($request->getContent(), true);
  1861.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  1862.             $requiredParameters = ['hour''start_date''end_date''coordinates''unit''model''format'];
  1863.             foreach ($requiredParameters as $param) {
  1864.                 if (!isset($params[$param])) {
  1865.                     $missingParams[] = $param;
  1866.                 }
  1867.             }
  1868.             if (!empty($missingParams)) {
  1869.                 // Throw an exception with a message that includes the missing parameters
  1870.                 $parameterList implode(", "$missingParams);
  1871.                 return $this->json(['success' => false'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
  1872.             }
  1873.             $hour $params['hour'];
  1874.             $startDate $params['start_date'];
  1875.             $endDate $params['end_date'];
  1876.             $coordinates $params['coordinates'];
  1877.             $unit $params['unit'];
  1878.             $model $params['model'];
  1879.             $format $params['format'];
  1880.             $response $this->meteomaticsWeatherService->getTidalAmplitudes(
  1881.                 $hour,
  1882.                 $startDate,
  1883.                 $endDate,
  1884.                 $coordinates,
  1885.                 $unit,
  1886.                 $model,
  1887.                 $format
  1888.             );
  1889.             // You can return or process the $data as needed
  1890.             // For demonstration purposes, we will just return a JSON response
  1891.             return $this->json($response);
  1892.         } catch (\Exception $ex) {
  1893.             $this->logger->error($ex->getMessage());
  1894.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  1895.         }
  1896.     }
  1897.     /**
  1898.      * @Route("/api/public/weather/significant-wave-height", methods={"POST"})
  1899.      */
  1900.     public function significantWaveHeightData(Request $request): JsonResponse
  1901.     {
  1902.         try {
  1903.             // check user credentials and expiry
  1904.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1905.             if ($response['success'] !== true) {
  1906.                 return $this->json($response);
  1907.             }
  1908.             $params json_decode($request->getContent(), true);
  1909.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  1910.             $requiredParameters = ['hour''start_date''end_date''coordinates''format'];
  1911.             foreach ($requiredParameters as $param) {
  1912.                 if (!isset($params[$param])) {
  1913.                     $missingParams[] = $param;
  1914.                 }
  1915.             }
  1916.             if (!empty($missingParams)) {
  1917.                 // Throw an exception with a message that includes the missing parameters
  1918.                 $parameterList implode(", "$missingParams);
  1919.                 return $this->json(['success' => false'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
  1920.             }
  1921.             $hour $params['hour'];
  1922.             $startDate $params['start_date'];
  1923.             $endDate $params['end_date'];
  1924.             $coordinates $params['coordinates'];
  1925.             $format $params['format'];
  1926.             $response $this->meteomaticsWeatherService->getSignificantWaveHeight(
  1927.                 $hour,
  1928.                 $startDate,
  1929.                 $endDate,
  1930.                 $coordinates,
  1931.                 $format
  1932.             );
  1933.             // You can return or process the $data as needed
  1934.             // For demonstration purposes, we will just return a JSON response
  1935.             return $this->json($response);
  1936.         } catch (\Exception $ex) {
  1937.             $this->logger->error($ex->getMessage());
  1938.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  1939.         }
  1940.     }
  1941.     /**
  1942.      * @Route("/api/public/weather/surge-amplitude", methods={"POST"})
  1943.      */
  1944.     public function surgeAmplitudeData(Request $request): JsonResponse
  1945.     {
  1946.         try {
  1947.             // check user credentials and expiry
  1948.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1949.             if ($response['success'] !== true) {
  1950.                 return $this->json($response);
  1951.             }
  1952.             $params json_decode($request->getContent(), true);
  1953.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  1954.             $requiredParameters = ['hour''start_date''end_date''coordinates''unit''model''format'];
  1955.             foreach ($requiredParameters as $param) {
  1956.                 if (!isset($params[$param])) {
  1957.                     $missingParams[] = $param;
  1958.                 }
  1959.             }
  1960.             if (!empty($missingParams)) {
  1961.                 // Throw an exception with a message that includes the missing parameters
  1962.                 $parameterList implode(", "$missingParams);
  1963.                 return $this->json(['success' => false'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
  1964.             }
  1965.             $hour $params['hour'];
  1966.             $startDate $params['start_date'];
  1967.             $endDate $params['end_date'];
  1968.             $coordinates $params['coordinates'];
  1969.             $unit $params['unit'];
  1970.             $model $params['model'];
  1971.             $format $params['format'];
  1972.             $response $this->meteomaticsWeatherService->getSurgeAmplitude(
  1973.                 $hour,
  1974.                 $startDate,
  1975.                 $endDate,
  1976.                 $coordinates,
  1977.                 $unit,
  1978.                 $model,
  1979.                 $format
  1980.             );
  1981.             // You can return or process the $data as needed
  1982.             // For demonstration purposes, we will just return a JSON response
  1983.             return $this->json($response);
  1984.         } catch (\Exception $ex) {
  1985.             $this->logger->error($ex->getMessage());
  1986.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  1987.         }
  1988.     }
  1989.     /**
  1990.      * @Route("/api/public/weather/fog", methods={"POST"})
  1991.      */
  1992.     public function fogData(Request $request): JsonResponse
  1993.     {
  1994.         try {
  1995.             // check user credentials and expiry
  1996.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  1997.             if ($response['success'] !== true) {
  1998.                 return $this->json($response);
  1999.             }
  2000.             $params json_decode($request->getContent(), true);
  2001.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  2002.             $requiredParameters = ['start_date''end_date''coordinates''format'];
  2003.             foreach ($requiredParameters as $param) {
  2004.                 if (!isset($params[$param])) {
  2005.                     $missingParams[] = $param;
  2006.                 }
  2007.             }
  2008.             if (!empty($missingParams)) {
  2009.                 // Throw an exception with a message that includes the missing parameters
  2010.                 $parameterList implode(", "$missingParams);
  2011.                 return $this->json(['success' => false'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
  2012.             }
  2013.             $startDate $params['start_date'];
  2014.             $endDate $params['end_date'];
  2015.             $interval $params['interval'];
  2016.             $unit $params['unit'];
  2017.             $coordinates $params['coordinates'];
  2018.             $format $params['format'];
  2019.             $response $this->meteomaticsWeatherService->getFog(
  2020.                 $coordinates,
  2021.                 $startDate,
  2022.                 $endDate,
  2023.                 $interval,
  2024.                 $unit,
  2025.                 $this->translator,
  2026.                 $format
  2027.             );
  2028.             // You can return or process the $data as needed
  2029.             // For demonstration purposes, we will just return a JSON response
  2030.             return $this->json($response);
  2031.         } catch (\Exception $ex) {
  2032.             $this->logger->error($ex->getMessage());
  2033.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  2034.         }
  2035.     }
  2036.     /**
  2037.      * @Route("/api/public/weather/generic-api", methods={"POST"})
  2038.      */
  2039.     public function fetchMeteomaticData(Request $request): JsonResponse
  2040.     {
  2041.         $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  2042.         if ($response['success'] !== true) {
  2043.             return $this->json($response);
  2044.         }
  2045.         $params json_decode($request->getContent(), true);
  2046.         $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  2047.         if (!isset($params['format'])) {
  2048.             throw new \InvalidArgumentException('Missing "format" parameter');
  2049.         }
  2050.         if ($params['format'] == "json") {
  2051.             if (
  2052.                 !isset($params['startdate']) ||
  2053.                 !isset($params['enddate']) ||
  2054.                 !isset($params['resolution']) ||
  2055.                 !isset($params['parameters']) ||
  2056.                 !isset($params['lat']) ||
  2057.                 !isset($params['lon']) ||
  2058.                 !isset($params['format'])
  2059.             ) {
  2060.                 throw new \Exception('Missing required parameters');
  2061.             }
  2062.             // date_default_timezone_set('UTC');
  2063.             //$hour = $params['hour'];
  2064.             $format $params['format'];
  2065.             $startDate $params['startdate'];
  2066.             $endDate $params['enddate'];
  2067.             $resolution $params['resolution'];
  2068.             $parameters $params['parameters'];
  2069.             $model $params['model'];
  2070.             $lat $params['lat'];
  2071.             $lon $params['lon'];
  2072.             $response $this->meteomaticApiService->timeSeriesQuery(
  2073.                 $startDate,
  2074.                 $endDate,
  2075.                 $resolution,
  2076.                 $parameters,
  2077.                 $model,
  2078.                 $lat,
  2079.                 $lon,
  2080.                 $format,
  2081.                 $this->translator
  2082.             );
  2083.         } else {
  2084.             $mandatoryParams = ['version''request''layers''crs''bbox''format''width''height''tiled'];
  2085.             foreach ($mandatoryParams as $param) {
  2086.                 if (!isset($params[$param]) || empty($params[$param])) {
  2087.                     $missingParams[] = $param;
  2088.                 }
  2089.             }
  2090.             if (!empty($missingParams)) {
  2091.                 // Throw an exception with a message that includes the missing parameters
  2092.                 $parameterList implode(", "$missingParams);
  2093.                 throw new \InvalidArgumentException(sprintf($this->translator->trans("missing_or_empty_mandatory_parameter: %s"), $parameterList));
  2094.             }
  2095.             header('Content-Type: image/png');
  2096.             $result $this->meteomaticsWeatherService->getWeatherMap($params['version'], $params['request'], $params['layers'], $params['crs'], $params['bbox'], $params['format'], $params['width'], $params['height'], $params['tiled']);
  2097.             echo $result;
  2098.             exit;
  2099.         }
  2100.         // You can return or process the $data as needed
  2101.         // For demonstration purposes, we will just return a JSON response
  2102.         return $this->json($response);
  2103.     }
  2104.     /**
  2105.      * @Route("/api/public/weather/top-ten-weather-station", methods={"POST"})
  2106.      */
  2107.     public function topTenWeatherStation(Request $request): JsonResponse
  2108.     {
  2109.         try {
  2110.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  2111.             if ($response['success'] !== true) {
  2112.                 return $this->json($response);
  2113.             }
  2114.             $params  json_decode($request->getContent(), true);
  2115.             // $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  2116.             $requiredParameters = ['parameter''from_date''to_date'];
  2117.             foreach ($requiredParameters as $param) {
  2118.                 if (!isset($params[$param])) {
  2119.                     $missingParams[] = $param;
  2120.                 }
  2121.             }
  2122.             if (!empty($missingParams)) {
  2123.                 // Throw an exception with a message that includes the missing parameters
  2124.                 $parameterList implode(", "$missingParams);
  2125.                 return $this->json(['success' => false'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
  2126.             }
  2127.             $lang = (isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  2128.             $result $this->weatherStationModel->getTopTenWeatherStations($params['parameter'], $params['from_date'], $params['to_date'], $lang);
  2129.             return $this->json($result);
  2130.         } catch (\Exception $ex) {
  2131.             $this->logger->error($ex->getMessage());
  2132.             return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  2133.         }
  2134.     }
  2135.     /**
  2136.      * @Route("/api/public/weather/get-historical-data-parameters", methods={"POST"})
  2137.      */
  2138.     public function getHistoricalDataParameters(Request $request): JsonResponse
  2139.     {
  2140.         try {
  2141.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  2142.             if ($response['success'] !== true) {
  2143.                 return $this->json($response);
  2144.             }
  2145.             $data = [];
  2146.             $historicalDataParameters = new HistoricalDataParameters\Listing();
  2147.             foreach ($historicalDataParameters as $key => $historicalDataParameter) {
  2148.                 if ($historicalDataParameter) {
  2149.                     $data[] = [
  2150.                         "id" => $historicalDataParameter->getId(),
  2151.                         "key" => $historicalDataParameter->getParameterKey(),
  2152.                         "unit" => $historicalDataParameter->getUnit('en'),
  2153.                         "unit_ar" => $historicalDataParameter->getUnit('ar'),
  2154.                         "name" => $historicalDataParameter->getName('en'),
  2155.                         "name_ar" => $historicalDataParameter->getName('ar')
  2156.                     ];
  2157.                 }
  2158.             }
  2159.             return $this->json(['success' => true'data' => $data]);
  2160.         } catch (\Exception $ex) {
  2161.             $this->logger->error($ex->getMessage());
  2162.             return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  2163.         }
  2164.     }
  2165.     /**
  2166.      * @Route("api/public/weather-data/{start_date}/{end_date}/{resolution}/{parameter}/{coordinate}/{format}", name="api_dynamic_temperature_weather_data", methods={"GET"})
  2167.      */
  2168.     public function getDynamicTemperatureWeatherData(
  2169.         Request $request,
  2170.         string $start_date,
  2171.         string $end_date,
  2172.         string $resolution,
  2173.         string $parameter,
  2174.         string $coordinate,
  2175.         string $format
  2176.     ): Response {
  2177.         try {
  2178.             // Check user authorization
  2179.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  2180.             if ($response['success'] !== true) {
  2181.                 return $this->json($response);
  2182.             }
  2183.             $user $response['user'];
  2184.             // Optional query parameters
  2185.             $queryParams $request->query->all();
  2186.             // Build Meteomatics-style path
  2187.             // Example: 2025-12-06T00:00:00Z--2025-12-07T00:00:00Z:PT1H/t_2m:C,t_20m:C/.../json
  2188.             $path sprintf(
  2189.                 "%s--%s:%s/%s/%s",
  2190.                 $start_date,
  2191.                 $end_date,
  2192.                 $resolution,
  2193.                 $parameter,
  2194.                 $coordinate
  2195.             );
  2196.             // Add format at the end
  2197.             $path .= '/' $format;
  2198.             // Call Meteomatics API service
  2199.             $weatherData $this->meteomaticApiService->getDynamicWeatherData($path$queryParams$user);
  2200.             return $weatherData;
  2201.         } catch (\Exception $ex) {
  2202.             $this->logger->error($ex->getMessage());
  2203.             return $this->json([
  2204.                 'success' => false,
  2205.                 'message' => $this->translator->trans(USER_ERROR_MESSAGE)
  2206.             ]);
  2207.         }
  2208.     }
  2209.     /**
  2210.      * @Route("/api/public/get-alert-type", methods={"POST"})
  2211.      */
  2212.     public function getAlertTypeAction(Request $request): JsonResponse
  2213.     {
  2214.         try {
  2215.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  2216.             if ($response['success'] !== true) {
  2217.                 return $this->json($response);
  2218.             }
  2219.             $result $this->ewsNotificationModel->getAlertTypes();
  2220.             return $this->json($result);
  2221.         } catch (\Exception $ex) {
  2222.             $this->logger->error($ex->getMessage());
  2223.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  2224.         }
  2225.     }
  2226.     /**
  2227.      * @Route("/api/public/get-alert-action", methods={"POST"})
  2228.      */
  2229.     public function getAlertActionAction(Request $request): JsonResponse
  2230.     {
  2231.         try {
  2232.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  2233.             if ($response['success'] !== true) {
  2234.                 return $this->json($response);
  2235.             }
  2236.             $params json_decode($request->getContent(), true);
  2237.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  2238.             $result $this->ewsNotificationModel->getAlertActions();
  2239.             return $this->json($result);
  2240.         } catch (\Exception $ex) {
  2241.             $this->logger->error($ex->getMessage());
  2242.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  2243.         }
  2244.     }
  2245.     /**
  2246.      * @Route("/api/public/get-phenomena-list-by-alerts", methods={"POST"})
  2247.      */
  2248.     public function getPhenomenaListByAlertsAction(Request $request): JsonResponse
  2249.     {
  2250.         try {
  2251.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  2252.             if ($response['success'] !== true) {
  2253.                 return $this->json($response);
  2254.             }
  2255.             $params json_decode($request->getContent(), true);
  2256.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  2257.             if (!isset($params['alert_id']) && !empty($params['alert_id'])) {
  2258.                 throw new \Exception('Missing required alert id');
  2259.             }
  2260.             $alertType $params['alert_id'];
  2261.             // $result = $this->ewsNotificationModel->getPhenomenaListByAlertIds($alertType);
  2262.             $result $this->ewsNotificationModel->getAlertStatuses($params);
  2263.             return $this->json($result);
  2264.         } catch (\Exception $ex) {
  2265.             $this->logger->error($ex->getMessage());
  2266.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  2267.         }
  2268.     }
  2269.     /**
  2270.      * @Route("/api/public/get-regions-list", methods={"POST"})
  2271.      */
  2272.     public function getRegionsListAction(Request $request): JsonResponse
  2273.     {
  2274.         try {
  2275.             $params json_decode($request->getContent(), true);
  2276.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  2277.             // check user credentials and expiry
  2278.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  2279.             if ($response['success'] !== true) {
  2280.                 return $this->json($response);
  2281.             }
  2282.             $search = (isset($params['search']) && !empty($params['search'])) ? $params['search'] : null;
  2283.             $id = (isset($params['id']) && !empty($params['id'])) ? $params['id'] : null;
  2284.             $result $this->ncmWeatherApiService->getRegionsByName($search$id, isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  2285.             return $this->json($result);
  2286.         } catch (\Exception $ex) {
  2287.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  2288.         }
  2289.     }
  2290.     /**
  2291.      * @Route("/api/public/get-governorates-list", methods={"POST"})
  2292.      */
  2293.     public function getGovernoratesListAction(Request $request): JsonResponse
  2294.     {
  2295.         try {
  2296.             $params json_decode($request->getContent(), true);
  2297.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  2298.             // check user credentials and expiry
  2299.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  2300.             if ($response['success'] !== true) {
  2301.                 return $this->json($response);
  2302.             }
  2303.             $result $this->ewsNotificationModel->getGovernoratesByParams($params);
  2304.             return $this->json($result);
  2305.         } catch (\Exception $ex) {
  2306.             $this->logger->error($ex->getMessage());
  2307.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  2308.         }
  2309.     }
  2310.     /**
  2311.      * @Route("/api/public/get-municipality-list", methods={"POST"})
  2312.      */
  2313.     public function getMunicipalityListAction(Request $request): JsonResponse
  2314.     {
  2315.         try {
  2316.             $params json_decode($request->getContent(), true);
  2317.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  2318.             // check user credentials and expiry
  2319.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  2320.             if ($response['success'] !== true) {
  2321.                 return $this->json($response);
  2322.             }
  2323.             if (!isset($params['governorate_id'])) {
  2324.                 throw new \Exception('Missing required governorate id');
  2325.             }
  2326.             $governorateId $params['governorate_id'];
  2327.             $search = (isset($params['search']) && !empty($params['search'])) ? $params['search'] : null;
  2328.             $result $this->ewsNotificationModel->getMunicipalityByParams($governorateId$search$params['lang']);
  2329.             return $this->json($result);
  2330.         } catch (\Exception $ex) {
  2331.             $this->logger->error($ex->getMessage());
  2332.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  2333.         }
  2334.     }
  2335.     /**
  2336.      * @Route("/api/public/list-tbase-crops", methods={"POST"})
  2337.      */
  2338.      public function listTbaseCropsAction(Request $requestPaginatorInterface $paginator)
  2339.      {
  2340.          try {
  2341.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  2342.             if ($response['success'] !== true) {
  2343.                 return $this->json($response);
  2344.             }
  2345.             $params json_decode($request->getContent(), true);
  2346.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  2347.              $crops $this->agricultureModel->getTbaseCrops($params$this->translator$paginator);
  2348.              return $this->json(['success' => true'data' => $crops]);
  2349.          } catch (\Exception $ex) {
  2350.              $this->logger->error($ex->getMessage());
  2351.              return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  2352.          }
  2353.     }
  2354.     /**
  2355.      * @Route("/api/public/get-chill-units", methods={"POST"})
  2356.     */
  2357.     public function getChillUnitsAction(Request $request): JsonResponse
  2358.     {
  2359.         try {
  2360.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  2361.             if ($response['success'] !== true) {
  2362.                 return $this->json($response);
  2363.             }
  2364.             $params json_decode($request->getContent(), true);
  2365.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  2366.             $isAccumulated $params['isAccumulated'] ?? false;
  2367.             $latitude $params['latitude'] ?? null;
  2368.             $longitude $params['longitude'] ?? null;
  2369.             $coordinate "$latitude,$longitude";
  2370.             $parametersArray = ['t_min_2m_1h:C''t_max_2m_1h:C'];
  2371.             $startDate = new DateTime($params['startDate']);
  2372.             $endDate = new DateTime($params['endDate']);
  2373.             
  2374.             $resolution 'PT1H';
  2375.             $format 'json';
  2376.             $model 'mix';
  2377.             $source '';
  2378.             $onInvalid '';
  2379.             
  2380.             $response $this->meteomaticApiService->publicRouteQuery(
  2381.                 $startDate,
  2382.                 $endDate,
  2383.                 $resolution,
  2384.                 $parametersArray,
  2385.                 $coordinate,
  2386.                 $format,
  2387.                 $model,
  2388.                 $source,
  2389.                 $onInvalid,
  2390.             );
  2391.             $hourlyData $this->chillUnitService->transformMeteomaticsResponse($response['data']);
  2392.             if ($isAccumulated) {
  2393.                 $result $this->chillUnitService->calculateAccumulated($hourlyData);
  2394.             } else {
  2395.                 $result $this->chillUnitService->calculate($hourlyData);
  2396.             }
  2397.             return $this->json($result);
  2398.         } catch (\Exception $ex) {
  2399.             $this->logger->error($ex->getMessage());
  2400.             return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  2401.         }
  2402.     }
  2403.     /**
  2404.      * @Route("/api/public/get-water-requirements", methods={"POST"})
  2405.     */
  2406.     public function getWaterRequirementAction(Request $request): JsonResponse
  2407.     {
  2408.         try {
  2409.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  2410.             if ($response['success'] !== true) {
  2411.                 return $this->json($response);
  2412.             }
  2413.             $params json_decode($request->getContent(), true);
  2414.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  2415.             $regionIds = [];
  2416.             
  2417.             $latitude $params['latitude'] ?? null;
  2418.             $longitude $params['longitude'] ?? null;
  2419.             $coordinate "$latitude,$longitude";
  2420.             
  2421.             $governorateArr \App\Lib\Utility::processLocationCoordinates([[$latitude$longitude]]);
  2422.             foreach ($governorateArr as $governorateName) {
  2423.                 if ($governorateName['en']) {
  2424.                     $governorate DataObject\Governorate::getByName($governorateName['en'],'en',true);
  2425.                     if ($governorate instanceof DataObject\Governorate) {
  2426.                         // Assuming getRegion() returns a Region DataObject
  2427.                         $region $governorate->getRegionId();
  2428.                         $regionIds[] = $region->getId();
  2429.                     }
  2430.                 }
  2431.             }
  2432.             $parametersArray = ['evapotranspiration_24h:mm'];
  2433.             $startDate = new DateTime();
  2434.             $endDate = new DateTime();
  2435.             $resolution 'PT24H';
  2436.             $format 'json';
  2437.             $model 'mix';
  2438.             $source '';
  2439.             $onInvalid '';
  2440.             $kcKeys $params['kcKeys'] ?? ['kcInitial''kcMid''kcEnd'];
  2441.             $cropNames $params['cropNames'] ?? [];
  2442.             $response $this->meteomaticApiService->publicRouteQuery(
  2443.                 $startDate,
  2444.                 $endDate,
  2445.                 $resolution,
  2446.                 $parametersArray,
  2447.                 $coordinate,
  2448.                 $format,
  2449.                 $model,
  2450.                 $source,
  2451.                 $onInvalid,
  2452.             );
  2453.             $meteoData $response['data']['data'][0]['coordinates'];
  2454.             $cropsData $this->agricultureModel->getCropsWithRegion($regionIds$cropNames$kcKeys$meteoData);
  2455.             return $this->json($cropsData);
  2456.          } catch (\Exception $ex) {
  2457.             $this->logger->error($ex->getMessage());
  2458.             return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  2459.         }
  2460.     }
  2461.     /**
  2462.      * @Route("/api/public/calculate-gdd-and-gts", methods={"POST"})
  2463.      */
  2464.     public function calculateGDDandGTSAction(Request $request): JsonResponse
  2465.     {
  2466.         try {
  2467.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  2468.             if ($response['success'] !== true) {
  2469.                 return $this->json($response);
  2470.             }
  2471.             $params json_decode($request->getContent(), true);
  2472.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  2473.             $params json_decode($request->getContent(), true);
  2474.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  2475.             $requiredParameters = [
  2476.                 'coordinates',
  2477.                 'cropIds',
  2478.                 'startDate',
  2479.                 'endDate'
  2480.             ];
  2481.          
  2482.             foreach ($requiredParameters as $param) {
  2483.                 if (!isset($params[$param])) {
  2484.                     $missingParams[] = $param;
  2485.                 }
  2486.             }
  2487.             if (!empty($missingParams)) {
  2488.                 // Throw an exception with a message that includes the missing parameters
  2489.                 $parameterList implode(", "$missingParams);
  2490.                 return $this->json(['success' => false'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
  2491.             }
  2492.             $params['meteomaticApiService'] = $this->meteomaticApiService;
  2493.             $gddAndGtsData $this->agricultureModel->calculateGDDandGTS($params,$this->translator);
  2494.             return $this->json($gddAndGtsData);
  2495.         } catch (\Exception $ex) {
  2496.             $this->logger->error($ex->getMessage());
  2497.             return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  2498.         }
  2499.     }
  2500.     /**
  2501.      * @Route("/api/public/crops", methods={"POST"})
  2502.      */
  2503.     public function cropsAction(Request $request): JsonResponse
  2504.     {
  2505.         try {
  2506.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  2507.             if ($response['success'] !== true) {
  2508.                 return $this->json($response);
  2509.             }
  2510.             $params json_decode($request->getContent(), true);
  2511.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  2512.             $result $this->agricultureModel->getCrops($request$params$this->translator);
  2513.             return $this->json($result);
  2514.         } catch (\Exception $ex) {
  2515.             $this->logger->error($ex->getMessage());
  2516.             return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  2517.         }
  2518.     }
  2519.     /**
  2520.      * @Route("/api/public/list-location", methods={"POST"})
  2521.      */
  2522.     public function listLocation(Request $requestPaginatorInterface $paginator): JsonResponse
  2523.     {
  2524.         try {
  2525.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  2526.             if ($response['success'] !== true) {
  2527.                 return $this->json($response);
  2528.             }
  2529.             $applicationName $request->headers->get('X-App-Name');
  2530.             $applicationConsumer $request->headers->get('X-App-Consumer-Key');
  2531.             if (!$applicationName || !$applicationConsumer) {
  2532.                 return $this->json(['success' => false,'message' => 'Missing required headers']);
  2533.             }
  2534.             $user DataObject\Customer::getByEmail($applicationNametrue);
  2535.             if (!$user) {
  2536.                 return $this->json([
  2537.                     'success' => false,
  2538.                     'message' => 'Invalid User'
  2539.                 ]);
  2540.             }
  2541.             $application DataObject\WSO2Applications::getByUser($usertrue);
  2542.             if (!$application) {
  2543.                 return $this->json([
  2544.                     'success' => false,
  2545.                     'message' => 'User not found'
  2546.                 ]);
  2547.             }
  2548.             // 5. Consumer key validation
  2549.             if ($application->getConsumerKey() !== $applicationConsumer) {
  2550.                 return $this->json([
  2551.                     'success' => false,
  2552.                     'message' => 'Invalid Consumer Key'
  2553.                 ]);
  2554.             }
  2555.             $params json_decode($request->getContent(), true);
  2556.             $this->translator->setlocale($params['lang'] ?? DEFAULT_LOCALE);
  2557.             $result $this->locationModel->locationListing(
  2558.                 $request,
  2559.                 $user,
  2560.                 $params,
  2561.                 $paginator,
  2562.                 $this->translator
  2563.             );
  2564.             return $this->json($result);
  2565.         } catch (\Exception $ex) {
  2566.             $this->logger->error($ex->getMessage());
  2567.             return $this->json([
  2568.                 'success' => false,
  2569.                 'message' => $ex->getMessage()
  2570.             ]);
  2571.         }
  2572.     }
  2573.     /**
  2574.      * @Route("/api/public/list-risk-category", methods={"POST"})
  2575.      */
  2576.     public function getRiskCategories(Request $requestPaginatorInterface $paginator)
  2577.     {
  2578.        try {
  2579.            $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  2580.            if ($response['success'] !== true) {
  2581.                return $this->json($response);
  2582.            }
  2583.            $applicationName $request->headers->get('X-App-Name');
  2584.            $applicationConsumer $request->headers->get('X-App-Consumer-Key');
  2585.            if (!$applicationName || !$applicationConsumer) {
  2586.                return $this->json(['success' => false,'message' => 'Missing required headers']);
  2587.            }
  2588.            $user DataObject\Customer::getByEmail($applicationNametrue);
  2589.            if (!$user) {
  2590.                return $this->json([
  2591.                    'success' => false,
  2592.                    'message' => 'Invalid User'
  2593.                ]);
  2594.            }
  2595.            $application DataObject\WSO2Applications::getByUser($usertrue);
  2596.            if (!$application) {
  2597.                return $this->json([
  2598.                    'success' => false,
  2599.                    'message' => 'User not found'
  2600.                ]);
  2601.            }
  2602.            // 5. Consumer key validation
  2603.            if ($application->getConsumerKey() !== $applicationConsumer) {
  2604.                return $this->json([
  2605.                    'success' => false,
  2606.                    'message' => 'Invalid Consumer Key'
  2607.                ]);
  2608.            }
  2609.            $params json_decode($request->getContent(), true);
  2610.            $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  2611.     
  2612.            $requiredParameters = [];
  2613.            foreach ($requiredParameters as $param) {
  2614.                if (!isset($params[$param])) {
  2615.                    $missingParams[] = $param;
  2616.                }
  2617.            }
  2618.            if (!empty($missingParams)) {
  2619.                // Throw an exception with a message that includes the missing parameters
  2620.                $parameterList implode(", "$missingParams);
  2621.                return $this->json(['success' => false'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
  2622.            }
  2623.            
  2624.            $result $this->weatherParameterModel->riskCategoryFetch($params$paginator$user);
  2625.            return $this->json($result); 
  2626.        } catch (\Exception $ex) {
  2627.            $this->logger->error($ex->getMessage());
  2628.            return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  2629.        }
  2630.     }
  2631.     /**
  2632.      * @Route("/api/public/locations-for-map", methods={"POST"})
  2633.      */
  2634.     public function getLocationsForMaps(Request $request): JsonResponse
  2635.     {
  2636.        try {
  2637.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  2638.             if ($response['success'] !== true) {
  2639.                 return $this->json($response);
  2640.             }
  2641.             $applicationName $request->headers->get('X-App-Name');
  2642.             $applicationConsumer $request->headers->get('X-App-Consumer-Key');
  2643.  
  2644.             if (!$applicationName || !$applicationConsumer) {
  2645.                 return $this->json(['success' => false,'message' => 'Missing required headers']);
  2646.             }
  2647.  
  2648.             $user DataObject\Customer::getByEmail($applicationNametrue);
  2649.             if (!$user) {
  2650.                 return $this->json([
  2651.                     'success' => false,
  2652.                     'message' => 'Invalid User'
  2653.                 ]);
  2654.             }
  2655.  
  2656.             $application DataObject\WSO2Applications::getByUser($usertrue);
  2657.             if (!$application) {
  2658.                 return $this->json([
  2659.                     'success' => false,
  2660.                     'message' => 'User not found'
  2661.                 ]);
  2662.             }
  2663.  
  2664.             // 5. Consumer key validation
  2665.             if ($application->getConsumerKey() !== $applicationConsumer) {
  2666.                 return $this->json([
  2667.                     'success' => false,
  2668.                     'message' => 'Invalid Consumer Key'
  2669.                 ]);
  2670.             }
  2671.             $params json_decode($request->getContent(), true);
  2672.             $parameter $params['parameter'] ?? null;
  2673.             $duration $params['duration'] ?? null;
  2674.             $dateTime $params['datetime'] ?? null;
  2675.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  2676.             if (!$parameter || !$duration || !$dateTime) {
  2677.                 return new JsonResponse(['success' => false'message' => $this->translator->trans('missing_parameter_or_duration_or_date')], 400);
  2678.             }
  2679.             $results $this->weatherParameterModel->getLocationsForMaps($params$parameter$duration$dateTime$user$this->translator);
  2680.            return $this->json(['success' => true'data' => $results]); 
  2681.        } catch (\Exception $ex) {
  2682.            $this->logger->error($ex->getMessage());
  2683.            return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  2684.        }
  2685.     }
  2686.     /**
  2687.      * @Route("/api/public/locations-by-dates", methods={"POST"})
  2688.      */
  2689.     public function getLocationsByDates(Request $request): JsonResponse
  2690.     {
  2691.        try {
  2692.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  2693.             if ($response['success'] !== true) {
  2694.                 return $this->json($response);
  2695.             }
  2696.             $applicationName $request->headers->get('X-App-Name');
  2697.             $applicationConsumer $request->headers->get('X-App-Consumer-Key');
  2698.  
  2699.             if (!$applicationName || !$applicationConsumer) {
  2700.                 return $this->json(['success' => false,'message' => 'Missing required headers']);
  2701.             }
  2702.  
  2703.             $user DataObject\Customer::getByEmail($applicationNametrue);
  2704.             if (!$user) {
  2705.                 return $this->json([
  2706.                     'success' => false,
  2707.                     'message' => 'Invalid User'
  2708.                 ]);
  2709.             }
  2710.  
  2711.             $application DataObject\WSO2Applications::getByUser($usertrue);
  2712.             if (!$application) {
  2713.                 return $this->json([
  2714.                     'success' => false,
  2715.                     'message' => 'User not found'
  2716.                 ]);
  2717.             }
  2718.  
  2719.             // 5. Consumer key validation
  2720.             if ($application->getConsumerKey() !== $applicationConsumer) {
  2721.                 return $this->json([
  2722.                     'success' => false,
  2723.                     'message' => 'Invalid Consumer Key'
  2724.                 ]);
  2725.             }
  2726.             $params json_decode($request->getContent(), true);
  2727.             $parameter $params['parameter'] ?? null;
  2728.             $duration $params['duration'] ?? null;
  2729.             $dateTime $params['datetime'] ?? null;
  2730.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  2731.             if (!$parameter || !$duration || !$dateTime) {
  2732.                 return new JsonResponse(['success' => false'message' => $this->translator->trans('missing_parameter_or_duration_or_date')], 400);
  2733.             }
  2734.            $results $this->weatherParameterModel->getLocationsbyDates($parameter$duration$dateTime$this->translator);
  2735.            return $this->json(['success' => true"lastUpdated" => $results['last_updated_at'], 'data' => $results['data']]); 
  2736.        } catch (\Exception $ex) {
  2737.            $this->logger->error($ex->getMessage());
  2738.            return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  2739.        }
  2740.     }
  2741.     /**
  2742.      * @Route("/api/public/locations-by-tags", methods={"POST"})
  2743.      */
  2744.     public function getLocationsByTags(Request $request): JsonResponse
  2745.     {
  2746.        try {
  2747.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  2748.             if ($response['success'] !== true) {
  2749.                 return $this->json($response);
  2750.             }
  2751.             $applicationName $request->headers->get('X-App-Name');
  2752.             $applicationConsumer $request->headers->get('X-App-Consumer-Key');
  2753.             if (!$applicationName || !$applicationConsumer) {
  2754.                 return $this->json(['success' => false,'message' => 'Missing required headers']);
  2755.             }
  2756.             $user DataObject\Customer::getByEmail($applicationNametrue);
  2757.             if (!$user) {
  2758.                 return $this->json([
  2759.                     'success' => false,
  2760.                     'message' => 'Invalid User'
  2761.                 ]);
  2762.             }
  2763.             $application DataObject\WSO2Applications::getByUser($usertrue);
  2764.             if (!$application) {
  2765.                 return $this->json([
  2766.                     'success' => false,
  2767.                     'message' => 'User not found'
  2768.                 ]);
  2769.             }
  2770.             // 5. Consumer key validation
  2771.             if ($application->getConsumerKey() !== $applicationConsumer) {
  2772.                 return $this->json([
  2773.                     'success' => false,
  2774.                     'message' => 'Invalid Consumer Key'
  2775.                 ]);
  2776.             }
  2777.             $params json_decode($request->getContent(), true);
  2778.             $parameter $params['parameter'] ?? null;
  2779.             $duration $params['duration'] ?? null;
  2780.             $dateTime $params['datetime'] ?? null;
  2781.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  2782.             if (!$parameter || !$duration || !$dateTime) {
  2783.                 return $this->json(['success' => false'message' => $this->translator->trans('missing_parameter_or_duration_or_date')], 400);
  2784.             }
  2785.             $tags = [];
  2786.             $tagListing = new WeatherParameterLocationTags\Listing();
  2787.             $tagListing->setCondition("`default` = ?", [true]);
  2788.             foreach ($tagListing as $tag) {
  2789.                 $tags[] = [
  2790.                     'id' => $tag->getId(),
  2791.                     'nameEn' => $tag->getNameEn(),
  2792.                     'nameAr' => $tag->getNameAr(),
  2793.                 ];
  2794.             }
  2795.             $desiredOrder = ['High risk''Medium risk''Low risk'];
  2796.             usort($tags, function ($a$b) use ($desiredOrder) {
  2797.                 $posA array_search($a['nameEn'], $desiredOrder);
  2798.                 $posB array_search($b['nameEn'], $desiredOrder);
  2799.                 return $posA <=> $posB;
  2800.             });
  2801.             $results $this->weatherParameterModel->getLocationsByTags($parameter$duration$dateTime$tags$this->translator);
  2802.            return $this->json(['success' => true'data' => $results]); 
  2803.        } catch (\Exception $ex) {
  2804.            $this->logger->error($ex->getMessage());
  2805.            return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  2806.        }
  2807.     }
  2808.     /**
  2809.      * @Route("/api/public/locations-by-risk", methods={"POST"})
  2810.      */
  2811.     public function getLocationsByRisk(Request $request): JsonResponse
  2812.     {
  2813.        try {
  2814.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  2815.             if ($response['success'] !== true) {
  2816.                 return $this->json($response);
  2817.             }
  2818.             $applicationName $request->headers->get('X-App-Name');
  2819.             $applicationConsumer $request->headers->get('X-App-Consumer-Key');
  2820.             if (!$applicationName || !$applicationConsumer) {
  2821.                 return $this->json(['success' => false,'message' => 'Missing required headers']);
  2822.             }
  2823.             $user DataObject\Customer::getByEmail($applicationNametrue);
  2824.             if (!$user) {
  2825.                 return $this->json([
  2826.                     'success' => false,
  2827.                     'message' => 'Invalid User'
  2828.                 ]);
  2829.             }
  2830.             $application DataObject\WSO2Applications::getByUser($usertrue);
  2831.             if (!$application) {
  2832.                 return $this->json([
  2833.                     'success' => false,
  2834.                     'message' => 'User not found'
  2835.                 ]);
  2836.             }
  2837.             // 5. Consumer key validation
  2838.             if ($application->getConsumerKey() !== $applicationConsumer) {
  2839.                 return $this->json([
  2840.                     'success' => false,
  2841.                     'message' => 'Invalid Consumer Key'
  2842.                 ]);
  2843.             }
  2844.             $params json_decode($request->getContent(), true);
  2845.             $parameter $params['parameter'] ?? null;
  2846.             $duration $params['duration'] ?? null;
  2847.             $dateTime $params['datetime'] ?? null;
  2848.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  2849.             if (!$parameter || !$duration || !$dateTime) {
  2850.                 return $this->json(['success' => false'message' => $this->translator->trans('missing_parameter_or_duration_or_date')], 400);
  2851.             }
  2852.             $results $this->weatherParameterModel->getLocationsByRiskCat($params$parameter$duration$dateTime$user$this->translator);
  2853.            return $this->json(['success' => true'data' => $results]); 
  2854.        } catch (\Exception $ex) {
  2855.            $this->logger->error($ex->getMessage());
  2856.            return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  2857.        }
  2858.     }
  2859.     /**
  2860.      * @Route("/api/public/locations-by-amana", methods={"POST"})
  2861.      */
  2862.     public function getLocationsByAmana(Request $request): JsonResponse
  2863.     {
  2864.        try {
  2865.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  2866.             if ($response['success'] !== true) {
  2867.                 return $this->json($response);
  2868.             }
  2869.             $applicationName $request->headers->get('X-App-Name');
  2870.             $applicationConsumer $request->headers->get('X-App-Consumer-Key');
  2871.             if (!$applicationName || !$applicationConsumer) {
  2872.                 return $this->json(['success' => false,'message' => 'Missing required headers']);
  2873.             }
  2874.             $user DataObject\Customer::getByEmail($applicationNametrue);
  2875.             if (!$user) {
  2876.                 return $this->json([
  2877.                     'success' => false,
  2878.                     'message' => 'Invalid User'
  2879.                 ]);
  2880.             }
  2881.             $application DataObject\WSO2Applications::getByUser($usertrue);
  2882.             if (!$application) {
  2883.                 return $this->json([
  2884.                     'success' => false,
  2885.                     'message' => 'User not found'
  2886.                 ]);
  2887.             }
  2888.             // 5. Consumer key validation
  2889.             if ($application->getConsumerKey() !== $applicationConsumer) {
  2890.                 return $this->json([
  2891.                     'success' => false,
  2892.                     'message' => 'Invalid Consumer Key'
  2893.                 ]);
  2894.             }
  2895.             $params json_decode($request->getContent(), true);
  2896.             $parameter $params['parameter'] ?? null;
  2897.             $duration $params['duration'] ?? null;
  2898.             $dateTime $params['datetime'] ?? null;
  2899.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  2900.             if (!$parameter || !$duration || !$dateTime) {
  2901.                 return new JsonResponse(['success' => false'message' => $this->translator->trans('missing_parameter_or_duration_or_date')], 400);
  2902.             }
  2903.             $results $this->weatherParameterModel->getLocationsByAmanaId($params$parameter$duration$dateTime$this->translator);
  2904.            return $this->json(['success' => true'data' => $results]); 
  2905.        } catch (\Exception $ex) {
  2906.            $this->logger->error($ex->getMessage());
  2907.            return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  2908.        }
  2909.     }
  2910. }