<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Models\Dealer;
use App\Models\PasswordChangeToken;
use App\Models\User;
use App\Support\PasswordPolicy;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\View\View;

class FirstLoginPasswordController extends Controller
{
    /**
     * Show the set-password form. Token must be valid; otherwise redirect to login with generic message.
     */
    public function show(Request $request, string $token): View|RedirectResponse
    {
        $record = $this->findValidToken($token);

        if (!$record) {
            return redirect()->route('login')->withErrors(['email' => 'This link has expired or is invalid. Please log in to request a new one.']);
        }

        $user = User::find($record->user_id);
        if (!$user) {
            return redirect()->route('login')->withErrors(['email' => 'This link has expired or is invalid. Please log in to request a new one.']);
        }

        $dealer = null;
        if ($user->dealer_id) {
            $dealer = Dealer::find($user->dealer_id);
        }

        return view('auth.first-login-set-password', [
            'token' => $token,
            'passwordHint' => PasswordPolicy::hintText(),
            'dealer' => $dealer,
            'loginUrl' => $this->dealerLoginRouteFromUser($user),
        ]);
    }

    /**
     * Update password using the one-time token.
     */
    public function update(Request $request, string $token): RedirectResponse
    {
        $request->validate([
            'password' => array_merge(PasswordPolicy::rules(), ['confirmed']),
        ], PasswordPolicy::messages());

        $record = $this->findValidToken($token);

        if (!$record) {
            return redirect()->route('login')->withErrors(['email' => 'This link has expired or is invalid. Please log in to request a new one.']);
        }

        $user = User::find($record->user_id);
        if (!$user) {
            return redirect()->route('login')->withErrors(['email' => 'This link has expired or is invalid. Please log in to request a new one.']);
        }

        if ($user->isSamePassword($request->password)) {
            return back()->withErrors(['password' => 'Your new password must be different from your current password.']);
        }

        $user->password = Hash::make($request->password);
        $user->force_password_change = false;
        $user->save();

        $record->used_at = now();
        $record->save();

        $loginRoute = $this->dealerLoginRouteFromUser($user);

        return redirect($loginRoute)->with('status', 'Password updated. Please log in.');
    }

    private function findValidToken(string $rawToken): ?PasswordChangeToken
    {
        $hash = hash('sha256', $rawToken);

        return PasswordChangeToken::query()
            ->valid()
            ->where('token_hash', $hash)
            ->first();
    }

    private function dealerLoginRouteFromUser(User $user): string
    {
        if ($user->dealer_id) {
            $dealerCode = Dealer::query()
                ->where('id', $user->dealer_id)
                ->value('code');

            if (is_string($dealerCode) && $dealerCode !== '') {
                return route('dealer.login.show', ['code' => $dealerCode]);
            }
        }

        return route('login');
    }
}
