<?php

namespace App\Components\Report;

use App\Models\Claim\Claim;
use App\Models\Claim\Status;
use App\Models\Client\Client;
use App\Models\Client\ClientHandler;
use Livewire\Component;

/**
 * Management ("Stat") Report for the HA workspace.
 *
 * Columns map to the stakeholder spec. Status-driven columns resolve their
 * status IDs from the live `statuses` table (type = 'ha') by display_name at
 * render time — the HA status list is data-driven and not seeded, so we avoid
 * hard-coding IDs that differ between environments.
 *
 * Not yet implemented (pending data model / business rules — deferred by request):
 *   - Cases Owed in total (needs a weekly counter/target mechanism)
 *   - Total Amount of Awards received (needs a numeric award amount field)
 *   - Aiker Fee's received to date (needs an Aiker fee field)
 */
class ManagementReport extends Component
{
    /**
     * Lead source name (partial match) used for the "signed up this week" figure.
     */
    private const LEAD_SOURCE_YL4U = 'YL4U';

    public function render()
    {
        $statuses = Status::forType('ha')->get(['id', 'display_name']);

        // Resolve a set of status IDs by exact display_name match.
        $exact = fn (array $names) => $statuses
            ->whereIn('display_name', $names)
            ->pluck('id')
            ->all();

        // Resolve status IDs by display_name prefix (handles the long
        // "Cancelled within/after 14 Day Cooling Off ..." names).
        $prefix = fn (string $needle) => $statuses
            ->filter(fn ($s) => str_starts_with($s->display_name, $needle))
            ->pluck('id')
            ->all();

        // --- Status groups (per spec) ------------------------------------
        $submittedIds = $exact([
            'Final Submission',
            'Panel Hearing',
            'Final Outcome',
            'Client Accepts Offer & Signs Waiver',
            'Submit Invoice & Request Payment from Client',
            'Closed Case - Payment Received',
        ]);

        $awardIds = $exact([
            'Final Outcome',
            'Client Accepts Offer & Signs Waiver',
            'Submit Invoice & Request Payment from Client',
            'Closed Case - Payment Received',
        ]);

        $panelIds     = $exact(['Panel Hearing']);
        $tobIds       = $exact(['Waiting on Terms of Business']);
        $dsarIds      = $exact(['Investigation - DSAR Activity']);
        $closedPaid   = $exact(['Closed Case - Payment Received']);
        $replacedIds  = $exact(['Case Replaced']);

        // The two 14-day cooling-off cancellations = "unable to progress".
        $cancelledIds = array_merge(
            $prefix('Closed Case - Cancelled within 14 Day'),
            $prefix('Closed Case - Cancelled after 14 Day'),
        );

        // --- Column figures ----------------------------------------------
        $stats = [
            // A: everything except the two 14-day cancellations
            'active'        => Claim::when($cancelledIds, fn ($q) => $q->whereNotIn('status_id', $cancelledIds))->count(),
            // B: new clients this week via YL4U lead source
            'signed_up'     => $this->signedUpThisWeek(),
            // D
            'dsar'          => Claim::whereIn('status_id', $dsarIds)->count(),
            // E
            'awaiting_tob'  => Claim::whereIn('status_id', $tobIds)->count(),
            // F
            'submitted'     => Claim::whereIn('status_id', $submittedIds)->count(),
            // H
            'awaiting_panel' => Claim::whereIn('status_id', $panelIds)->count(),
            // I
            'awards'        => Claim::whereIn('status_id', $awardIds)->count(),
            // L
            'closed'        => Claim::whereIn('status_id', $closedPaid)->count(),
            // M
            'unable'        => Claim::whereIn('status_id', $cancelledIds)->count(),
            // N
            'replacements'  => Claim::whereIn('status_id', $replacedIds)->count(),
        ];

        return view('components.report.management-report', [
            'stats'    => $stats,
            'handlers' => $this->submissionRateByHandler($submittedIds, $cancelledIds),
        ]);
    }

    /**
     * B — clients created this week (Mon–now) whose lead source is YL4U.
     */
    private function signedUpThisWeek(): int
    {
        return Client::whereBetween('created_at', [now()->startOfWeek(), now()])
            ->whereHas('leadSource', fn ($q) => $q->where('display_name', 'like', '%' . self::LEAD_SOURCE_YL4U . '%'))
            ->count();
    }

    /**
     * G — Case Handler Submission Rate.
     *
     * For each handler (a user with client_handlers assignments): how many of
     * their claims have reached a "submitted" status vs their total live
     * caseload (excluding 14-day cancellations), expressed as a percentage.
     */
    private function submissionRateByHandler(array $submittedIds, array $cancelledIds)
    {
        return ClientHandler::with('user')
            ->get()
            ->groupBy('user_id')
            ->map(function ($rows) use ($submittedIds, $cancelledIds) {
                $clientIds = $rows->pluck('client_id')->unique();
                $user      = $rows->first()->user;

                $total = Claim::whereIn('client_id', $clientIds)
                    ->when($cancelledIds, fn ($q) => $q->whereNotIn('status_id', $cancelledIds))
                    ->count();

                $submitted = Claim::whereIn('client_id', $clientIds)
                    ->whereIn('status_id', $submittedIds)
                    ->count();

                return [
                    'handler'   => $user ? trim($user->name_first . ' ' . $user->name_last) : 'Unassigned',
                    'submitted' => $submitted,
                    'total'     => $total,
                    'rate'      => $total > 0 ? round($submitted / $total * 100) : 0,
                ];
            })
            ->sortByDesc('rate')
            ->values();
    }
}
