<?php

namespace App\Http\Middleware;

use Illuminate\Http\Request;
use Inertia\Middleware;

class HandleInertiaRequests extends Middleware
{
    /**
     * The root template that's loaded on the first page visit.
     *
     * @see https://inertiajs.com/server-side-setup#root-template
     *
     * @var string
     */
    protected $rootView = 'app';

    /**
     * Determines the current asset version.
     *
     * @see https://inertiajs.com/asset-versioning
     */
    public function version(Request $request): ?string
    {
        return parent::version($request);
    }

    /**
     * Define the props that are shared by default.
     *
     * @see https://inertiajs.com/shared-data
     *
     * @return array<string, mixed>
     */
    public function share(Request $request): array
    {
        return array_merge(parent::share($request), [
            'auth' => [
                'user' => function () use ($request) {
                    $user = $request->user();
                    if (! $user) {
                        return null;
                    }

                    return [
                        'id' => $user->id,
                        'name' => $user->name,
                        'email' => $user->email,
                        'roles' => $user->roles()->select('id', 'name', 'slug')->get(),
                        'permissions' => $user->permissions()->pluck('slug')->values(),
                    ];
                },
            ],
            'flash' => [
                'success' => fn () => $request->session()->get('success'),
                'error' => fn () => $request->session()->get('error'),
                'warning' => fn () => $request->session()->get('warning'),
                'info' => fn () => $request->session()->get('info'),
                'method' => fn () => $request->session()->get('flash_method'), // HTTP method for toast styling
            ],
            'callLaterCount' => function () use ($request) {
                if (! $request->user()) {
                    return 0;
                }

                return \App\Models\CallLater::query()
                    ->whereNull('completed_at')
                    ->count();
            },
            'notifications' => function () use ($request) {
                try {
                    $user = $request->user();
                    if (! $user) {
                        return null;
                    }

                    $today = now()->toDateString();

                    // Base fetch to avoid serialization issues; eager load relations afterwards
                    $activities = \App\Models\Activity::query()
                        ->select(['id', 'due_date', 'amount', 'contract_id', 'client_case_id', 'created_at'])
                        ->whereDate('due_date', $today)
                        // Exclude activities that have been marked as read by this user
                        ->whereNotExists(function ($q) use ($user, $today) {
                            $q->select(\DB::raw(1))
                                ->from('activity_notification_reads')
                                ->whereColumn('activity_notification_reads.activity_id', 'activities.id')
                                ->where('activity_notification_reads.user_id', $user->id)
                                ->whereDate('activity_notification_reads.due_date', '<=', $today)
                                ->whereNotNull('activity_notification_reads.read_at');
                        })
                        ->orderBy('created_at')
                        ->limit(20)
                        ->get();

                    // Eager load needed relations (contracts and client cases) with qualified selects
                    $activities->load([
                        'contract' => function ($q) {
                            $q->select(['contracts.id', 'contracts.uuid', 'contracts.reference', 'contracts.client_case_id'])
                                ->with([
                                    // Include client (via case) so the UI can render client.person.full_name
                                    'clientCase' => function ($qq) {
                                        // Include person_id to ensure nested person loads correctly and to avoid null clientCase due to narrow selects
                                        $qq->select(['client_cases.id', 'client_cases.uuid', 'client_cases.client_id', 'client_cases.person_id'])
                                            ->with([
                                                'client' => function ($qqq) {
                                                    $qqq->select(['clients.id', 'clients.person_id'])
                                                        ->with([
                                                            'person' => function ($qqqq) {
                                                                $qqqq->select(['person.id', 'person.full_name']);
                                                            },
                                                        ]);
                                                },
                                            ]);
                                    },
                                    'account' => function ($qq) {
                                        $qq->select(['accounts.id', 'accounts.contract_id', 'accounts.balance_amount', 'accounts.initial_amount']);
                                    },
                                ]);
                        },
                        'clientCase' => function ($q) {
                            $q->select(['client_cases.id', 'client_cases.uuid', 'client_cases.person_id', 'client_cases.client_id'])
                                ->with([
                                    'person' => function ($qq) {
                                        $qq->select(['person.id', 'person.full_name']);
                                    },
                                    'client' => function ($qq) {
                                        $qq->select(['clients.id', 'clients.person_id'])
                                            ->with([
                                                'person' => function ($qqq) {
                                                    $qqq->select(['person.id', 'person.full_name']);
                                                },
                                            ]);
                                    },
                                ]);
                        },
                    ]);

                    // For convenience on the frontend, mirror client onto the contract so it can be accessed as contract.client.person
                    // 1) Build a map of contract_id -> client_id using a lightweight join
                    $contractIds = $activities->pluck('contract_id')->filter()->unique()->values();
                    if ($contractIds->isNotEmpty()) {
                        $mapContractToClient = \App\Models\Contract::query()
                            ->whereIn('contracts.id', $contractIds)
                            ->join('client_cases', 'client_cases.id', '=', 'contracts.client_case_id')
                            ->pluck('client_cases.client_id', 'contracts.id');

                        // 2) Load all needed clients with their person
                        $clientIds = $mapContractToClient->filter()->unique()->values();
                        $clientsById = $clientIds->isNotEmpty()
                            ? \App\Models\Client::query()
                                ->whereIn('clients.id', $clientIds)
                                ->with(['person:id,full_name'])
                                ->get(['clients.id', 'clients.uuid', 'clients.person_id'])
                                ->keyBy('id')
                            : collect();

                        // 3) Attach client relation on each contract instance
                        foreach ($activities as $act) {
                            $contract = $act->getRelation('contract');
                            if (! $contract) {
                                continue;
                            }
                            $cid = $mapContractToClient->get($contract->id);
                            if ($cid && $clientsById->has($cid)) {
                                $contract->setRelation('client', $clientsById->get($cid));
                            }
                        }
                    }

                    return [
                        'dueToday' => [
                            'count' => $activities->count(),
                            'items' => $activities,
                            'date' => $today,
                        ],
                    ];
                } catch (\Throwable $e) {
                    return null;
                }
            },
        ]);
    }
}
