<?php

namespace App\Http\Controllers;

use App\Models\Account;
use App\Models\Activity;
use App\Models\Client;
use App\Models\Contract;
// assuming model name Import
use App\Models\FieldJob; // if this model exists
use App\Models\Import;
use App\Models\SmsLog;
use App\Models\SmsProfile;
use App\Services\Sms\SmsService;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Inertia\Inertia;
use Inertia\Response;

class DashboardController extends Controller
{
    public function __invoke(SmsService $sms): Response
    {
        $today = now()->startOfDay();
        $cacheMinutes = 5;

        // Active clients count - cached
        $activeClientsCount = Cache::remember('dashboard:active_clients:'.now()->format('Y-m-d'), $cacheMinutes * 60, function () {
            return Client::where('active', true)->count();
        });

        // Active contracts count - cached
        $activeContractsCount = Cache::remember('dashboard:active_contracts:'.now()->format('Y-m-d'), $cacheMinutes * 60, function () {
            return Contract::whereNull('deleted_at')->count();
        });

        // Sum of active contracts' account balance - cached
        $totalBalance = Cache::remember('dashboard:total_balance:'.now()->format('Y-m-d'), $cacheMinutes * 60, function () {
            return Account::whereHas('contract', function ($q) {
                $q->whereNull('deleted_at');
            })->sum('balance_amount') ?? 0;
        });

        // Active promises count (not expired or expires today) - cached
        $activePromisesCount = Cache::remember('dashboard:active_promises:'.now()->format('Y-m-d'), $cacheMinutes * 60, function () use ($today) {
            return Account::whereHas('contract', function ($q) {
                $q->whereNull('deleted_at');
            })
                ->whereNotNull('promise_date')
                ->whereDate('promise_date', '>=', $today)
                ->count();
        });

        // Activities (limit 10) - cached
        $activities = Cache::remember('dashboard:activities', $cacheMinutes * 60, function () {
            return Activity::query()
                ->with(['clientCase:id,uuid'])
                ->latest()
                ->limit(10)
                ->get(['id', 'note', 'created_at', 'client_case_id', 'contract_id', 'action_id', 'decision_id'])
                ->map(fn ($a) => [
                    'id' => $a->id,
                    'note' => $a->note,
                    'created_at' => $a->created_at,
                    'client_case_id' => $a->client_case_id,
                    'client_case_uuid' => $a->clientCase?->uuid,
                    'contract_id' => $a->contract_id,
                    'action_id' => $a->action_id,
                    'decision_id' => $a->decision_id,
                ]);
        });

        // 7-day trends for field jobs - cached
        $trends = Cache::remember('dashboard:field_jobs_trends:'.now()->format('Y-m-d'), $cacheMinutes * 60, function () {
            $start = now()->subDays(6)->startOfDay();
            $end = now()->endOfDay();

            $dateKeys = collect(range(0, 6))
                ->map(fn ($i) => now()->subDays(6 - $i)->format('Y-m-d'));

            $fieldJobTrendRaw = FieldJob::whereBetween(DB::raw('COALESCE(assigned_at, created_at)'), [$start, $end])
                ->selectRaw("DATE(COALESCE(assigned_at, created_at) AT TIME ZONE 'Europe/Ljubljana') as d, COUNT(*) as c")
                ->groupBy('d')
                ->pluck('c', 'd');

            // Completed field jobs last 7 days
            $fieldJobCompletedRaw = FieldJob::whereNotNull('completed_at')
                ->whereBetween('completed_at', [$start, $end])
                ->selectRaw("DATE(completed_at AT TIME ZONE 'Europe/Ljubljana') as d, COUNT(*) as c")
                ->groupBy('d')
                ->pluck('c', 'd');

            return [
                'field_jobs' => $dateKeys->map(fn ($d) => (int) ($fieldJobTrendRaw[$d] ?? 0))->values(),
                'field_jobs_completed' => $dateKeys->map(fn ($d) => (int) ($fieldJobCompletedRaw[$d] ?? 0))->values(),
                'labels' => $dateKeys,
            ];
        });

        // Field jobs assigned today - cached
        $fieldJobsAssignedToday = Cache::remember('dashboard:field_jobs_assigned_today:'.now()->format('Y-m-d'), $cacheMinutes * 60, function () use ($today) {
            return FieldJob::query()
                ->whereRaw('DATE(COALESCE(assigned_at, created_at)) = ?', [$today->toDateString()])
                ->select(['id', 'assigned_user_id', 'priority', 'assigned_at', 'created_at', 'contract_id'])
                ->with(['contract' => function ($q) {
                    $q->select('id', 'uuid', 'reference', 'client_case_id')
                        ->with(['clientCase:id,uuid,person_id', 'clientCase.person:id,full_name', 'segments:id,name']);
                }])
                ->orderByRaw('COALESCE(assigned_at, created_at) DESC')
                ->limit(15)
                ->get()
                ->map(function ($fj) {
                    $contract = $fj->contract;
                    $segmentId = null;
                    if ($contract && method_exists($contract, 'segments')) {
                        $activeSeg = $contract->segments->first();
                        if ($activeSeg && isset($activeSeg->pivot) && ($activeSeg->pivot->active ?? true)) {
                            $segmentId = $activeSeg->id;
                        }
                    }

                    if (! $contract) {
                        return null;
                    }

                    return [
                        'id' => $fj->id,
                        'priority' => $fj->priority,
                        'assigned_at' => $fj->assigned_at?->toIso8601String(),
                        'created_at' => $fj->created_at?->toIso8601String(),
                        'contract' => [
                            'uuid' => $contract->uuid,
                            'reference' => $contract->reference,
                            'client_case_uuid' => optional($contract->clientCase)->uuid,
                            'person_full_name' => optional(optional($contract->clientCase)->person)->full_name,
                            'segment_id' => $segmentId,
                        ],
                    ];
                })
                ->filter()
                ->values();
        });

        // System health for timestamp
        $recentActivity = Activity::query()->latest('created_at')->value('created_at');
        $lastActivityMinutes = null;
        if ($recentActivity) {
            $lastActivityMinutes = (int) max(0, now()->diffInMinutes($recentActivity));
        }
        $systemHealth = [
            'last_activity_minutes' => $lastActivityMinutes,
            'last_activity_iso' => $recentActivity?->toIso8601String(),
            'generated_at' => now()->toIso8601String(),
        ];

        return Inertia::render('Dashboard/Index', [
            'kpis' => [
                'active_clients' => $activeClientsCount,
                'active_contracts' => $activeContractsCount,
                'total_balance' => $totalBalance,
                'active_promises' => $activePromisesCount,
            ],
            'trends' => $trends,
        ])->with([
            'activities' => fn () => $activities,
            'systemHealth' => fn () => $systemHealth,
            'fieldJobsAssignedToday' => fn () => $fieldJobsAssignedToday,
            'smsStats' => function () use ($sms, $today, $cacheMinutes) {
                // SMS stats - cached
                return Cache::remember('dashboard:sms_stats:'.now()->format('Y-m-d'), $cacheMinutes * 60, function () use ($sms, $today) {
                    $counts = SmsLog::query()
                        ->whereDate('created_at', $today)
                        ->selectRaw('profile_id, status, COUNT(*) as c')
                        ->groupBy('profile_id', 'status')
                        ->get()
                        ->groupBy('profile_id')
                        ->map(function ($rows) {
                            $map = [
                                'queued' => 0,
                                'sent' => 0,
                                'delivered' => 0,
                                'failed' => 0,
                            ];
                            foreach ($rows as $r) {
                                $map[$r->status] = (int) $r->c;
                            }
                            $map['total'] = array_sum($map);

                            return $map;
                        });

                    $profiles = SmsProfile::query()
                        ->orderBy('name')
                        ->get(['id', 'name', 'active', 'api_username', 'encrypted_api_password']);

                    return $profiles->map(function (SmsProfile $p) use ($sms, $counts) {
                        try {
                            $balance = $sms->getCreditBalance($p);
                        } catch (\Throwable $e) {
                            $balance = '—';
                        }
                        $c = $counts->get($p->id) ?? ['queued' => 0, 'sent' => 0, 'delivered' => 0, 'failed' => 0, 'total' => 0];

                        return [
                            'id' => $p->id,
                            'name' => $p->name,
                            'active' => (bool) $p->active,
                            'balance' => $balance,
                            'today' => $c,
                        ];
                    })->values();
                });
            },
        ]);
    }
}
