<?php

namespace App\Http\Controllers\API\v1\Admin\Impersonate;

use App\Http\Controllers\Controller;
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class StartController extends Controller
{
    public function __invoke(Request $request)
    {
        $request->validate([
            'user_id' => ['required', 'integer', 'exists:users,id'],
        ]);

        $impersonator = Auth::user();
        $target = User::findOrFail((int) $request->input('user_id'));

        if (! $impersonator || ! method_exists($impersonator, 'tokenCan') || ! $impersonator->tokenCan('admin')) {
            return response()->json(['error' => 'Unauthenticated.'], 401);
        }

        if ((int) $impersonator->id === (int) $target->id) {
            return response()->json([
                'status' => 'failed',
                'message' => 'Tidak boleh impersonate akaun sendiri.',
            ], 422);
        }

        if (method_exists($impersonator, 'canImpersonate') && ! $impersonator->canImpersonate()) {
            return response()->json([
                'status' => 'failed',
                'message' => 'Akses ditolak (impersonate).',
            ], 403);
        }

        if (method_exists($target, 'canBeImpersonated') && ! $target->canBeImpersonated()) {
            return response()->json([
                'status' => 'failed',
                'message' => 'Akaun ini tidak boleh di-impersonate.',
            ], 403);
        }

        // Revoke current token to reduce risk of dual active sessions.
        try {
            if (method_exists($impersonator, 'token') && $impersonator->token()) {
                $impersonator->token()->revoke();
            }
        } catch (\Throwable $e) {
            // Best effort.
        }

        // Encode impersonator id in token name for later "leave" action.
        $tokenName = 'impersonate:' . (int) $impersonator->id;
        $accessToken = $target->createToken($tokenName, ['admin'])->accessToken;

        activity()
            ->performedOn($target)
            ->withProperties([
                'admin_id' => $impersonator->id,
                'admin_name' => $impersonator->name,
                'admin_email' => $impersonator->email,
                'impersonated_user_id' => $target->id,
                'impersonated_user_name' => $target->name,
                'impersonated_user_email' => $target->email,
                'ip' => $request->ip(),
                'user_agent' => $request->userAgent(),
            ])
            ->log("admin impersonate: {$impersonator->email} -> {$target->email}");

        return response()->json([
            'status' => 'success',
            'message' => 'Impersonate berjaya.',
            'user' => $target,
            'impersonator' => $impersonator,
            'token' => $accessToken,
        ]);
    }
}

