<?php

declare(strict_types=1);

namespace App\Http\Controllers\Api\Pwa;

use App\Http\Controllers\Api\Pwa\Traits\RoleAwareQueries;
use App\Http\Controllers\Controller;
use App\Models\CollectionVisit;
use App\Models\Credit;
use App\Models\Installment;
use App\Models\Payment;
use App\Models\User;
use App\Services\CollectorVisibilityResolver;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class TeamController extends Controller
{
    use RoleAwareQueries;

    public function __construct(
        private readonly CollectorVisibilityResolver $resolver
    ) {}

    /**
     * GET /api/pwa/team
     *
     * Lista de cobradores visibles para el usuario con métricas del día.
     *
     * Visibilidad según CollectorVisibilityResolver:
     *   admin                        → todos los collectors de la empresa
     *   supervisor (sees_all=true)   → todos los collectors de la empresa
     *   supervisor (asignados)       → solo sus collectors asignados
     *   supervisor (sin asignación)  → respuesta vacía con unassigned: true
     */
    public function index(Request $request): JsonResponse
    {
        if (! $this->canViewAllCredits($request)) {
            return response()->json(['message' => 'No autorizado.'], 403);
        }

        $user = $request->user();
        $today = Carbon::today()->toDateString();
        $companyId = $user->company_id;

        $baseQuery = User::role('collector')
            ->where('users.company_id', $companyId)
            ->select(['users.id', 'users.name', 'users.email', 'users.phone'])
            ->addSelect([

                // ── COBRADO HOY ─────────────────────────────────────────────
                // Se atribuye al cobrador ASIGNADO al crédito (credits.collector_user_id),
                // no a quien registró el pago, y solo sobre créditos hoja en estado
                // activo — misma definición que CollectionMetricsService::
                // getCollectorPerformanceToday(), que alimenta el panel Filament.
                // (Antes se agrupaba por registered_by_user_id sin filtro de estado/hoja,
                // divergiendo del back office cuando un supervisor/admin registraba el pago.)
                'today_collected_amount' => Payment::selectRaw('COALESCE(SUM(payments.amount), 0)')
                    ->join('credits as pc', 'pc.id', '=', 'payments.credit_id')
                    ->whereColumn('pc.collector_user_id', 'users.id')
                    ->where('payments.company_id', $companyId)
                    ->where('payments.voided', false)
                    ->where('payments.payment_method', '!=', 'reversal')
                    ->where('payments.payment_date', $today)
                    ->whereIn('pc.status', Credit::ACTIVE_STATUSES)
                    ->whereNotExists(
                        fn ($q) => $q->select(DB::raw(1))
                            ->from('credits as pch')
                            ->whereColumn('pch.parent_credit_id', 'pc.id')
                    ),

                'today_collected_count' => Payment::selectRaw('COUNT(*)')
                    ->join('credits as pc2', 'pc2.id', '=', 'payments.credit_id')
                    ->whereColumn('pc2.collector_user_id', 'users.id')
                    ->where('payments.company_id', $companyId)
                    ->where('payments.voided', false)
                    ->where('payments.payment_method', '!=', 'reversal')
                    ->where('payments.payment_date', $today)
                    ->whereIn('pc2.status', Credit::ACTIVE_STATUSES)
                    ->whereNotExists(
                        fn ($q) => $q->select(DB::raw(1))
                            ->from('credits as pch2')
                            ->whereColumn('pch2.parent_credit_id', 'pc2.id')
                    ),

                // ── VISITAS HOY ─────────────────────────────────────────────
                'today_visits_count' => CollectionVisit::selectRaw('COUNT(*)')
                    ->whereColumn('collector_user_id', 'users.id')
                    ->where('company_id', $companyId)
                    ->where('visit_date', $today),

                // ── CRÉDITOS ACTIVOS EN RUTA (solo leaf) ────────────────────
                'active_credits_count' => Credit::selectRaw('COUNT(*)')
                    ->whereColumn('collector_user_id', 'users.id')
                    ->where('company_id', $companyId)
                    ->whereIn('status', ['active', 'delayed', 'overdue'])
                    ->whereNotExists(
                        fn ($q) => $q->select(DB::raw(1))
                            ->from('credits as children')
                            ->whereColumn('children.parent_credit_id', 'credits.id')
                    ),

                // ── CUOTAS PENDIENTES HOY (solo leaf) ───────────────────────
                'pending_today_count' => Installment::selectRaw('COUNT(*)')
                    ->join('credits as ci', 'ci.id', '=', 'installments.credit_id')
                    ->where('ci.company_id', $companyId)
                    ->whereColumn('ci.collector_user_id', 'users.id')
                    ->whereIn('ci.status', ['active', 'delayed', 'overdue'])
                    ->whereNotExists(
                        fn ($q) => $q->select(DB::raw(1))
                            ->from('credits as ch')
                            ->whereColumn('ch.parent_credit_id', 'ci.id')
                    )
                    ->where('installments.due_date', $today)
                    ->whereIn('installments.status', ['pending', 'partial_paid', 'overdue']),

            ]);

        // Aplicar filtro de visibilidad según rol y asignaciones.
        $filteredQuery = $this->resolver->applyToQuery($baseQuery, $user);

        // El supervisor no tiene collectors asignados → respuesta vacía con señal para la UI.
        if ($filteredQuery === null) {
            return response()->json([
                'data' => [],
                'meta' => [
                    'total' => 0,
                    'date' => $today,
                    'unassigned' => true,
                ],
            ]);
        }

        $collectors = $filteredQuery->orderBy('users.name')->get();

        return response()->json([
            'data' => $collectors->map(fn (User $c) => [
                'id' => $c->id,
                'name' => $c->name,
                'email' => $c->email,
                'phone' => $c->phone,
                'today' => [
                    'collected_amount' => (float) ($c->today_collected_amount ?? 0),
                    'collected_count' => (int) ($c->today_collected_count ?? 0),
                    'visits_count' => (int) ($c->today_visits_count ?? 0),
                    'pending_count' => (int) ($c->pending_today_count ?? 0),
                ],
                'route' => [
                    'active_credits' => (int) ($c->active_credits_count ?? 0),
                ],
            ]),
            'meta' => [
                'total' => $collectors->count(),
                'date' => $today,
                'unassigned' => false,
            ],
        ]);
    }
}
