<?php

namespace App\Http\Controllers;

use App\Models\Bidang;
use App\Models\JadwalMingguan;
use App\Models\PembimbingMagang;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;

class AuthController extends Controller
{
    public function showLogin(Request $request)
    {
        if (Auth::check()) {
            return $this->redirectAuthenticatedUser($request);
        }

        $loginRole = $request->query('role');
        $activeAuthMode = $request->query('mode') === 'register' && ! in_array($loginRole, ['admin', 'superadmin'], true)
            ? 'register'
            : 'login';

        return view('admin.login', [
            'loginRole' => $loginRole,
            'activeAuthMode' => $activeAuthMode,
            'bidangs' => Bidang::orderBy('nama', 'asc')->pluck('nama'),
            'bidangOptions' => Bidang::orderBy('nama', 'asc')->get(),
            'pembimbingOptions' => PembimbingMagang::orderBy('nama', 'asc')->get(),
            'title' => 'Login Akun',
            'action' => route('login'),
        ]);
    }

    public function showRegister(Request $request)
    {
        if (Auth::check()) {
            return $this->redirectAuthenticatedUser($request);
        }

        return redirect()->route('login.form', ['mode' => 'register']);
    }

    public function showForgotPassword(Request $request)
    {
        if (Auth::check()) {
            return $this->redirectAuthenticatedUser($request);
        }

        if ($request->boolean('reset')) {
            $request->session()->forget('password_reset_user_id');
        }

        $verifiedResetUser = null;
        if ($request->session()->has('password_reset_user_id')) {
            $verifiedResetUser = User::where('role', 'user')
                ->find($request->session()->get('password_reset_user_id'));

            if (! $verifiedResetUser) {
                $request->session()->forget('password_reset_user_id');
            }
        }

        return view('admin.login', [
            'loginRole' => null,
            'activeAuthMode' => 'forgot',
            'verifiedResetUser' => $verifiedResetUser,
            'bidangs' => Bidang::orderBy('nama', 'asc')->pluck('nama'),
            'bidangOptions' => Bidang::orderBy('nama', 'asc')->get(),
            'pembimbingOptions' => PembimbingMagang::orderBy('nama', 'asc')->get(),
            'title' => 'Lupa Password',
            'subtitle' => 'Masukkan nama dan email yang dipakai saat registrasi.',
            'action' => route('login'),
        ]);
    }

    public function login(Request $request)
    {
        $credentials = $request->validate([
            'login' => 'required|string',
            'password' => 'required|string',
            'expected_role' => ['nullable', Rule::in(['admin', 'superadmin', 'admin_instansi'])],
        ], [
            'login.required' => 'Email atau ID admin wajib diisi.',
            'password.required' => 'Password wajib diisi.',
        ]);

        $login = trim($credentials['login']);
        $expectedRole = $credentials['expected_role'] ?? null;
        $isEmailLogin = filter_var($login, FILTER_VALIDATE_EMAIL);

        if ($expectedRole) {
            $field = $isEmailLogin ? 'email' : 'username';
        } elseif ($isEmailLogin) {
            $field = 'email';
        } else {
            $adminAccount = User::where('username', $login)
                ->whereIn('role', ['admin', 'superadmin', 'admin_instansi', 'admin_kesbangpol'])
                ->first();

            if (! $adminAccount) {
                return redirect()->back()
                    ->withInput($request->only('login'))
                    ->with('error_swal', 'Masukkan email peserta yang terdaftar atau ID admin yang valid.');
            }

            $field = 'username';
        }

        if (! Auth::attempt([$field => $login, 'password' => $credentials['password'], 'status_akun' => 'aktif'], $request->boolean('remember'))) {
            return redirect()->back()
                ->withInput($request->only('login'))
                ->with('error_swal', 'Akun atau password tidak valid.');
        }

        $request->session()->regenerate();

        if ($expectedRole && Auth::user()->role !== $expectedRole) {
            Auth::logout();
            $request->session()->invalidate();
            $request->session()->regenerateToken();

            return redirect()
                ->route('login.form', ['role' => $expectedRole])
                ->withInput($request->only('login'))
                ->with('error_swal', 'Gunakan akun '.($expectedRole === 'superadmin' ? 'Super Admin' : 'Admin').' untuk masuk ke halaman ini.');
        }

        session([
            'admin_authenticated' => in_array(Auth::user()->role, ['admin', 'superadmin', 'admin_instansi', 'admin_kesbangpol'], true),
            'admin_role' => Auth::user()->role,
        ]);

        if (Auth::user()->role === 'superadmin') {
            return redirect()->route('admin.dashboard')->with('success_swal', 'Login Super Admin berhasil!');
        }

        if (Auth::user()->role === 'admin_kesbangpol') {
            return redirect()->route('kesbangpol.dashboard')->with('success_swal', 'Berhasil masuk sebagai Admin Kesbangpol');
        }

        if (Auth::user()->role === 'admin' || Auth::user()->role === 'admin_instansi') {
            return redirect()->route('admin.dashboard', ['tab' => 'pegawai'])->with('success_swal', 'Login Admin berhasil!');
        }

        return redirect()->intended(route('home'))->with('success_swal', 'Login peserta magang berhasil!');
    }

    public function register(Request $request)
    {
        $data = $request->validate([
            'nama' => 'required|string|max:100',
            'email' => 'required|email|max:100|unique:md_user,email',
            'password' => 'required|string|min:6|confirmed',
            'nik' => 'required|string|max:16|unique:md_user,nik',
            'nim' => 'required|string|max:30',
            'tempat_lahir' => 'required|string|max:100',
            'tanggal_lahir' => 'required|date',
            'program_studi' => 'required|string|max:150',
            'asal_instansi' => 'required|string|max:255',
            'no_hp' => 'required|string|max:30',
            'alamat' => 'required|string',
        ], [
            'nama.required' => 'Nama lengkap wajib diisi.',
            'email.required' => 'Email wajib diisi.',
            'email.email' => 'Format email tidak valid.',
            'email.unique' => 'Email sudah terdaftar.',
            'password.required' => 'Password wajib diisi.',
            'password.min' => 'Password minimal 6 karakter.',
            'password.confirmed' => 'Konfirmasi password tidak sama.',
            'nik.required' => 'NIK wajib diisi.',
            'nik.unique' => 'NIK sudah digunakan.',
            'nim.required' => 'NIM / NIS wajib diisi.',
            'tempat_lahir.required' => 'Tempat lahir wajib diisi.',
            'tanggal_lahir.required' => 'Tanggal lahir wajib diisi.',
            'program_studi.required' => 'Program studi wajib diisi.',
            'asal_instansi.required' => 'Asal instansi pendidikan wajib diisi.',
            'no_hp.required' => 'Nomor WhatsApp wajib diisi.',
            'alamat.required' => 'Alamat lengkap wajib diisi.',
        ]);

        $user = User::create([
            'nama' => $data['nama'],
            'username' => $this->generateUsername($data['nama'], $data['email']),
            'email' => $data['email'],
            'password' => $data['password'],
            'nik' => $data['nik'],
            'nim' => $data['nim'],
            'tempat_lahir' => $data['tempat_lahir'],
            'tanggal_lahir' => $data['tanggal_lahir'],
            'program_studi' => $data['program_studi'],
            'asal_instansi' => $data['asal_instansi'],
            'no_hp' => $data['no_hp'],
            'alamat' => $data['alamat'],
            'role' => 'user',
            'status_akun' => 'aktif',
        ]);

        $user->jadwalMingguan()->create(JadwalMingguan::defaultSchedule());

        Auth::login($user);
        $request->session()->regenerate();

        session([
            'admin_authenticated' => false,
            'admin_role' => 'user',
        ]);

        return redirect()->route('home')->with('success_swal', 'Registrasi berhasil. Akun peserta magang sudah aktif.');
    }

    public function verifyForgotPasswordIdentity(Request $request)
    {
        $data = $request->validate([
            'nama' => 'required|string|max:100',
            'email' => 'required|email|max:100',
        ], [
            'nama.required' => 'Nama lengkap wajib diisi.',
            'email.required' => 'Email wajib diisi.',
            'email.email' => 'Format email tidak valid.',
        ]);

        $nama = $this->normalizeName($data['nama']);
        $email = Str::lower(trim($data['email']));

        $user = User::where('role', 'user')
            ->whereRaw('LOWER(nama) = ?', [Str::lower($nama)])
            ->whereRaw('LOWER(email) = ?', [$email])
            ->first();

        if (! $user) {
            return redirect()->back()
                ->withInput($request->only('nama', 'email'))
                ->with('error_swal', 'Nama dan email tidak cocok dengan data registrasi peserta.');
        }

        $request->session()->put('password_reset_user_id', $user->id);

        return redirect()
            ->route('password.request')
            ->with('success_swal', 'Data peserta ditemukan. Silakan buat password baru.');
    }

    public function resetUserPassword(Request $request)
    {
        $userId = $request->session()->get('password_reset_user_id');
        $user = $userId ? User::where('role', 'user')->find($userId) : null;

        if (! $user) {
            return redirect()
                ->route('password.request')
                ->with('error_swal', 'Verifikasi nama dan email terlebih dahulu sebelum membuat password baru.');
        }

        $data = $request->validate([
            'password' => 'required|string|min:6|confirmed',
        ], [
            'password.required' => 'Password baru wajib diisi.',
            'password.min' => 'Password baru minimal 6 karakter.',
            'password.confirmed' => 'Konfirmasi password baru tidak sama.',
        ]);

        $user->update([
            'password' => $data['password'],
        ]);

        $request->session()->forget('password_reset_user_id');

        return redirect()
            ->route('login.form')
            ->withInput(['login' => $user->email])
            ->with('success_swal', 'Password berhasil diperbarui. Silakan masuk dengan password baru.');
    }

    public function logout(Request $request)
    {
        Auth::logout();

        $request->session()->forget(['admin_authenticated', 'admin_role']);
        $request->session()->invalidate();
        $request->session()->regenerateToken();

        return redirect()->route('home')->with('success_swal', 'Logout berhasil.');
    }

    private function redirectAuthenticatedUser(Request $request)
    {
        $user = Auth::user();
        $requestedRole = $request->query('role');

        if (in_array($requestedRole, ['admin', 'superadmin', 'admin_instansi'], true) && $user->role !== $requestedRole) {
            return redirect()->route($user->role === 'user' ? 'home' : 'admin.dashboard')
                ->with('error_swal', 'Anda sudah login sebagai '.ucfirst($user->role).'. Logout dulu untuk masuk sebagai role lain.');
        }

        if ($user->role === 'superadmin') {
            return redirect()->route('admin.dashboard');
        }

        if ($user->role === 'admin_kesbangpol') {
            return redirect()->route('kesbangpol.dashboard');
        }

        if (in_array($user->role, ['admin', 'admin_instansi'], true)) {
            return redirect()->route('admin.dashboard', ['tab' => 'pegawai']);
        }

        return redirect()->route('home');
    }

    private function generateUsername(string $name, string $email): string
    {
        $emailPrefix = Str::before($email, '@');
        $base = Str::of($emailPrefix ?: $name)
            ->lower()
            ->replaceMatches('/[^a-z0-9._-]+/', '.')
            ->trim('.-_')
            ->value();

        $base = $base !== '' ? $base : 'peserta';
        $username = $base;
        $counter = 1;

        while (User::where('username', $username)->exists()) {
            $username = $base.$counter;
            $counter++;
        }

        return $username;
    }

    private function normalizeName(string $name): string
    {
        return trim(preg_replace('/\s+/', ' ', $name));
    }
}
