<?php

namespace App\Http\Responses;

use Illuminate\Http\JsonResponse;
use Illuminate\Support\Str;
use Laravel\Fortify\Contracts\TwoFactorLoginResponse as TwoFactorLoginResponseContract;
use Laravel\Fortify\Fortify;
use Mtc\MercuryDataModels\TwoFactorRememberedDevice;

class TwoFactorLoginResponse implements TwoFactorLoginResponseContract
{
    /**
     * The number of days to remember the device.
     */
    protected const REMEMBER_DAYS = 90;

    /**
     * The cookie name for remembering the device.
     */
    public const COOKIE_NAME = 'two_factor_remember';

    /**
     * Create an HTTP response that represents the object.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function toResponse($request)
    {
        $response = $request->wantsJson()
            ? new JsonResponse('', 204)
            : redirect()->intended(Fortify::redirects('login'));

        // Set the remember device cookie if requested
        if ($request->boolean('remember')) {
            $user = auth()->user();
            if ($user) {
                $response = $this->setRememberDeviceCookie($response, $user, $request);
            }
        }

        return $response;
    }

    /**
     * Set the remember device cookie on the response.
     */
    protected function setRememberDeviceCookie($response, $user, $request)
    {
        $token = Str::random(64);
        $expiresAt = now()->addDays(self::REMEMBER_DAYS);

        // Store the token in the database
        TwoFactorRememberedDevice::create([
            'user_id' => $user->id,
            'token' => hash('sha256', $token),
            'user_agent' => $request->userAgent(),
            'ip_address' => $request->ip(),
            'expires_at' => $expiresAt,
        ]);

        // Clean up old tokens for this user (keep only last 5 devices)
        $this->cleanupOldTokens($user);

        // Set the cookie (secure only in production)
        $cookie = cookie(
            self::COOKIE_NAME,
            $user->id . '|' . $token,
            self::REMEMBER_DAYS * 24 * 60, // minutes
            '/',
            config('session.domain'),
            config('session.secure'),
            true,  // httpOnly
            false, // raw
            config('session.same_site')
        );

        return $response->withCookie($cookie);
    }

    /**
     * Clean up old remembered device tokens.
     */
    protected function cleanupOldTokens($user): void
    {
        // Delete expired tokens
        TwoFactorRememberedDevice::query()
            ->where('user_id', $user->id)
            ->where('expires_at', '<', now())
            ->delete();

        // Keep only the 5 most recent tokens
        $tokensToKeep = TwoFactorRememberedDevice::query()
            ->where('user_id', $user->id)
            ->orderBy('created_at', 'desc')
            ->take(5)
            ->pluck('id');

        TwoFactorRememberedDevice::query()
            ->where('user_id', $user->id)
            ->whereNotIn('id', $tokensToKeep)
            ->delete();
    }
}
