<?php

namespace App\Http\Controllers;

use App\Http\Requests\LoginRequest;
use App\Http\Requests\RegisterRequest;
use App\Http\Requests\UpdateUserRequest;
use App\Http\Resources\UserResource;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class AuthController extends Controller
{
    public function register(RegisterRequest $request)
    {
        $data = $request->validated();

        $avatarPath = null;
        if ($request->hasFile('avatar')) {
            $avatarPath = $request->file('avatar')->store('avatars', 'public');
        }

        $user = User::create([
            'name' => $data['name'],
            'email' => strtolower($data['email']),
            'password' => Hash::make($data['password']),
            'avatar_url' => $avatarPath,
        ]);

        $token = $user->createToken('api', ['user'])->plainTextToken;

        return response()->json([
            'user' => new UserResource($user),
        ], 201)->cookie('token', $token, 60 * 24 * 30);
    }

    public function login(LoginRequest $request): JsonResponse
    {
        $data = $request->validated();

        $user = User::where('email', strtolower($data['email']))->first();

        if (! $user || ! Hash::check($data['password'], $user->password)) {
            return response()->json([
                'message' => 'Identifiants invalides',
            ], 401);
        }

        $token = $user->createToken('api')->plainTextToken;

        return response()->json([
            'user' => new UserResource($user),
        ])->cookie('token', $token, 60 * 24 * 30);
    }

    public function logout(): JsonResponse
    {
        $request = request();
        $request->user()->currentAccessToken()->delete();

        return response()->json([
            'message' => 'Déconnecté avec succès',
        ])->withoutCookie('token');
    }

    public function me(): JsonResource|JsonResponse
    {
        $user = auth()->user();

        if (! $user) {
            return response()->json(['message' => 'Non authentifié'], 401);
        }

        return new UserResource($user);
    }

    public function update(UpdateUserRequest $request): JsonResource
    {
        $user = $request->user();
        $data = $request->validated();
        $nutritionGoals = $data['nutritionGoals'] ?? null;

        if ($request->hasFile('avatar')) {
            if ($user->avatar_url) {
                Storage::disk('public')->delete($user->avatar_url);
            }

            $path = $request->file('avatar')->store('avatars', 'public');
            $data['avatar_url'] = $path;
        }

        unset($data['avatar']);
        unset($data['nutritionGoals']);

        if (is_array($nutritionGoals)) {
            $data['daily_calorie_goal'] = $nutritionGoals['calories'];
            $data['daily_protein_goal'] = $nutritionGoals['proteins'];
            $data['daily_carbs_goal'] = $nutritionGoals['carbs'];
            $data['daily_fats_goal'] = $nutritionGoals['fats'];
        }

        if (! empty($data)) {
            $user->update($data);
        }

        return new UserResource($user->fresh());
    }

    public function destroy(Request $request): JsonResponse
    {
        $user = $request->user();
        $storagePaths = collect([$user->avatar_url])
            ->merge($user->mealPosts()->withTrashed()->pluck('image_url'))
            ->filter(fn (?string $path): bool => $this->isPublicStoragePath($path))
            ->values()
            ->all();

        DB::transaction(function () use ($user): void {
            $user->tokens()->delete();
            $user->notifications()->delete();

            DB::table('sessions')
                ->where('user_id', $user->getKey())
                ->delete();

            DB::table('password_reset_tokens')
                ->where('email', $user->email)
                ->delete();

            $user->delete();
        });

        if (! empty($storagePaths)) {
            Storage::disk('public')->delete($storagePaths);
        }

        return response()->json([
            'message' => 'Compte supprimé avec succès',
        ])->withoutCookie('token');
    }

    private function isPublicStoragePath(?string $path): bool
    {
        return filled($path) && ! Str::startsWith($path, ['http://', 'https://']);
    }
}
