<?php

namespace App\Http\Controllers;

use App\Http\Resources\DistrictResource;
use App\Http\Resources\ManagerResource;
use App\Http\Resources\PointMapResource;
use App\Http\Resources\PointResource;
use App\Models\District;
use App\Models\PointPlan;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Models\Log;
use App\Models\Point;
use App\Models\SchedulePlan;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Crypt; //для ЭЦП
use App\Models\Region;
use Carbon\Carbon;

class AdminController extends Controller

{
    private function convertEPSG3857to4326($x, $y): array
    {
        $originShift = 2 * pi() * 6378137 / 2.0;

        $lon = ($x / $originShift) * 180.0;
        $lat = ($y / $originShift) * 180.0;
        $lat = 180 / pi() * (2 * atan(exp($lat * pi() / 180.0)) - pi() / 2.0);

        return [round($lat, 7), round($lon, 7)];
    }
    //
    public function getUsers(): JsonResponse
    {
        // 1. Берём всех активных пользователей вместе с ролью
        $users = User::with('role:id,name')        // жадная загрузка только нужных полей
        ->where('is_active', true)
            ->get(['id','first_name','middle_name','last_name',
                'position','role_id','birthday','is_active']);

        // 2. Группируем по названию роли
        $grouped = $users->groupBy(fn ($u) => $u->role->name ?? 'Без роли')
            ->map(function ($collection) {
                // 3. Оставляем в ответе только то, что реально нужно фронту
                return $collection->map(fn ($u) => [
                    'id'          => $u->id,
                    'first_name'  => $u->first_name,
                    'middle_name' => $u->middle_name,
                    'last_name'   => $u->last_name,
                    'position'    => $u->position,
                    'role'        => $u->role,          // id + name
                    'birthday'    => $u->birthday,
                    'is_active'   => $u->is_active,
                ])->values();                            // убираем ключи коллекции
            });

        return response()->json($grouped, 200);
    }

    public function getUserInfo($id): JsonResponse
    {
        $user = User::find($id);
        $role = $user->role;
        return response()->json(['user' => [
            'id' => $user->id,
            'first_name' => $user->first_name,
            'middle_name' => $user->middle_name,
            'last_name' => $user->last_name,
            'position' => $user->position,
            'role' => $role,
            'birthday' => $user->birthday,
        ]]);
    }
    public function editUser(Request $request, $id): JsonResponse
    {
        $actionUser = Auth::user();
        $user = User::findOrFail($id);
        $data = $request->validate([
            'last_name'              => 'sometimes|string|max:255',
            'first_name'             => 'sometimes|string|max:255',
            'middle_name'            => 'sometimes|string|max:255',
            'position'               => 'sometimes|string|max:255',
            'birthday'               => 'sometimes|date',
            'role_id'                => 'sometimes|integer|exists:roles,id',
            'password'               => 'nullable|string|min:8|confirmed',
        ]);
        $original = $user->only(array_keys($data));
        $user->fill($data);
        if ($user->isDirty()) {
            $user->save();
            // 4) логгируем только реально изменённые
            foreach ($user->getDirty() as $field => $new) {
                Log::create([
                    'model_id'   => $user->id,
                    'model_type' => User::class,
                    'change'     => 'Изменено поле ' . $field,
                    'action'     => 'Обновление данных',
                    'old_value'  => $original[$field] ?? null,
                    'new_value'  => $new,
                    'created_by' => $actionUser->id,
                ]);
            }
            return response()->json(['success' => 'Данные пользователя обновлены']);
        }

        return response()->json(['info' => 'Нечего обновлять']);
    }
    public function delUser($id): JsonResponse
    {
        $user = User::find($id);
        $user->update(['is_active' => false]);
        return response()->json(['success' => 'Пользователь успешно удалён']);
    }
    public function getLogs(): JsonResponse
    {
        $users = User::all();
        $logs = Log::all();
        return response()->json(['logs' => $logs, 'users' => $users]);
    }



    public function getRegionsAndSenManagers(): JsonResponse
    {
        $regions    = Region::all();
        // Все пользователи с ролью регионального менеджера
        $stManagers = User::with('role')
            ->where('role_id', 3)
            ->active()
            ->get();

        return response()->json(compact('regions','stManagers'));
    }


    public function proposeSenManagerToRegion(Request $request): JsonResponse
    {
        $authUser  = Auth::user();

        $validated = $request->validate([
            'region_id'      => ['required', 'exists:regions,id'],
            'sen_manager_id' => ['nullable', 'exists:users,id'],
        ]);

        $region = Region::findOrFail($validated['region_id']);

        //‑‑‑ Перезаписываем менеджера (может быть null) ‑‑‑
        $region->sen_manager_id = $validated['sen_manager_id'];
        $region->save();

        /* ------ если менеджера назначили ------ */
        if ($validated['sen_manager_id']) {

            $user = User::findOrFail($validated['sen_manager_id']);

            // уведомляем
            $user->userNotifications()->create([
                'title'   => 'Назначение Регионального менеджера',
                'content' => 'Вы назначены Региональным менеджером региона «' . $region->name . '».',
            ]);

            // лог
            Log::create([
                'model_id'   => $region->id,
                'model_type' => Region::class,
                'change'     => 'Региональный менеджер',
                'action'     => 'На регион «' . $region->name . '» назначен региональный менеджер',
                'old_value'  => '',
                'new_value'  => $user->fullName(),
                'created_by' => $authUser->id,
            ]);

            return response()->json(['success' => 'Региональный менеджер назначен.']);

            /* ------ если менеджера сняли ------ */
        } else {

            Log::create([
                'model_id'   => $region->id,
                'model_type' => Region::class,
                'change'     => 'Региональный менеджер',
                'action'     => 'С региона «' . $region->name . '» снят региональный менеджер',
                'old_value'  => '',
                'new_value'  => '',
                'created_by' => $authUser->id,
            ]);

            return response()->json(['success' => 'Региональный менеджер снят.']);
        }
    }


    public function getRegionswithDistrics(): JsonResponse
    {
        $regions = Region::with('districts')->get();
        return response()->json([
            'regions' => $regions,
        ]);
    }
    public function getPointList()
    {
        $allowed = $this->getAllowedDistrictIdsForCurrentUser();

        $points = Point::with(['district.region', 'requests'])
            ->whereIn('district_id', $allowed)
            ->where('is_active', true)
            ->get();

        return response()->json(['points' => $points]);
    }

    public function getPointsForMap(Request $r): JsonResponse
    {
        // 0. входные данные
        $allowed  = $this->getAllowedDistrictIdsForCurrentUser();
        $district = $r->integer('district_id'); // null → все районы

        // 1. колонки
        $cols = [
            'id','latitude','longitude','name','district_id',
            'length','road_category','accounting_point','record_number',
            'monitoring_freq','accounting_flag','is_active',
        ];
        if ($district) {
            $cols[] = 'geojson';
        }

        // 2. eager-load
        $with = [
            'district:id,name,region_id',
            'district.region:id,name',
            'plans' => function ($q) {
                $q->select([
                    'id','point_id','request_id',
                    'day','timeStart','timeEnd',
                    'subgroup_manager_id','counter_id',
                    'comment','isWorkedOut',
                ])
                    ->where('is_active', true);
            },
            'requests' => function ($q) {
                $q->select(['requests.id', 'requests.name']);
            },
        ];


        // 3. строим основной запрос
        $query = Point::query()
            ->where('is_active', true)
            ->whereIn('district_id', $allowed)
            ->select($cols);

        // фильтр по району, если задан
        if ($district) {
            $query->where('district_id', $district);
        }

        // 4. применяем eager-load и забираем результаты
        $points = $query
            ->with($with)
            ->get();

        // 5. отдаём через Resource
        return response()->json([
            'points' => PointMapResource::collection($points),
        ]);
    }


    public function infoForCreatePoint(): JsonResponse
    {
        $regions = Region::with('districts')->get();
        return response()->json(['regions' => $regions]);
    }

    public function createPoint(Request $request): JsonResponse
    {
        $authUser = Auth::user();

        $request->validate([
            'id' => ['nullable', 'exists:points,id'],
            'name' => ['required', 'string'],
            'latitude' => ['required', 'numeric'],
            'longitude' => ['required', 'numeric'],
            'file' => ['nullable', 'file', 'mimetypes:application/json,text/plain'],
            'district_id' => ['required_without:id', 'exists:districts,id'],
            'length' => ['nullable', 'numeric'],
            'accounting_point' => ['nullable', 'string'],
            'road_category' => ['nullable', 'string'],
            'road_subcategory' => ['nullable', 'string'],
            'record_number' => ['nullable', 'integer'],
            'accounting_type' => ['nullable', 'string'],
            'monitoring_freq' => ['nullable', 'integer'], // 1 или 2
            'accounting_flag' => ['nullable', 'integer'], // 1 или 2
        ]);

        $featureCollection = null;

        if ($request->hasFile('file')) {
            $file = $request->file('file');
            $json = json_decode(file_get_contents($file->getRealPath()), true);

            if (!isset($json['features']) || !is_array($json['features'])) {
                return response()->json(['error' => 'Некорректный GeoJSON'], 400);
            }

            $features = [];

            foreach ($json['features'] as $feature) {
                if (
                    isset($feature['geometry']['type']) &&
                    $feature['geometry']['type'] === 'MultiLineString' &&
                    isset($feature['geometry']['coordinates'])
                ) {
                    foreach ($feature['geometry']['coordinates'] as $line) {
                        $convertedLine = array_map(function ($coord) {
                            return $this->convertEPSG3857to4326($coord[0], $coord[1]);
                        }, $line);

                        $features[] = [
                            'type' => 'Feature',
                            'geometry' => [
                                'type' => 'LineString',
                                'coordinates' => $convertedLine,
                            ],
                        ];
                    }
                }
            }

            $featureCollection = [
                'type' => 'FeatureCollection',
                'features' => $features,
            ];
        }

        if ($request->id) {
            $point = Point::findOrFail($request->id);
            $originalData = $point->only([
                'name',
                'latitude',
                'longitude',
                'geojson',
                'length',
                'accounting_point',
                'road_category',
                'road_subcategory',
                'record_number',
                'accounting_type',
                'monitoring_freq',
                'accounting_flag',
            ]);

            $point->fill($request->only([
                'name',
                'latitude',
                'longitude',
                'length',
                'accounting_point',
                'road_category',
                'road_subcategory',
                'record_number',
                'accounting_type',
                'monitoring_freq',
                'accounting_flag',
            ]));

            if ($featureCollection) {
                $point->geojson = json_encode($featureCollection, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
            }

            if ($point->isDirty()) {
                $dirtyFields = $point->getDirty();
                $point->save();

                foreach ($dirtyFields as $field => $newValue) {
                    $oldValue = $originalData[$field] ?? null;

                    Log::create([
                        'model_id' => $point->id,
                        'model_type' => Point::class,
                        'change' => 'Изменено поле ' . $field,
                        'action' => 'Обновление точки',
                        'old_value' => is_array($oldValue) ? json_encode($oldValue) : $oldValue,
                        'new_value' => is_array($newValue) ? json_encode($newValue) : $newValue,
                        'created_by' => $authUser->id,
                    ]);
                }
            }
        } else {
            $point = Point::create([
                'district_id' => $request->district_id,
                'name' => $request->name,
                'latitude' => $request->latitude,
                'longitude' => $request->longitude,
                'length' => $request->length,
                'accounting_point' => $request->accounting_point,
                'road_category' => $request->road_category,
                'road_subcategory' => $request->road_subcategory,
                'record_number' => $request->record_number,
                'accounting_type' => $request->accounting_type,
                'monitoring_freq' => $request->monitoring_freq,
                'accounting_flag' => $request->accounting_flag,
                'geojson' => $featureCollection ? json_encode($featureCollection, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) : null,
            ]);

            Log::create([
                'model_id' => $point->id,
                'model_type' => Point::class,
                'change' => 'Создание точки',
                'action' => 'Создана точка ' . $point->name . ' в регионе ' . $point->district->region->name,
                'old_value' => '',
                'new_value' => $point->name,
                'created_by' => $authUser->id,
            ]);
        }

        return response()->json([
            'id' => $point->id,
            'name' => $point->name,
            'latitude' => $point->latitude,
            'longitude' => $point->longitude,
            'length' => $point->length,
            'accounting_point' => $point->accounting_point,
            'road_category' => $point->road_category,
            'road_subcategory' => $point->road_subcategory,
            'record_number' => $point->record_number,
            'accounting_type' => $point->accounting_type,
            'monitoring_freq' => $point->monitoring_freq,
            'accounting_flag' => $point->accounting_flag,
        ]);
    }

    public function getInfoPointForEdit($id): JsonResponse
    {
        $point = Point::with('district.region')->find($id);
        return response()->json([
            'point' => $point,
        ]);
    }


    public function editPoint(Request $request): JsonResponse
    {
        $actionUser = Auth::user();

        $point = Point::find($request->id);
        if (!$point) {
            return response()->json(['error' => 'Точка не найдена'], 404);
        }

        $hasGeoUpdated = false;

        // Обработка GeoJSON файла, если он есть
        if ($request->hasFile('file')) {
            $file = $request->file('file');
            $json = json_decode(file_get_contents($file->getRealPath()), true);

            if (!isset($json['features']) || !is_array($json['features'])) {
                return response()->json(['error' => 'Неверный формат GeoJSON'], 400);
            }

            $features = [];

            foreach ($json['features'] as $feature) {
                if (
                    isset($feature['geometry']['type']) &&
                    $feature['geometry']['type'] === 'MultiLineString' &&
                    isset($feature['geometry']['coordinates'])
                ) {
                    foreach ($feature['geometry']['coordinates'] as $line) {
                        $convertedLine = array_map(function ($coord) {
                            return $this->convertEPSG3857to4326($coord[0], $coord[1]);
                        }, $line);

                        $features[] = [
                            'type' => 'Feature',
                            'geometry' => [
                                'type' => 'LineString',
                                'coordinates' => $convertedLine,
                            ],
                        ];
                    }
                }
            }

            $newGeojson = json_encode([
                'type' => 'FeatureCollection',
                'features' => $features,
            ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

            // Логируем и сохраняем geojson
            Log::create([
                'model_id' => $point->id,
                'model_type' => Point::class,
                'change' => 'GeoJSON',
                'action' => 'Обновление геоданных',
                'old_value' => 'Предыдущий файл',
                'new_value' => 'Загружен новый файл',
                'created_by' => $actionUser->id,
            ]);

            $point->geojson = $newGeojson;
            $hasGeoUpdated = true;
        }

        // Обработка обычных полей
        $originalData = $point->only(['latitude', 'longitude', 'name', 'district_id']);
        $point->fill($request->only(['latitude', 'longitude', 'name', 'district_id']));

        if ($point->isDirty() || $hasGeoUpdated) {
            try {
                $dirtyFields = $point->getDirty();
                unset($dirtyFields['geojson']);
                $point->save();
                foreach ($dirtyFields as $field => $newValue) {
                    $oldValue = isset($originalData[$field]) ? $this->normalizeValue($originalData[$field]) : null;
                    $newValue = $this->normalizeValue($newValue);

                    if ($oldValue !== $newValue) {
                        Log::create([
                            'model_id' => $point->id,
                            'model_type' => Point::class,
                            'change' => 'Изменено поле ' . $field,
                            'action' => 'Обновление данных',
                            'old_value' =>  $originalData[$field]  ?? 'null',
                            'new_value' => $newValue,
                            'created_by' => $actionUser->id,
                        ]);
                    }
                }

                return response()->json(['success' => 'Информация по точке успешно обновлена']);
            } catch (\Exception $e) {
                return response()->json(['error' => 'Произошла ошибка при сохранении: ' . $e->getMessage()], 500);
            }
        }

        return response()->json(['info' => 'Изменений не было']);
    }


    public function getSenManagerPoints($id): JsonResponse
    {
        $user = User::find($id);
        $points = Point::where('senManager_id', $user->id)->get();

        $monthNames = [
            1 => 'Январь',
            2 => 'Февраль',
            3 => 'Март',
            4 => 'Апрель',
            5 => 'Май',
            6 => 'Июнь',
            7 => 'Июль',
            8 => 'Август',
            9 => 'Сентябрь',
            10 => 'Октябрь',
            11 => 'Ноябрь',
            12 => 'Декабрь'
        ];

        $year = now()->year; // текущий год

        for ($month = 1; $month <= 12; $month++) {
            $daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year);

            $calendar[] = [
                'year' => $year,
                'month' => $monthNames[$month],
                'days' => range(1, $daysInMonth),
            ];
        }

        return response()->json(['points' => $points, 'calendar' => $calendar]);
    }

    public function getPointInfo($id): JsonResponse
    {
        $point = Point::find($id);
        $users = User::whereHas('role', function ($query) {
            $query->where('name', 'Менеджер');
        })->where('is_active', true)->get()->map(function ($user) {
            $role = $user->role;
            return [
                'id' => $user->id,
                'first_name' => $user->first_name,
                'middle_name' => $user->middle_name,
                'last_name' => $user->last_name,
                'position' => $user->position,
                'role' => $role,
                'birthday' => $user->birthday,
                'is_active' => $user->is_active
            ];
        });
        return response()->json(['point' => $point, 'users' => $users]);
    }

    public function createSignatureSchedule($id)
    {
        $plan = SchedulePlan::find($id);
        if (!$plan) {
            return response()->json(['error' => 'Schedule plan not found'], 404);
        }

        $user = Auth::user();
        if (empty($user->private_key)) {
            return response()->json(['error' => 'У пользователя нет приватного ключа'], 400);
        }

        // Строим строку для хеширования
        $hashString = implode('|', [
            $plan->manager_id,
            $plan->point_id,
            $plan->day,
            $plan->start_time,
            $plan->end_time,
        ]);
        $hash = hash('sha256', $hashString);

        // Расшифровываем приватный ключ из БД
        $privateKey = Crypt::decryptString($user->private_key);

        // Подписываем хеш
        $signature = '';
        openssl_sign($hash, $signature, $privateKey, OPENSSL_ALGO_SHA256);

        $plan->update([
            'hash'                => $hash,
            'signature'           => base64_encode($signature),
            'signature_public_key' => $user->public_key,
            'is_active'           => true,
        ]);

        return response()->json([
            'message' => 'График подписан успешно',
            'data'    => $plan,
        ]);
    }

    public function getDraftScheduleInfo($id): JsonResponse
    {
        $schedule_plan = SchedulePlan::find($id);
        return response()->json(['schedule_plan' => $schedule_plan]);
    }

    public function getSchedulesInfo($id): JsonResponse
    {
        $schedules = SchedulePlan::where('manager_id', $id)->get()->map(function ($schedule) {
            return [
                'id' => $schedule->id,
                'manager_id' => $schedule->manager_id,
                'point' => [
                    'id' => $schedule->point_id,
                    'name' => optional($schedule->point)->name,
                ],
                'day' => $schedule->day,
                'start_time' => $schedule->start_time,
                'end_time' => $schedule->end_time,
                'is_active' => $schedule->is_active,
            ];
        });
        $operators = User::whereHas('role', function ($query) {
            $query->where('name', 'Оператор');
        })->get()->map(function ($user) {
            return [
                'id' => $user->id,
                'first_name' => $user->first_name,
                'middle_name' => $user->middle_name,
                'last_name' => $user->last_name,
            ];
        });

        if (!$schedules) {
            return response()->json(['message' => 'График не найден'], 404);
        }

        return response()->json(['schedule' => $schedules, 'operators' => $operators]);
    }
    public function generatePointPlans(Request $request)
    {
        $validated = $request->validate([
            'date_start'   => 'required|date',
            'date_end'     => 'required|date|after_or_equal:date_start',
            'point_ids'    => 'required|array|min:1',
            'point_ids.*'  => 'integer|exists:points,id',
            'shifts'       => 'required|array|min:1',
            'shifts.*.start' => 'required|date_format:H:i',
            'shifts.*.end'   => 'required|date_format:H:i',
            'request_id'     => 'required|integer|exists:requests,id',
            'district_id'         => 'nullable|integer|exists:districts,id',
            'subgroup_manager_id' => 'nullable|integer|exists:users,id',
        ]);

        $start    = Carbon::parse($validated['date_start']);
        $year     = $start->year;
        $schedule = SchedulePlan::where('year', $year)->firstOrFail();
        $scheduleId = $schedule->id;

        $end   = Carbon::parse($validated['date_end']);
        $holidays = [
            '2025-01-01','2025-01-07','2025-03-08','2025-05-01','2025-05-02',
            '2025-05-08','2025-05-09','2025-06-12','2025-06-13','2025-11-03',
            '2025-11-04','2025-12-31',
        ];

        // собираем рабочие даты
        $dates = [];
        for ($d = $start->copy(); $d->lte($end); $d->addDay()) {
            if ($d->isWeekend() || in_array($d->toDateString(), $holidays)) {
                continue;
            }
            $dates[] = $d->toDateString();
        }

        $shifts   = $validated['shifts'];
        $pointIds = $validated['point_ids'];
        $total    = count($pointIds);
        $slotsPerOp = count($dates) * count($shifts);

        if ($slotsPerOp === 0) {
            return response()->json(['message' => 'Нет доступных рабочих слотов за период'], 422);
        }

        // подгружаем точки с районами
        $query = Point::with('district')->whereIn('id', $pointIds);

        if ($request->filled('district_id')) {
            $query->where('district_id', $request->district_id);
        }

        if ($request->filled('subgroup_manager_id')) {
            $query->whereHas('district', function($q) use ($request) {
                $q->where('subgroup_manager_id', $request->subgroup_manager_id);
            });
        }

        $points = $query->get()->keyBy('id');
        if ($points->isEmpty()) {
            return response()->json(['message' => 'Не найдено ни одной точки для выбранных фильтров'], 422);
        }

        // --- Проверка на дубли по заявке и точкам
        $existing = PointPlan::whereIn('point_id', $pointIds)
            ->where('request_id', $validated['request_id'])
            ->where('is_active', true) // если нужно учитывать только активные
            ->get()
            ->groupBy('point_id');

        $duplicatedPoints = [];
        foreach ($pointIds as $pid) {
            if (!empty($existing[$pid])) {
                $pt = $points[$pid] ?? null;
                if ($pt) {
                    $duplicatedPoints[] = $pt->name;
                }
            }
        }

        if (!empty($duplicatedPoints)) {
            return response()->json([
                'message' => 'В выбранной заявке по следующим точкам уже запланированы работы:',
                'duplicated_points' => $duplicatedPoints,
            ], 422);
        }

        // готовим список слотов
        $slots = [];
        foreach ($dates as $day) {
            foreach ($shifts as $sh) {
                $slots[] = ['day' => $day, 'start' => $sh['start'], 'end' => $sh['end']];
            }
        }

        $batch = [];
        $now = now();
        foreach ($pointIds as $i => $pid) {
            $slotIndex    = $i % $slotsPerOp;
            $slot         = $slots[$slotIndex];
            $pt           = $points[$pid];
            $subMgr       = $validated['subgroup_manager_id'] ?? optional($pt->district)->subgroup_manager_id;

            $batch[] = [
                'day'                 => $slot['day'],
                'timeStart'           => $slot['start'],
                'timeEnd'             => $slot['end'],
                'point_id'            => $pid,
                'schedule_id'         => $scheduleId,
                'request_id'          => $validated['request_id'], // вот оно!
                'subgroup_manager_id' => $subMgr,
                'isWorkedOut'         => false,
                'is_active'           => true,
                'created_at'          => $now,
                'updated_at'          => $now,
            ];
        }

        // сохраняем пачками
        collect($batch)
            ->chunk(100)
            ->each(fn($chunk) => PointPlan::insert($chunk->toArray()));

        return response()->json([
            'rows_created' => count($batch),
        ]);
    }


    public function getRegionsAndGroupManagers(): JsonResponse
    {
        $regions        = Region::all();
        // Все пользователи с ролью менеджера группы
        $groupManagers  = User::with('role')
            ->where('role_id', 4)
            ->get();

        return response()->json(compact('regions','groupManagers'));
    }

    /**
     * @param Request $r
     * @return JsonResponse
     */
    public function assignGroupManager(Request $r): JsonResponse
    {
        $r->validate([
            'region_id'        => 'required|exists:regions,id',
            'group_manager_id' => 'required|exists:users,id',
        ]);
        $region = Region::findOrFail($r->region_id);
        $region->update(['group_manager_id' => $r->group_manager_id]);
        return response()->json(['success' => true]);
    }

    /**
     * @return JsonResponse
     */
    public function getDistrictsAndSubgroupManagers(): JsonResponse
    {
        $districts = District::with(['region', 'subgroupManager'])->get();

        $subManagers = User::query()
            ->whereHas('role', fn ($q) => $q->where('name', 'Менеджер подгруппы'))
            ->where('is_active', true)
            ->get();

        return response()->json([
            'districts'    => DistrictResource::collection($districts),
            'subManagers'  => ManagerResource::collection($subManagers),
        ]);
    }


    /**
     * @param Request $r
     * @return JsonResponse
     */
    public function assignSubgroupManager(Request $r): JsonResponse
    {
        $r->validate([
            'district_id'         => 'required|exists:districts,id',
            'subgroup_manager_id' => 'required|exists:users,id',
        ]);
        $district = District::findOrFail($r->district_id);
        $district->update(['subgroup_manager_id' => $r->subgroup_manager_id]);
        return response()->json(['success' => true]);
    }

    /**
     * @param $requestId
     * @return JsonResponse
     */
    public function getRequestPlansDateRange($requestId): JsonResponse
    {
        $dates = PointPlan::where('request_id', $requestId)
            ->where('is_active', true)
            ->selectRaw('MIN(day) as date_start, MAX(day) as date_end')
            ->first();

        // Всегда возвращаем строки ISO, даже если null
        return response()->json([
            'date_start' => $dates->date_start ? Carbon::parse($dates->date_start)->toDateString() : null,
            'date_end'   => $dates->date_end ? Carbon::parse($dates->date_end)->toDateString() : null,
        ]);
    }

    /*
        Метод, который вернет массив с диапазонами по каждому району
    */
    /**
     * @param $id
     * @return JsonResponse
     */
    public function getRequestDistrictRanges($id)
    {
        $plans = PointPlan::where('request_id', $id)
            ->where('is_active', true)
            ->with(['point.district'])
            ->get();

        $grouped = $plans->groupBy(function($plan) {
            return optional($plan->point->district)->id;
        });

        $result = [];
        foreach ($grouped as $districtId => $plansGroup) {
            $district = optional($plansGroup->first()->point->district);
            $dates = $plansGroup->pluck('day')->sort();
            $result[] = [
                'district_id'   => $districtId,
                'district_name' => $district->name ?? '—',
                'date_start'    => $dates->first(),
                'date_end'      => $dates->last(),
            ];
        }
        return response()->json($result);
    }
}
