<?php

namespace App\Services;

use App\Mail\AdminPasswordChangedMail;
use App\Mail\AdminPasswordResetMail;
use App\Mail\AdminTemporaryPasswordMail;
use App\Models\AdminUser;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;

class AdminCredentialService
{
    public function temporaryPassword(): string
    {
        return Str::password(16, symbols: true);
    }

    public function sendTemporaryPassword(AdminUser $adminUser, string $password): void
    {
        Mail::to($adminUser->email, $adminUser->name)->send(new AdminTemporaryPasswordMail($adminUser, $password));
    }

    public function sendResetLink(string $email): void
    {
        $adminUser = AdminUser::where('email', strtolower($email))->where('status', 'active')->first();
        if (! $adminUser) {
            return;
        }

        $token = Str::random(64);
        DB::table('admin_password_reset_tokens')->updateOrInsert(
            ['email' => $adminUser->email],
            ['token' => Hash::make($token), 'created_at' => now()],
        );
        $url = route('password.reset', ['token' => $token, 'email' => $adminUser->email]);
        Mail::to($adminUser->email, $adminUser->name)->send(new AdminPasswordResetMail($adminUser, $url));
    }

    public function resetPassword(string $email, string $token, string $password): AdminUser
    {
        $record = DB::table('admin_password_reset_tokens')->where('email', strtolower($email))->first();
        if (! $record || ! Hash::check($token, $record->token) || now()->diffInMinutes($record->created_at, absolute: true) > 60) {
            throw ValidationException::withMessages(['email' => 'This password reset link is invalid or has expired.']);
        }

        $adminUser = AdminUser::where('email', strtolower($email))->firstOrFail();
        $this->changePassword($adminUser, $password);
        DB::table('admin_password_reset_tokens')->where('email', $adminUser->email)->delete();

        return $adminUser;
    }

    public function changePassword(AdminUser $adminUser, string $password): void
    {
        $adminUser->update(['password' => $password, 'force_change_password' => false]);
        try {
            Mail::to($adminUser->email, $adminUser->name)->send(new AdminPasswordChangedMail($adminUser));
        } catch (\Throwable $exception) {
            report($exception);
        }
    }
}
