<?php

namespace App\Http\Controllers\Api\Parents;

use App\Http\Controllers\Controller;
use App\Services\Parents\AuthorizedUsersManagementService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Validator;

/**
 * Public invite confirmation & password setup for authorized users.
 */
class AuthorizedUserInviteController extends Controller
{
    public function __construct(
        private AuthorizedUsersManagementService $svc,
    ) {}

    public function confirm(Request $request): RedirectResponse|JsonResponse
    {
        $token = (string) ($request->query('token') ?? '');
        try {
            $result = $this->svc->confirmEmailClick($token);
        } catch (\InvalidArgumentException $e) {
            if ($request->expectsJson()) {
                return response()->json(['message' => $e->getMessage()], 400);
            }

            return response(
                '<!DOCTYPE html><html><head><meta charset="utf-8"></head><body style="font-family:sans-serif;padding:24px;">'
                .'<p>'.e($e->getMessage()).'</p></body></html>',
                400,
                ['Content-Type' => 'text/html; charset=UTF-8'],
            );
        }

        $redirectUrl = (string) $result['redirect_url'];
        if (! $this->isTrustedRedirectUrl($redirectUrl)) {
            return response()->json(['message' => 'Invalid redirect URL.'], 400);
        }

        if ($request->expectsJson()) {
            return response()->json([
                'message' => 'Confirmed.',
                'redirect_url' => $redirectUrl,
            ]);
        }

        return redirect()->away($redirectUrl);
    }

    public function setPasswordForm(Request $request, int $authorizedUserId): JsonResponse|Response
    {
        $token = (string) ($request->query('token') ?? '');
        $row = $this->svc->findActiveSetupRow($authorizedUserId, $token);
        if (! $row) {
            if ($request->expectsJson()) {
                return response()->json(['message' => 'Invalid or expired confirmation link.'], 400);
            }

            return response('Invalid or expired confirmation link.', 400);
        }

        if ($request->expectsJson()) {
            return response()->json([
                'message' => 'OK',
                'user_id' => $authorizedUserId,
                'token' => $token,
            ]);
        }

        return response(
            '<!DOCTYPE html><html><head><meta charset="utf-8"><title>Set password</title></head>'
            .'<body><p>Set your password using the client app or API POST to this URL with JSON body.</p></body></html>',
            200,
            ['Content-Type' => 'text/html; charset=UTF-8'],
        );
    }

    public function savePassword(Request $request, int $authorizedUserId): JsonResponse
    {
        $validator = Validator::make($request->all(), [
            'password' => ['required', 'string', 'min:8', 'regex:/[A-Z]/', 'regex:/[a-z]/', 'regex:/[0-9]/', 'regex:/[\W_]/'],
            'password_confirmation' => ['required_without:password_confirm', 'same:password'],
            'password_confirm' => ['required_without:password_confirmation', 'same:password'],
            'user_id' => ['required', 'integer'],
            'token' => ['required', 'string'],
        ], [
            'password.regex' => 'Password must include uppercase, lowercase, number, and special character.',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'message' => 'Validation failed.',
                'errors' => $validator->errors(),
            ], 422);
        }

        $data = $validator->validated();

        try {
            $this->svc->setAuthorizedUserPassword(
                $authorizedUserId,
                (int) $data['user_id'],
                (string) $data['token'],
                (string) $data['password'],
            );
        } catch (\InvalidArgumentException $e) {
            return response()->json(['message' => $e->getMessage()], 400);
        }

        return response()->json(['message' => 'Password has been successfully set.']);
    }

    private function isTrustedRedirectUrl(string $url): bool
    {
        $host = parse_url($url, PHP_URL_HOST);
        if (! is_string($host) || $host === '') {
            return false;
        }

        $trusted = [
            parse_url((string) config('app.url'), PHP_URL_HOST),
            parse_url((string) config('app.frontend_url'), PHP_URL_HOST),
            parse_url((string) config('services.frontend.url'), PHP_URL_HOST),
        ];

        return in_array(strtolower($host), array_filter(array_map(
            static fn ($value) => is_string($value) ? strtolower($value) : null,
            $trusted
        )), true);
    }
}
