<?php

namespace App\Http\Controllers;

use App\Models\User;
use App\Models\Course;
use App\Models\Note;
use App\Models\Progress;
use App\Models\Receipt;
use App\Models\Role;
use App\Models\Subscription;
use App\Models\SubscriptionProduct;
use App\Models\UserCertificate;
use App\Models\UserCourse;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;

class AdminController extends Controller
{
    public function usuarios(Request $request) {

        $buscar = $request->input('buscar');
        $estadoUsuario = $request->input('estadoUsuario');
        $filtroPorRol = $request->input('filtroPorRol');
        $ownedCourses = $request->input('ownedCourses', 0);
        $completedCourses = $request->input('completedCourses', 0);
        $subscriptionPlans = $request->input('subscriptionPlans', []);
        $orden = $request->input('orden', 'desc');

        // Obtener valores del ENUM del campo status
        $statusType = DB::select("SHOW COLUMNS FROM users WHERE Field = 'status'")[0];

        preg_match('/enum\((.*)\)/', $statusType->Type, $matches);
        $enumValues = array_map(fn($value) => trim($value, "'"), explode(',', $matches[1]));

        // Obtener roles y sus IDs
        $roles = Role::select('id','name')->orderByDesc('id')->get();

        // Obtener todos los planes de suscripción
        $subscriptionProducts = SubscriptionProduct::all();
    
        // Consulta de usuarios
        $usuarios = User::with('role', 'courses', 'subscriptions.subscriptionProduct')
        ->withCount('ownedCourses')
        ->when($buscar, function ($query) use ($buscar) {
            $query->where(function ($q) use ($buscar) {
                $q->where('name', 'like', "%$buscar%")
                ->orWhere('surname', 'like', "%$buscar%")
                ->orWhere('username', 'like', "%$buscar%")
                ->orWhere('email', 'like', "%$buscar%");
            });
        })
        ->when($estadoUsuario, function ($query) use ($estadoUsuario) {
            $query->where('status', $estadoUsuario);
        })
        ->when($filtroPorRol, function ($query) use ($filtroPorRol) {
            $query->where('role_id', $filtroPorRol);
        })
        ->when($ownedCourses, function ($query) use ($ownedCourses) {
            if ($ownedCourses == 0) {
                $query->orWhere('owned_courses_count', 0);
            } else {
                $query->having('owned_courses_count', '>=', $ownedCourses);
            }
        })
        ->when($completedCourses, function ($query) use ($completedCourses) {
            if ($completedCourses == 0) {
                $query->orWhere('completed_courses', 0);
            } else {
                $query->having('completed_courses', '>=', $completedCourses);
            }
        })
        ->when(!empty($subscriptionPlans), function ($query) use ($subscriptionPlans) {
            foreach ($subscriptionPlans as $planId) {
                $query->whereHas('subscriptions', function ($q) use ($planId) {
                    $q->where('subscription_product_id', $planId);
                });
            }
        })    
        ->orderBy('id', $orden)
        ->get();
    

        // Si es una solicitud AJAX, retorna solo datos
        if ($request->expectsJson()) {
            return response()->json(['usuarios' => $usuarios]);
        }
    
        return view('pages.admin.cruds.users', compact('usuarios', 'enumValues','roles','subscriptionProducts'));
    }

    public function deleteUser(Request $request) {

        $userId = $request->id;

        DB::beginTransaction();

        try {

            $user = User::findOrFail($userId);

            // Eliminar notas del usuario
            Note::where('owner_id', $userId)->delete();

            // Eliminar progresos
            Progress::where('user_id', $userId)->delete();

            // Eliminar cursos del usuario y certificados asociados
            $userCourses = UserCourse::where('user_id', $userId)->get();
            
            foreach ($userCourses as $uc) {
                UserCertificate::where('user_course_id', $uc->id)->delete();
            }

            UserCourse::where('user_id', $userId)->delete();

            // Setear owner_id en NULL en cursos
            Course::where('owner_id', $userId)->update(['owner_id' => NULL]);

            // Eliminar suscripciones y recibos asociados
            $subscriptions = Subscription::where('user_id', $userId)->get();

            foreach ($subscriptions as $sub) {
                Receipt::where('id', $sub->receipt_id)->delete();
            }

            Subscription::where('user_id', $userId)->delete();

            // Finalmente, eliminar el usuario
            $user->delete();

            DB::commit();

            return response()->json(['message' => 'Usuario eliminado correctamente']);

        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['message' => 'Error eliminando el usuario.'], 500);
        }

    }

    public function updateUser(Request $request, $id) {

        $request->validate([
            'name' => 'required|string|max:255',
            'surname' => 'nullable|string|max:255',
            'username' => 'required|string|max:255|unique:users,username,' . $id,
            'email' => 'required|email|max:255|unique:users,email,' . $id,
            'status' => 'required|in:active,inactive,banned',
            'role_id' => 'required|exists:roles,id',
            'subscriptions' => 'nullable|array',
            'subscriptions.*' => 'exists:subscription_products,id',
        ]);
    
        $user = User::findOrFail($id);
    
        $user->update([
            'name' => $request->input('name'),
            'surname' => $request->input('surname'),
            'username' => $request->input('username'),
            'email' => $request->input('email'),
            'password' => Hash::make($request->password),
            'status' => $request->input('status'),
            'role_id' => $request->input('role_id'),
        ]);
    
        // Obtener suscripciones actuales
        $currentSubs = Subscription::where('user_id', $user->id)->pluck('subscription_product_id')->toArray();
    
        // Nuevas seleccionadas
        $selectedIds = $request->input('subscriptions', []);
    
        // Eliminar las que ya no están seleccionadas
        $subsToDelete = array_diff($currentSubs, $selectedIds);
        if (!empty($subsToDelete)) {
            Subscription::where('user_id', $user->id)->whereIn('subscription_product_id', $subsToDelete)->delete();
        }
    
        // Agregar nuevas suscripciones si no existen
        foreach ($selectedIds as $subId) {
            $exists = Subscription::where('user_id', $user->id)
                ->where('subscription_product_id', $subId)
                ->exists();
    
            if (!$exists) {
    
                $subscriptionProduct = SubscriptionProduct::findOrFail($subId);
                $pricePaid = $subscriptionProduct->price;
                $subscriptionDate = Carbon::now()->addMonth();
                
                if ($subscriptionProduct->name === 'Free') {

                    Subscription::create([
                        'user_id' => $user->id,
                        'subscription_product_id' => $subId,
                        'receipt_id' => null,
                        'price_paid' => $pricePaid,
                        'created_at' => Carbon::now(),
                        'updated_at' => Carbon::now(),
                    ]);

                } else {

                    Subscription::create([
                        'user_id' => $user->id,
                        'subscription_product_id' => $subId,
                        'receipt_id' => null,
                        'price_paid' => $pricePaid,
                        'subscription_date' => $subscriptionDate,
                        'created_at' => Carbon::now(),
                        'updated_at' => Carbon::now(),
                    ]);

                }
            }
        }
    
        return response()->json(['message' => 'Usuario actualizado correctamente', 'user' => $user]);
    }

    public function subscriptionsJSON(Request $request) {

        try {
            
            $query = SubscriptionProduct::query();

            $products = $query->get();

            return response()->json([
                'products' => $products
            ], 200);

        } catch (\Exception $e) {

            return response()->json([
                'error' => $e->getMessage()
            ], 500);

        }

    }

    public function rolesJSON(Request $request) {

        try {

            $query = Role::query()->orderByDesc('id');

            $roles = $query->get();

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

    }

    public function statusJSON(Request $request) {

        try {
            // Obtener valores del ENUM del campo status
            $statusType = DB::select("SHOW COLUMNS FROM users WHERE Field = 'status'")[0];
    
            preg_match('/enum\((.*)\)/', $statusType->Type, $matches);
            $enumValues = array_map(fn($value) => trim($value, "'"), explode(',', $matches[1]));
    
            return response()->json([
                'enumValues' => $enumValues
            ], 200);
    
        } catch (\Exception $e) {
            return response()->json([
                'error' => $e->getMessage()
            ], 500);
        }
    }

    public function createUser(Request $request) {
    
        // Log::info('Creating user with request data:', $request->all());
    
        $errors = [];
    
        if (empty($request->name)) {
            $errors['name'] = 'Name is required';
        } elseif (!preg_match('/^\p{Lu}\p{L}*$/u', $request->name)) {
            $errors['name'] = 'Name must start with a capital letter and contain only letters';
        }
    
        if (empty($request->surname)) {
            $errors['surname'] = 'Surname is required';
        } elseif (!preg_match('/^(\p{Lu}\p{L}+)(\s\p{Lu}\p{L}+)?$/u', $request->surname)) {
            $errors['surname'] = 'Surname must start with capital letters';
        }
    
        if (empty($request->username)) {
            $errors['username'] = 'Username is required';
        } elseif (!preg_match('/^[a-z]+$/', $request->username)) {
            $errors['username'] = 'Username must contain only lowercase letters';
        }
        
        if (empty($request->email)) {
            $errors['email'] = 'Email is required';
        } elseif (!filter_var($request->email, FILTER_VALIDATE_EMAIL)) {
            $errors['email'] = 'Email is not valid';
        }
        
        if (empty($request->password)) {
            $errors['password'] = 'Password is required';
        } elseif (!empty($request->password) && strlen($request->password) < 8) {
            $errors['password'] = 'Password must have at least 8 characters';
        }

        if (empty($request->password_confirmation)) {
            $errors['password_confirmation'] = 'Write your password again';
        } elseif (!empty($request->password) && !empty($request->password_confirmation) && $request->password !== $request->password_confirmation) {
            $errors['password_confirmation'] = 'Passwords do not match';
        } elseif (!empty($request->password) && strlen($request->password) < 8) {
            $errors['password'] = 'Password must have at least 8 characters';
        }
    
        if (empty($request->role_id)) {
            $errors['role_id'] = 'Role is required';
        } elseif (!is_numeric($request->role_id) || !Role::find($request->role_id)) {
            $errors['role_id'] = 'Selected role does not exist';
        }
    
        $validStatuses = ['active', 'inactive'];
        if (empty($request->status)) {
            $errors['status'] = 'Status is required';
        } elseif (!in_array($request->status, $validStatuses)) {
            $errors['status'] = 'Invalid status selected';
        }
    
        if (!$request->filled('subscriptions') || !is_array($request->subscriptions) || count($request->subscriptions) === 0) {
            $errors['subscriptions'] = 'You must select at least one subscription';
        } else {
            foreach ($request->subscriptions as $subId) {
                if (!is_numeric($subId) || !SubscriptionProduct::find($subId)) {
                    $errors['subscriptions'] = 'One or more selected subscriptions are invalid';
                    break;
                }
            }
        }        
    
        if (!empty($errors)) {
            // Log::info('Validation failed:', $errors);
            return redirect()->route('users.create')->withInput()->withErrors($errors);
        }
    
        Log::info('Passed manual validations, proceeding with Laravel validation');
    
        $request->validate([
            'name' => 'required|string|max:255',
            'surname' => 'nullable|string|max:255',
            'username' => 'required|string|max:255|unique:users,username',
            'email' => 'required|email|max:255|unique:users,email',
            'password' => 'required|string|min:8',
            'status' => 'required|in:active,inactive',
            'role_id' => 'required|exists:roles,id',
            'subscriptions' => 'nullable|array',
            'subscriptions.*' => 'exists:subscription_products,id',
        ]);
    
        Log::info('Creating user in database');
    
        $user = User::create([
            'name' => $request->input('name'),
            'surname' => $request->input('surname'),
            'username' => $request->input('username'),
            'email' => $request->input('email'),
            'password' => Hash::make($request->password),
            'coins' => 0,
            'status' => $request->input('status'),
            'completed_courses' => 0,
            'role_id' => $request->input('role_id'),
            'remember_token' => Str::random(60),
            'created_at' => Carbon::now(),
            'updated_at' => Carbon::now(),
        ]);
    
        // Log::info('User created:', ['user_id' => $user->id]);
    
        $selectedIds = $request->input('subscriptions', []);
        // Log::info('Attaching subscriptions:', ['user_id' => $user->id, 'subscriptions' => $selectedIds]);
    
        foreach ($selectedIds as $subId) {
            $subscriptionProduct = SubscriptionProduct::findOrFail($subId);
            $pricePaid = $subscriptionProduct->price;
            $subscriptionDate = Carbon::now()->addMonth();
    
            if ($subscriptionProduct->name === 'Free') {
                Subscription::create([
                    'user_id' => $user->id,
                    'subscription_product_id' => $subId,
                    'receipt_id' => null,
                    'price_paid' => $pricePaid,
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now(),
                ]);
                Log::info("Free subscription added", ['user_id' => $user->id, 'subscription_id' => $subId]);
            } else {
                Subscription::create([
                    'user_id' => $user->id,
                    'subscription_product_id' => $subId,
                    'receipt_id' => null,
                    'price_paid' => $pricePaid,
                    'subscription_date' => $subscriptionDate,
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now(),
                ]);
                Log::info("Paid subscription added", ['user_id' => $user->id, 'subscription_id' => $subId]);
            }
        }
    
        Log::info('User creation process completed successfully');
    
        return response()->json(['message' => 'User successfully created', 'user' => $user]);
    }

    public function createRole(Request $request) {

        $request->validate(['name' => 'required|string|max:255']);

        $role = Role::create(['name' => $request->name]);

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

    public function showReviewRequests() {

        $requests = User::where('change_role', true)->get();
        return view('pages.admin.review_requests', compact('requests'));

    }

    public function approveTeacher($id) {

        $user = User::findOrFail($id);
        $user->update([
            'role_id' => 2,
            'change_role' => false
        ]);
        return redirect()->back()->with('success', 'Teacher approved.');

    }

    public function rejectTeacher($id) {

        $user = User::findOrFail($id);
        $user->update([
            'change_role' => false,
            'cv' => null,
            'portfolio' => null,
            'linkedin' => null,
        ]);
        return redirect()->back()->with('success', 'Request rejected.');

    }

}
