<?php

namespace App\Http\Controllers;

use A7kz\Platform\Models\UniModel;
use A7kz\Platform\Modules\Platform\Acl\Facades\Acl;
use A7kz\Platform\Modules\Platform\Segment\Facades\Segment;
use App\Http\Notifications\TelegramNotification;
use App\Models\User;
use App\Modules\applications\Enum\ApplicationStatus;
use App\Modules\auto\Enums\AutoStatusEnums;
use App\Service\DepositService;
use Carbon\CarbonPeriod;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Facades\Storage;
use Mpdf\Tag\Mark;
use function PHPUnit\Framework\isEmpty;

class MobileApiController extends Controller
{
    public function getMarks(): JsonResponse {
        $data = [];
        $marks = UniModel::model('pipi_brand_models')->get();
        if (!isset($marks)) {
            return response()->json();
        }
        foreach ($marks as $mark) {
            $brand = UniModel::model('pipi_auto_brands')->find($mark->brand_id);
            $tariffs = UniModel::model('pipi_auto_tariffs')->where('model_id', $mark->id)->get();
            $equipment = UniModel::model('pipi_auto_equipment')->where('id', $mark->equipment_id)->first();
            if ($mark->name != 'Ввод остатков') {
                foreach ($tariffs as $tariff) {
                    $tariffs_new[] = [
                        'name' => $tariff?->name,
                        'price' => $tariff?->base_rate,
                        'min' => $tariff?->day_range_start,
                        'max' => $tariff?->day_range_end,
                    ];
                }
                $data[$mark->name . '-' . $mark->year] = [
                    'id'            => $mark->id,
                    'brand'         => $brand->name,
                    'mark'          => $mark->name,
                    'year'          => $mark->year,
                    'configuration' => $equipment?->name,
                    'tariffs'       => $tariffs_new
                ];
            }
        }

        if (empty($data)) {
            $data = (object) [];
        }
        return response()->json($data);
    }

    /**
     * @throws Exception
     */
    public function sendApplication(Request $request): JsonResponse {
        try {
            $data = $request->all();
            $data['started_at'] = Carbon::createFromFormat('d-m-Y H:i', $data['started_at']);
            $data['ended_at'] = Carbon::createFromFormat('d-m-Y H:i', $data['ended_at']);
            $authToken = null;
            $data['car_id'] = null;
            if ($request->header('Authorization')) {
                $user = auth()->guard('api')->user();
                $data['user_id'] = $user?->id;
                $authToken = $request->header('Authorization');
            } else {
                $user = User::where('email', $data['email'])->first();

                if ($user) {
                    $data['user_id'] = $user->id;
                    $tokenResult = $user->createToken('auth_token');
                    $authToken = $tokenResult->plainTextToken;
                } else {
                    $data['user_id'] = null;
                }
            }

            $response = [
                'status' => 'OK',
                'message' => 'Заявка создана',
            ];

            $car = $this->getAvailableCar($data['started_at'], $data['ended_at'], $data['mark_id'], $data['color_code']);
            $status = ApplicationStatus::pending->value;
            if (!isset($car)) {
                return response()->json('Нет свободных машин');
            }
            $data['car_id'] = $car->id;
            if ($data['user_id']) {
                $period = CarbonPeriod::create($data['started_at'], $data['ended_at']);

                $dates = array_map(fn($date) => $date->toDateString(), iterator_to_array($period));

                foreach ($dates as $date) {
                    UniModel::model('pipi_auto_calendar')->create([
                        'auto_id' => $data['car_id'],
                        'date' => $date,
                        'status' => AutoStatusEnums::Rent->name
                    ]);
                }
                $status = ApplicationStatus::approved->value;
                $response['auth_token'] = $authToken;
                $response['message'] = 'Заявка создана, и вы были автоматически авторизованы';
            } elseif (!isset($data['user_id'])) {
                $response['message'] = 'Заявка создана, с вами свяжется наш оператор';
            }
            $address_end = UniModel::model('pipi_address')->where('name', $data['address_end'])->first();
            $address_start = UniModel::model('pipi_address')->where('name', $data['address_start'])->first();
            $service = new DepositService;
            $sums = $service->calculateSummary($data['mark_id'], $data['started_at'], $data['ended_at']);
            $sum = $sums['discounted_sum'];
            if ($data['deposit'] != $sums['deposit_base']) {
                $sum += $data['deposit'];
            }
            UniModel::model('pipi_applications')->create([
                'rent_day'      => $data['rent_day'],
                'started_at'    => $data['started_at'],
                'ended_at'      => $data['ended_at'],
                'user_id'       => $data['user_id'],
                'phone'         => $user?->phone ?? $data['phone'] ?? ''                                                                                                                                                                                                                 ,
                'car_id'        => $data['car_id'],
                'user_name'     => $user?->name ?? $data['name'] ?? null,
                'user_surname'  => $user?->name ?? $data['surname'] ?? null,
                'user_email'    => $user?->email ?? $data['email'] ?? null,
                'address_end'   => $address_end?->id,
                'address_start' => $address_start?->id,
                'deposit'       => $data['deposit'] ?? null,
                'status'        => $status,
                'sum'           => $sum
            ]);

            $notification = [];
            $notification['Адрес получения'] = $data['address_start'];
            $notification['Адрес возврата'] = $data['address_end'];
            $notification['Дата и время начала'] = $data['started_at'];
            $notification['Дата и время возврата'] = $data['ended_at'];
            $notification['Телефон'] = $data['phone'] ?? $user?->phone ?? null;
            $notification['Имя'] = $data['name'] ?? $user?->name ?? null;
            $notification['Почта'] = $data['email'] ?? $user?->email ?? null;
            $notification['Сообщение'] = __('Новая заявка');
            $this->sendNotification($notification);

            return response()->json($response);
        } catch (Exception $e) {
            return response()->json($e->getMessage());
        }
    }

    public function getApplications(): JsonResponse
    {
        $request = request();
        if ($request->header('Authorization')) {
            $user = auth()->guard('api')->user();
        } else {
            return response()->json([
                'status' => false,
                'message' => __('Вы не авторизованы')
            ]);
        }

        $status = $request->query('status');

        $data = [];
        $query = UniModel::model('pipi_applications')->where('user_id', $user->id);
        if (isset($status)) {
            $query->where('status', $status);
        } else {
            $query->whereIn('status', [ApplicationStatus::approved->value, ApplicationStatus::review->value]);
        }

        $applications = $query->orderBy('id', 'desc')->get();
        foreach ($applications as $app) {
            $car = UniModel::model('pipi_auto')->find($app->car_id);
            $model = UniModel::model('pipi_brand_models')->find($car->model_id);
            $photo = UniModel::model('core_files')->find($model->photo_id);
            $photo = url('api/files/file/' . ltrim($photo?->path, '/'));
            $class_id = UniModel::model('pipi_auto_classes')->where('id', $model->class_id)->first();
            $bodywork_id = UniModel::model('pipi_auto_bodywork')->where('id', $model->bodywork_id)->first();
            $address = UniModel::model('pipi_address')->where('id', $app->address_end)->first();
            $data[] = [
                'id' => $app->id,
                'rent_day' => $app->rent_day,
                'started_at' => $app->started_at,
                'ended_at' => $app->ended_at,
                'status' => ApplicationStatus::from($app->status)->getName(),
                'sum' => $app->sum ?? 0,
                'address_end' => $address->name ?? '',
                'car' => [
                    'name' => $model->name,
                    'year' => $model->year,
                    'people' => $model?->people ?? '5',
                    'actuator' => $model?->actuator ?? 'Передний',
                    'fuel_type' => $model?->fuel_type ?? 'АКПП',
                    'hp' => $model?->hp ?? '1.6',
                    'engine_capacity' => $model?->engine_capacity ?? '1591',
                    'fuel_tank' => $model?->fuel_tank ?? '50',
                    'class' => $class_id->name ?? 'Эконом',
                    'bodywork' => $bodywork_id->name ?? 'Седан',
                    'photo' => $photo ?? '',
                ]
            ];
        }
        if (empty($data)) {
            $data = (object) $data;
        }
        return response()->json($data);
    }

    public function login(Request $request)
    {
        $credentials = $request->only('email', 'password');

        if (auth()->attempt($credentials)) {
            $user = auth()->user();
            $tokenResult = $user->createToken('auth_token');

            $response = [
                'access_token' => $tokenResult->plainTextToken,
                'token_type' => 'Bearer',
                'user' => [
                    'id' => $user->id,
                    'name' => $user->name,
                    'email' => $user->email,
                ],
            ];

            return response()->json($response, 200);
        } else {
            return response()->json(['error' => 'Unauthorized'], 401);
        }
    }

    public function checkAvailableCar($started_at = null, $ended_at = null, $modelId = null, $color = null): JsonResponse
    {
        if (!$started_at || !$ended_at || !$modelId || !$color) {
            $request = request();
            $started_at = $started_at ?? $request->input('started_at');
            $ended_at = $ended_at ?? $request->input('ended_at');
            $modelId = $modelId ?? $request->input('model_id');
            $color = Unimodel::model('pipi_auto_colors')->where('code', $request->input('color'))->first()->id;
        }

        if (!$started_at || !$ended_at || !$modelId || !$color) {
            return response()->json(['available' => false]);
        }

        $started_at = Carbon::parse($started_at)->format('Y-m-d');
        $ended_at = Carbon::parse($ended_at)->format('Y-m-d');
        $cars = UniModel::model('pipi_auto')
            ->where('is_inactive', '=', false)
            ->where('model_id', $modelId)
            ->where('color_id', $color)
            ->get();
        $busyCars = UniModel::model('pipi_auto_calendar')
            ->whereBetween('date', [$started_at, $ended_at])
            ->pluck('auto_id')
            ->toArray();

        $availableCars = $cars->reject(fn($car) => in_array($car->id, $busyCars));

        return response()->json(['available' => $availableCars->isNotEmpty()]);
    }

    public function getAvailableMarksList(Request $request): JsonResponse
    {
        $started_at = $request->query('started_at');
        $ended_at = $request->query('ended_at');
        $class = $request->query('class');
        $bodywork = $request->query('bodywork');

        $marks = UniModel::model('pipi_brand_models')->get();

        $availableMarks = [];

        if ($class) {
            $class_id = UniModel::model('pipi_auto_classes')->where('name', $class)->first()?->id;
            $marks = $marks->where('class_id', $class_id);
        }
        if ($bodywork) {
            $bodywork_id = UniModel::model('pipi_auto_bodywork')->where('name', $bodywork)->first()?->id;
            $marks = $marks->where('bodywork_id', $bodywork_id);
        }

        foreach ($marks as $mark) {
            if ($mark->name === 'Ввод остатков') {
                continue;
            }

            $tariffs = UniModel::model('pipi_auto_tariffs')->where('model_id', $mark->id)->get();
            if ($tariffs->isEmpty()) {
                continue;
            }

            $cars = UniModel::model('pipi_auto')->where('model_id', $mark->id)->get();

            if ($cars->isEmpty()) {
                continue;
            }

            $brand = UniModel::model('pipi_auto_brands')->find($mark->brand_id);
            $tariffs = UniModel::model('pipi_auto_tariffs')->where('model_id', $mark->id)->get();
            $equipment = UniModel::model('pipi_auto_equipment')->where('id', $mark->equipment_id)->first();
            $class = UniModel::model('pipi_auto_classes')->find($mark->class_id);
            $bodywork = UniModel::model('pipi_auto_bodywork')->find($mark->bodywork_id);
            $photo = UniModel::model('core_files')->find($mark?->photo_id);

            $path = null;
            if ($photo) {
                $path = url('api/files/file/' . ltrim($photo->path, '/'));
            }

            $tariffs_new = [];
            foreach ($tariffs as $tariff) {
                $tariffs_new[] = [
                    'name'          => $tariff?->name,
                    'price'         => $tariff?->base_rate,
                    'min'           => $tariff?->day_range_start,
                    'max'           => $tariff?->day_range_end,
                    'deposit'       => $tariff?->deposit,
                ];
            }
            $carsByColor = $cars->groupBy('color_id');

            foreach ($carsByColor as $carColor => $carsOfColor) {
                $carColor = UniModel::model('pipi_auto_colors')->find($carColor);

                $colorPath = $path;
                if ($carsOfColor->first()->photo_id) {
                    $photo = UniModel::model('core_files')->find($carsOfColor->first()->photo_id);
                    $colorPath = url('api/files/file/' . ltrim($photo->path, '/'));
                }

                $key = $mark->name . '-' . $mark->year . '-' . $carColor->code;

                $availableMarks[$key] = [
                    'id' => $mark->id,
                    'brand' => $brand?->name,
                    'mark' => $mark->name,
                    'year' => $mark->year,
                    'color' => $carColor->code,
                    'configuration' => $equipment?->name,
                    'people' => $mark?->people ?? '5',
                    'actuator' => $mark?->actuator ?? 'Передний',
                    'fuel_type' => $mark?->fuel_type ?? 'АКПП',
                    'hp' => $mark?->hp ?? '1.6',
                    'engine_capacity' => $mark?->engine_capacity ?? '1591',
                    'fuel_tank' => $mark?->fuel_tank ?? '50',
                    'class' => $class->name ?? 'Эконом',
                    'bodywork' => $bodywork->name ?? 'Седан',
                    'deposit'   => $tariffs_new[0]['deposit'] ?? 30000,
                    'conditioner' => $mark?->conditioner,
                    'photo' => $colorPath,
                    'available' => $this->checkAvailableCar($started_at, $ended_at, $mark->id, $carColor->id)->getData()->available,
                    'tariffs' => $tariffs_new,
                ];
            }
        }

        if (empty($availableMarks)) {
            $availableMarks = (object) [];
        }
        return response()->json($availableMarks);
    }

    public function getAvailableCar($started_at, $ended_at, $modelId, $color)
    {
        $started_at = Carbon::parse($started_at)->format('Y-m-d');
        $ended_at = Carbon::parse($ended_at)->format('Y-m-d');
        $color = UniModel::model('pipi_auto_colors')->where('code', $color)->first()->id;
        $cars = UniModel::model('pipi_auto')
            ->where('color_id', $color)
            ->where('model_id', $modelId)
            ->whereNull('regular_user')
            ->get();
        $busyCars = UniModel::model('pipi_auto_calendar')
            ->whereBetween('date', [$started_at, $ended_at])
            ->pluck('auto_id')
            ->toArray();

        $availableCars = $cars->reject(fn($car) => in_array($car->id, $busyCars));

        if ($availableCars->isNotEmpty()) {
            return $availableCars->first();
        } else {
            return null;
        }
    }

    public function getSum(Request $request)
    {
        $started_at = $request->input('started_at');
        $ended_at = $request->input('ended_at');
        $mark_id = $request->input('mark_id');

        $start = Carbon::createFromFormat('d-m-Y H:i', $started_at);
        $end = Carbon::createFromFormat('d-m-Y H:i', $ended_at);
        try {
            $service = new DepositService();
            $summary = $service->calculateSummary($mark_id, $start, $end);

            return response()->json($summary);
        } catch (\Exception $e) {
            return response()->json(['error' => $e->getMessage()], 400);
        }
    }

    public function closeOrder(Request $request): JsonResponse
    {
        $order_id = $request->input('order_id');

        $application = UniModel::model('pipi_applications')->find($order_id);
        if (!isset($application)) {
            return response()->json([
                'success' => false,
                'message' => __('Такой заявки не существует')
            ]);
        }

        if (count($request->file('photos')) < 5) {
            return response()->json([
                'success' => false,
                'message' => __('Неверное количество фотографий')
            ]);
        }

        foreach ($request->file('photos') as $photo) {
            $files[] = $this->uploadFile($photo);
        }
        $application->photos = $files;
        $application->status = ApplicationStatus::review->value;
        $application->save();

        $notification = [];
        $notification['ID заявки'] = $application->id;
        $notification['Сообщение'] = __('Получена заявка на закрытие');
        $this->sendNotification($notification);
        return response()->json([
            'success' => true,
            'message' => __('Фото получены ожидайте закрытия заявки после проверки оператором'),
        ]);
    }

    private function uploadFile($file)
    {
        $ufile = UniModel::model(config('platform.file_manager.tables.files'));
        $ufile->filename = $file->getClientOriginalName();
        $ufile->path = $this->_gen_storage_file_name($file->getClientOriginalExtension());
        $ufile->ext = $file->getClientOriginalExtension();
        $ufile->size = $file->getSize();
        $ufile->mime = $file->getClientMimeType();
        $ufile->public = 1;
        $ufile->user_file = 1;
        $ufile->company_file = 1;

        Storage::disk('file')->put($ufile->path, file_get_contents($file->getRealPath()));
        $ufile->save();

        return ['status' => 1, 'file_id' => $ufile->id, 'name' => 'photos', 'file_name' => $ufile->filename];
    }

    private function _gen_storage_file_name($ext): string
    {
        $storage_file_name = md5(time());
        $folder1 = substr($storage_file_name, 0, 2);
        $folder2 = substr($storage_file_name, 2, 3);
        return $folder1 . '/' . $folder2 . '/' . $storage_file_name . '.' . $ext;
    }

    public function getAddress(): JsonResponse
    {
        $addresses = UniModel::model('pipi_address')->get();
        foreach ($addresses as $address) {
            $data[$address->id] = $address->name;
        }

        if (empty($data)) {
            $data = (object) [];
        }

        return response()->json($data);
    }

    public function getFAQCategory(): JsonResponse
    {
        $faqs = UniModel::model('pipi_faq')->distinct('category')->get();
        $data = [];
        foreach ($faqs as $faq) {
            $data[] = $faq->category;
        }

        return response()->json($data);
    }
    public function getFAQSubCategory(Request $request): JsonResponse
    {
        $category = $request->query('category');

        $query = UniModel::model('pipi_faq');
        if (isset($category)) {
            $query->where('category', $category);
        }
        $faqs = $query->distinct('subcategory')->get();
        $data = [];
        foreach ($faqs as $faq) {
            $data[] = $faq->subcategory;
        }

        return response()->json($data);
    }
    public function getFAQText(Request $request): JsonResponse
    {
        $subcategory = $request->query('subcategory');

        $query = UniModel::model('pipi_faq')->where('subcategory', $subcategory)->first();
        $text = $query?->text;

        return response()->json($text ?? '');
    }

    private function sendNotification(array $data): void
    {
        foreach ($data as $key => $value) {
            $text[$key] = $key . ': ' . $value;
        }
        Notification::send([$text], new TelegramNotification($text));
    }
}
