<?php
namespace App\Actions;

use Root\Core\Base as BaseClass;
use Root\Core\Helper\Validator;
use App\Models as Models;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\DB;
use App\Classes\Weather;

class StoreBatch extends BaseClass\Action
{
    public $results = [];
    public $successCount = 0;
    public $failCount = 0;
    
    public $items;
    public $crawledAt;

    public function AttributesLabel()
    {
        return [
            'items' => AL(1),
            'crawledAt' => AL(2),
        ];
    }

    public function Rules()
    {
        return [
            'items' => Validator::ArrayVR(),
            'crawledAt' => Validator::StringVR(),
        ];
    }

    public function Verify(): bool
    {
        if (empty($this->items) || !is_array($this->items)) 
            return $this->AddRuntimeError('items', EL(4));

        foreach ($this->items as $index => $item) {
            
            if (!isset($item['cityId']))
                return $this->AddRuntimeError('items', EL(5), ['index' => $index]);

            if (!is_numeric($item['cityId']))
                return $this->AddRuntimeError('items', EL(6), ['index' => $index]);

            if (!isset($item['weatherData']))
                return $this->AddRuntimeError('items', EL(7), ['index' => $index]);

            $weatherData = $item['weatherData'];
            
            if (!is_array($weatherData))
                return $this->AddRuntimeError('items', EL(8), ['index' => $index]);

            $sections = ['current', 'hourly', 'daily'];
            foreach ($sections as $section) {
                if (!isset($weatherData[$section]) || !is_array($weatherData[$section])) {
                    return $this->AddRuntimeError('items', EL(9), [
                        'index' => $index,
                        'section' => $section
                    ]);
                }
            }

            $requiredCurrentFields = ['time', 'temperature_2m', 'weather_code', 'wind_speed_10m', 'relative_humidity_2m'];
            foreach ($requiredCurrentFields as $field) {
                if (!isset($weatherData['current'][$field])) {
                    return $this->AddRuntimeError('items', EL(10), [
                        'index' => $index,
                        'section' => 'current',
                        'field' => $field
                    ]);
                }
            }

            $requiredHourlyFields = ['time', 'temperature_2m', 'weather_code'];
            foreach ($requiredHourlyFields as $field) {
                if (!isset($weatherData['hourly'][$field]) || !is_array($weatherData['hourly'][$field])) {
                    return $this->AddRuntimeError('items', EL(10), [
                        'index' => $index,
                        'section' => 'hourly',
                        'field' => $field
                    ]);
                }
            }

            $requiredDailyFields = ['time', 'temperature_2m_min', 'temperature_2m_max', 'weather_code'];
            foreach ($requiredDailyFields as $field) {
                if (!isset($weatherData['daily'][$field]) || !is_array($weatherData['daily'][$field])) {
                    return $this->AddRuntimeError('items', EL(10), [
                        'index' => $index,
                        'section' => 'daily',
                        'field' => $field
                    ]);
                }
            }
        }

        return true;
    }

    public function Run(): bool
    {
        try {
            foreach ($this->items as $item) {
                $cityId = $item['cityId'];
                $weatherData = $item['weatherData'];

                $city = Models\City::find($cityId);

                if (!$city) {
                    $this->results[] = [
                        'cityId' => $cityId,
                        'cityName' => 'نامشخص',
                        'success' => false,
                        'error' => str_replace('{{cityId}}', $cityId, EL(11)),
                    ];
                    $this->failCount++;
                    continue;
                }

                try {
                    $processedData = Weather::ProcessWeatherBatchData($weatherData);
                    
                    DB::beginTransaction();
                    
                    $existingRecord = Models\WeatherResult::where('cityId', $cityId)->first();
                    
                    $dataPayload = [
                        'data' => json_encode($processedData, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT),
                        'resultDateTime' => $this->crawledAt,
                        'updated_at' => now(),
                    ];
                    
                    if ($existingRecord) {
                        $existingRecord->update($dataPayload);
                    } else {
                        $dataPayload['id'] = Str::uuid();
                        $dataPayload['cityId'] = $cityId;
                        $dataPayload['created_at'] = now();
                        Models\WeatherResult::create($dataPayload);
                    }

                    DB::commit();

                    $this->results[] = [
                        'cityId' => $cityId,
                        'cityName' => $city->name,
                        'success' => true,
                    ];
                    $this->successCount++;

                } catch (\Exception $e) {
                    DB::rollBack();
                    $this->results[] = [
                        'cityId' => $cityId,
                        'cityName' => $city->name,
                        'success' => false,
                        'error' => str_replace('{{cityId}}', $cityId, EL(13)) . ' - ' . $e->getMessage(),
                    ];
                    $this->failCount++;
                }
            }

            if ($this->successCount === 0 && $this->failCount > 0)
                return $this->AddRuntimeError('items', EL(12));

            return true;

        } catch (\Exception $e) {
            return $this->AddRuntimeError('items', EL(14));
        }
    }
}


