<?php

namespace App\Services;

use App\Facades\Notifications;
use App\Models\Claim\Claim;
use App\Models\Client\Client;
use App\Models\Document\Document;
use App\Models\Dsar\Dsar;
use App\Models\User\User;
use App\Notifications\ClientProofUploadedNotification;
use App\Notifications\InitialDocumentsSignedNotification;
use Illuminate\Notifications\Notification;

/**
 * Routes onboarding events to the staff responsible for a client (their
 * handlers): every assigned handler is notified and given a task to action.
 */
class ClientHandlerAlertService
{
    /**
     * Document type display names that count as client-supplied proof, mapped
     * to the human label used in the notification/task copy.
     */
    private const PROOF_TYPES = [
        'ID'  => 'Proof of ID',
        'POA' => 'Proof of Address',
    ];

    public function __construct(
        private readonly TaskService $tasks,
        private readonly HistoryService $history,
    ) {}

    /**
     * A client has e-signed their initial documents (CFA / LOA / Part 1 / etc.).
     * Fired from the e-sign webhook once per signing session.
     *
     * @param  array<int, array{document_id?: int, name?: string}>  $documents
     */
    public function initialDocumentsSigned(Client $client, array $documents): void
    {
        $names = collect($documents)->pluck('name')->filter()->values();

        $description = $names->isNotEmpty()
            ? $client->full_name . ' e-signed: ' . $names->join(', ') . '. Please review.'
            : $client->full_name . ' e-signed their initial documents. Please review.';

        $this->alertHandlers(
            $client,
            new InitialDocumentsSignedNotification($client, $documents),
            'Review e-signed initial documents',
            $description,
        );
    }

    /**
     * A client has uploaded a Proof of ID / Proof of Address document. Intended
     * to be called from the client self-upload flow once it is live; no-ops for
     * any other document type or when no client can be resolved.
     */
    public function proofUploaded(Document $document): void
    {
        $client = $this->resolveClient($document);

        if (! $client) {
            return;
        }

        $label = self::PROOF_TYPES[$document->type?->display_name] ?? null;

        if (! $label) {
            return;
        }

        $this->alertHandlers(
            $client,
            new ClientProofUploadedNotification($client, $document, $label),
            'Verify ' . $label,
            $client->full_name . ' uploaded their ' . $label . '. Please verify.',
        );
    }

    /**
     * Notify every handler assigned to the client and raise a task for each.
     */
    private function alertHandlers(Client $client, Notification $notification, string $taskTitle, string $taskDescription): void
    {
        $userIds = $client->handlers()->pluck('user_id')->filter()->unique();

        if ($userIds->isEmpty()) {
            return;
        }

        $users = User::whereIn('id', $userIds)->get();

        if ($users->isEmpty()) {
            return;
        }

        Notifications::sendToMany($users, $notification);

        // System-raised tasks: no acting user, and the solicitor is passed
        // explicitly because the e-sign webhook is unauthenticated (BelongsToSolicitor
        // only stamps solicitor_id from a bound tenant in HTTP context).
        foreach ($users as $user) {
            $this->tasks->addSystemTask(
                $this->history,
                $client,
                $user,
                $taskTitle,
                now()->addHours(48),
                $taskDescription,
                $client->solicitor_id,
            );
        }
    }

    private function resolveClient(Document $document): ?Client
    {
        $owner = $document->owner;

        return match (true) {
            $owner instanceof Client => $owner,
            $owner instanceof Claim  => $owner->client,
            $owner instanceof Dsar   => $owner->claim?->client,
            default                  => null,
        };
    }
}
