<?php

namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use App\Models\PointPlan;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Crypt; //для ЭЦП
use App\Models\PointPlanPhoto;

class OperatorController extends Controller
{
    // app/Http/Controllers/OperatorController.php
    public function getPoints(Request $request): JsonResponse
    {
        $allowed = $this->getAllowedDistrictIdsForCurrentUser();
        $perPage = (int) $request->query('per_page', 50);
        $page    = (int) $request->query('page', 1);

        // 1) Строим базовый запрос со всеми фильтрами, но без paginate()
        $base = PointPlan::where('is_active', true)
            ->whereHas('point', fn($q) => $q->whereIn('district_id', $allowed));

        if ($request->filled('request_id')) {
            $base->where('request_id', $request->query('request_id'));
        }
        if ($request->filled('district_id')) {
            $base->whereHas('point', fn($q) => $q->where('district_id', $request->query('district_id')));
        }
        if ($request->filled('subgroup_manager_id')) {
            $base->where('subgroup_manager_id', $request->query('subgroup_manager_id'));
        }
        if ($request->filled('month')) {
            $base->whereMonth('day', (int)$request->query('month'));
        }

        // 2) Считаем сводку по ВСЕМ записям (до пагинации)
        $all = (clone $base)
            ->withCount([
                'measurements',
                'files as before_count' => fn($q)=> $q->where('type','before'),
                'files as after_count'  => fn($q)=> $q->where('type','after'),
            ])
            ->get();

        $planned   = $all->count();
        $completed = $all->filter(fn($p)=>
            $p->measurements_count > 0 &&
            $p->before_count      > 0 &&
            $p->after_count       > 0
        )->count();
        $remarks   = $all->filter(fn($p)=> trim((string)$p->comment) !== '')->count();
        $overdue   = $all->filter(fn($p)=>
            $p->day < now() &&
            ! (
                $p->measurements_count > 0 &&
                $p->before_count      > 0 &&
                $p->after_count       > 0
            )
        )->count();
        $remaining = $planned - $completed;

        $maxDay    = $all->max('day');
        $deadline  = $maxDay
            ? Carbon::parse($maxDay)->toDateString()
            : null;


        // 3) К paginated-запросу добавляем eager-loading, counts и paginate()
        $paginated = $base
            ->with([
                'point:id,name,district_id,record_number,accounting_flag,monitoring_freq,length,accounting_point,segment_from,segment_to',
                'point.district:id,name,region_id,group_manager_id',
                'point.district.region:id,name',
                'point.district.groupManager:id,first_name,last_name,middle_name',
                'subgroupManager:id,first_name,last_name,middle_name',
                'counter:id,first_name,last_name',
            ])
            ->withCount([
                'measurements',
                'files as before_count' => fn($q) => $q->where('type','before'),
                'files as after_count'  => fn($q) => $q->where('type','after'),
                'files as doc_count'    => fn($q) => $q->where('type','doc'),
            ])
            ->orderBy('day')
            ->paginate($perPage, ['*'], 'page', $page);

        // 4) Возвращаем и страницы, и summary
        return response()->json([
            'point_plans' => $paginated->items(),
            'meta'        => [
                'current_page' => $paginated->currentPage(),
                'last_page'    => $paginated->lastPage(),
                'per_page'     => $paginated->perPage(),
                'total'        => $paginated->total(),
            ],
            'summary'     => [
                'planned'   => $planned,
                'completed' => $completed,
                'remarks'   => $remarks,
                'overdue'   => $overdue,
                'remaining' => $remaining,
                'deadline'  => $deadline,
            ],
        ]);
    }


    public function uploadFile(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'point_plan_id' => 'required|exists:point_plans,id',
            'file' => 'required|file|mimes:jpeg,jpg,png,mp4,mov|max:10240', // Любой файл до 10MB
            'type' => 'required|in:before,after',
            'comment' => 'nullable|string|max:255',
        ]);

        $file = $request->file('file');
        $originalName = $file->getClientOriginalName(); // Сохраняем оригинальное имя
        $extension = $file->getClientOriginalExtension(); // Расширение файла
        $path = $file->store('point_files', 'public'); // Папка для хранения

        $uploadedFile = PointPlanPhoto::create([
            'point_plan_id' => $validated['point_plan_id'],
            'file_path' => $path,
            'file_name' => $originalName, // Сохраняем имя файла
            'file_type' => $extension, // Сохраняем тип файла (jpg, mp4, pdf и т.д.)
            'type' => $validated['type'],
            'comment' => $validated['comment'] ?? null,
        ]);

        return response()->json([
            'message' => 'Файл успешно загружен',
            'file' => $uploadedFile
        ]);
    }


    public function createSignaturePointPlan($id)
    {
        $plan = PointPlan::find($id);

        $user = $plan->operator;

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

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

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

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

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

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

    public function getPointPlanInfo(int $id): JsonResponse
    {
        // 1) получаем список разрешённых для пользователя district_id
        $allowedDistricts = $this->getAllowedDistrictIdsForCurrentUser();

        // 2) ищем сам PointPlan только если его точка в разрешённых районах
        $plan = PointPlan::where('id', $id)
            ->whereHas('point', fn($q) => $q->whereIn('district_id', $allowedDistricts))
            ->with([
                // саму точку с нужными полями
                'point' => fn($q) => $q->select([
                    'id',
                    'name',
                    'district_id',
                    'latitude',
                    'longitude',
                    'record_number',
                    'monitoring_freq',
                    'accounting_flag',
                ]),
                // район + область
                'point.district:id,name,region_id',
                'point.district.region:id,name',
                // год и отвечающий за расписание
                'schedule:id,year,sen_manager_id',
                // оператор
                'subgroupManager:id,first_name,middle_name,last_name',
                // счётчик
                'counter:id,first_name,last_name',
            ])
            ->first();

        if (! $plan) {
            return response()->json(['error' => 'План не найден или доступ к нему запрещён'], 404);
        }

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

}
