<?php

namespace App\Services;

use App\Models\PortalUser;
use App\Notifications\PortalUserInvitationNotification;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\Notification;
use Illuminate\Validation\ValidationException;

class PortalUserService
{
    /**
     * Send invitation email to portal user.
     *
     * @param PortalUser $portalUser
     * @param string|null $recipientEmail Optional custom email to send invitation to (not saved to DB)
     */
    public function sendInvitation(PortalUser $portalUser, ?string $recipientEmail = null): void
    {
        $portalUser->generateInvitationToken();

        if ($recipientEmail) {
            // Send to custom recipient email (not saved to DB)
            // Pass portal user's email and role for URL generation and greeting
            Notification::route('mail', $recipientEmail)
                ->notify(new PortalUserInvitationNotification(
                    $portalUser->invitation_token,
                    $portalUser->email,
                    $portalUser->isCompanyAdmin()
                ));
        } else {
            // Send to portal user's email (default behavior)
            $portalUser->sendInvitationNotification();
        }
    }

    /**
     * Resend invitation email to portal user.
     */
    public function resendInvitation(PortalUser $portalUser): void
    {
        if ($portalUser->hasSetPassword()) {
            throw ValidationException::withMessages([
                'user' => ['Password has already been set for this account.'],
            ]);
        }

        $this->sendInvitation($portalUser);
    }

    /**
     * Validate invitation token and return the portal user.
     */
    public function validateInvitationToken(string $token, string $email): PortalUser
    {
        $portalUser = PortalUser::where('invitation_token', $token)
            ->where('email', $email)
            ->first();

        if (! $portalUser) {
            throw ValidationException::withMessages([
                'token' => ['Invalid invitation token or email.'],
            ]);
        }

        if ($portalUser->hasSetPassword()) {
            throw ValidationException::withMessages([
                'token' => ['Password has already been set for this account.'],
            ]);
        }

        if ($portalUser->hasExpiredInvitationToken()) {
            throw ValidationException::withMessages([
                'token' => ['Invitation token has expired. Please request a new invitation.'],
            ]);
        }

        return $portalUser;
    }

    /**
     * Set password for portal user from invitation.
     */
    public function setPasswordFromInvitation(string $token, string $email, string $password): PortalUser
    {
        $portalUser = $this->validateInvitationToken($token, $email);

        $portalUser->update([
            'password' => $password,
            'password_set_at' => now(),
            'email_verified_at' => now(),
            'invitation_token' => null,
            'invitation_sent_at' => null,
        ]);

        // If this user has an associated company employee record, activate it
        if ($portalUser->employee_id && $portalUser->companyEmployee) {
            $portalUser->companyEmployee->update([
                'employment_status' => 'active',
            ]);

            // Sync the employee registration account_status to active
            \App\Models\EmployeeRegistration::where('company_employee_id', $portalUser->employee_id)
                ->update(['account_status' => 'active']);
        }

        return $portalUser;
    }
}

