HEX
Server: LiteSpeed
System: Linux s1049.use1.mysecurecloudhost.com 4.18.0-477.27.2.lve.el8.x86_64 #1 SMP Wed Oct 11 12:32:56 UTC 2023 x86_64
User: xedaptot (3356)
PHP: 8.3.31
Disabled: NONE
Upload Files
File: /home/xedaptot/be.naniguide.com/app/Http/Controllers/Refactor/Admin/AdminAdsDashboardController.php
<?php

namespace App\Http\Controllers\Refactor\Admin;

use App\Http\Controllers\Controller;
use App\Model\AdActivityLog;
use App\Model\AdCampaign;
use App\Model\AdMetric;
use App\Model\AdPlatform;
use App\Model\Customer;
use App\Services\Ads\AdCredentialResolver;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class AdminAdsDashboardController extends Controller
{
    public function index(Request $request)
    {
        $period = $request->input('period', '30d');
        $days = match ($period) {
            '7d' => 7,
            '30d' => 30,
            '90d' => 90,
            default => 30,
        };
        $startDate = now()->startOfDay()->subDays($days - 1);
        $prevStart = (clone $startDate)->subDays($days);
        $prevEnd = (clone $startDate)->subDay();

        // Global stats
        $stats = [
            'total_platforms' => AdPlatform::count(),
            'system_platforms' => AdPlatform::whereNull('customer_id')->count(),
            'customer_platforms' => AdPlatform::whereNotNull('customer_id')->count(),
            'total_campaigns' => AdCampaign::count(),
            'active_campaigns' => AdCampaign::where('status', AdCampaign::STATUS_ACTIVE)->count(),
            'draft_campaigns' => AdCampaign::where('status', AdCampaign::STATUS_DRAFT)->count(),
            'error_campaigns' => AdCampaign::where('status', AdCampaign::STATUS_ERROR)->count(),
        ];

        // Totals in period (cross-customer)
        $current = AdMetric::where('date', '>=', $startDate)
            ->selectRaw('COALESCE(SUM(impressions),0) as impressions, COALESCE(SUM(clicks),0) as clicks, COALESCE(SUM(spend),0) as spend, COALESCE(SUM(conversions),0) as conversions')
            ->first();

        $previous = AdMetric::whereBetween('date', [$prevStart, $prevEnd])
            ->selectRaw('COALESCE(SUM(impressions),0) as impressions, COALESCE(SUM(clicks),0) as clicks, COALESCE(SUM(spend),0) as spend, COALESCE(SUM(conversions),0) as conversions')
            ->first();

        $pctDelta = function ($a, $b) {
            if ($b == 0) {
                return $a > 0 ? 100 : 0;
            }
            return round((($a - $b) / $b) * 100, 1);
        };

        $totals = [
            'impressions' => (int) $current->impressions,
            'clicks' => (int) $current->clicks,
            'spend' => (float) $current->spend,
            'conversions' => (int) $current->conversions,
        ];
        $deltas = [
            'spend' => $pctDelta((float) $current->spend, (float) $previous->spend),
            'impressions' => $pctDelta((int) $current->impressions, (int) $previous->impressions),
            'clicks' => $pctDelta((int) $current->clicks, (int) $previous->clicks),
            'conversions' => $pctDelta((int) $current->conversions, (int) $previous->conversions),
        ];

        // Daily series for chart
        $rawDaily = AdMetric::where('date', '>=', $startDate)
            ->selectRaw('date, SUM(impressions) as impressions, SUM(clicks) as clicks, SUM(spend) as spend, SUM(conversions) as conversions')
            ->groupBy('date')
            ->orderBy('date')
            ->get()
            ->keyBy(fn ($row) => (string) $row->date->format('Y-m-d'));

        $daily = [];
        for ($i = 0; $i < $days; $i++) {
            $d = (clone $startDate)->addDays($i)->format('Y-m-d');
            $row = $rawDaily[$d] ?? null;
            $daily[] = [
                'date' => $d,
                'impressions' => (int) ($row->impressions ?? 0),
                'clicks' => (int) ($row->clicks ?? 0),
                'spend' => (float) ($row->spend ?? 0),
                'conversions' => (int) ($row->conversions ?? 0),
            ];
        }

        $sparklines = [
            'spend' => array_map(fn ($r) => $r['spend'], $daily),
            'impressions' => array_map(fn ($r) => $r['impressions'], $daily),
            'clicks' => array_map(fn ($r) => $r['clicks'], $daily),
            'conversions' => array_map(fn ($r) => $r['conversions'], $daily),
        ];

        // Per-platform provisioning status
        $provisioning = [];
        foreach (AdPlatform::PLATFORMS as $platform) {
            $provisioning[$platform] = [
                'label' => AdPlatform::PLATFORM_LABELS[$platform],
                'configured' => AdCredentialResolver::isConfigured($platform),
                'source' => AdCredentialResolver::source($platform),
                'customer_connections' => AdPlatform::whereNotNull('customer_id')
                    ->where('platform', $platform)
                    ->count(),
                'healthy' => AdPlatform::where('platform', $platform)
                    ->where('health_status', 'healthy')
                    ->whereNotNull('customer_id')
                    ->count(),
                'error' => AdPlatform::where('platform', $platform)
                    ->where('health_status', 'error')
                    ->whereNotNull('customer_id')
                    ->count(),
            ];
        }

        // Customer adoption
        $totalCustomers = Customer::count();
        $customersWithPlatform = AdPlatform::whereNotNull('customer_id')
            ->distinct('customer_id')
            ->count('customer_id');
        $adoptionPercent = $totalCustomers > 0 ? round(($customersWithPlatform / $totalCustomers) * 100, 1) : 0;

        // Top customers by spend in period — raw DB query returns stdClass rows
        $prefix = DB::getTablePrefix();
        $topCustomerStats = DB::table("{$prefix}ad_metrics")
            ->join("{$prefix}ad_campaigns", "{$prefix}ad_metrics.ad_campaign_id", '=', "{$prefix}ad_campaigns.id")
            ->where("{$prefix}ad_metrics.date", '>=', $startDate)
            ->selectRaw("{$prefix}ad_campaigns.customer_id as customer_id, SUM({$prefix}ad_metrics.spend) as spend, SUM({$prefix}ad_metrics.impressions) as impressions, SUM({$prefix}ad_metrics.conversions) as conversions, COUNT(DISTINCT {$prefix}ad_campaigns.id) as campaign_count")
            ->groupBy("{$prefix}ad_campaigns.customer_id")
            ->orderByDesc('spend')
            ->limit(5)
            ->get();

        $topCustomerModels = Customer::whereIn('id', $topCustomerStats->pluck('customer_id'))->get()->keyBy('id');
        $topCustomers = $topCustomerStats->map(function ($row) use ($topCustomerModels) {
            $customer = $topCustomerModels[$row->customer_id] ?? null;
            if (!$customer) return null;
            return [
                'model' => $customer,
                'spend' => (float) $row->spend,
                'impressions' => (int) $row->impressions,
                'conversions' => (int) $row->conversions,
                'campaign_count' => (int) $row->campaign_count,
            ];
        })->filter()->values();

        // Recent cross-customer activity
        $recentActivity = AdActivityLog::orderByDesc('created_at')
            ->limit(8)
            ->get();

        // Platform health summary
        $healthSummary = [
            'healthy' => AdPlatform::whereNotNull('customer_id')->where('health_status', 'healthy')->count(),
            'degraded' => AdPlatform::whereNotNull('customer_id')->where('health_status', 'degraded')->count(),
            'error' => AdPlatform::whereNotNull('customer_id')->where('health_status', 'error')->count(),
            'unknown' => AdPlatform::whereNotNull('customer_id')->where('health_status', 'unknown')->count(),
        ];

        // Alerts
        $alerts = [];
        foreach ($provisioning as $platform => $info) {
            if (!$info['configured']) {
                $alerts[] = [
                    'severity' => 'warning',
                    'title' => $info['label'] . ' not configured',
                    'desc' => 'Customers cannot connect this platform until you add OAuth credentials.',
                    'action_label' => 'Configure',
                    'action_url' => route('refactor.admin.ads.settings.show'),
                ];
            }
        }
        if ($healthSummary['error'] > 0) {
            $alerts[] = [
                'severity' => 'error',
                'title' => $healthSummary['error'] . ' platform connection(s) in error state',
                'desc' => 'These customers cannot publish to the affected platforms until they reconnect.',
                'action_label' => 'View platforms',
                'action_url' => route('refactor.admin.ads.platforms.index'),
            ];
        }
        if ($stats['error_campaigns'] > 0) {
            $alerts[] = [
                'severity' => 'error',
                'title' => $stats['error_campaigns'] . ' campaign(s) in error state',
                'desc' => 'Publishing failed for these campaigns. Review cross-customer activity for details.',
                'action_label' => 'Review',
                'action_url' => route('refactor.admin.ads.platforms.index'),
            ];
        }

        // Admin setup checklist — mirrors the customer onboarding rail on the
        // customer dashboard. Shows 4 platforms as 4 rows with a live stat line
        // (connected-customer count + healthy count) so admin can see the state
        // of the entire ads network at a glance.
        $adminSetup = [];
        $platformIcons = ['meta' => 'groups', 'google' => 'search', 'tiktok' => 'music_note', 'linkedin' => 'work'];
        foreach (AdPlatform::PLATFORMS as $platform) {
            $info = $provisioning[$platform];
            if (!$info['configured']) {
                $state = 'locked';
                $stat = trans('refactor/ads_admin_settings.admin_dashboard.setup_stat_not_configured');
            } elseif ($info['customer_connections'] === 0) {
                $state = 'current';
                $stat = trans('refactor/ads_admin_settings.admin_dashboard.setup_stat_configured_no_customers', [
                    'source' => $info['source'] === 'env'
                        ? trans('refactor/ads_admin_settings.dashboard_enhancements.source_env')
                        : trans('refactor/ads_admin_settings.dashboard_enhancements.source_setting'),
                ]);
            } else {
                $state = 'done';
                $stat = trans('refactor/ads_admin_settings.admin_dashboard.setup_stat_live', [
                    'customers' => $info['customer_connections'],
                    'healthy' => $info['healthy'],
                    'errors' => $info['error'],
                ]);
            }
            $adminSetup[] = [
                'key' => $platform,
                'label' => $info['label'],
                'icon' => $platformIcons[$platform] ?? 'campaign',
                'state' => $state,
                'configured' => $info['configured'],
                'stat' => $stat,
                'configure_url' => route('refactor.admin.ads.settings.show'),
                'view_url' => route('refactor.admin.ads.platforms.index'),
            ];
        }
        $adminSetupDone = count(array_filter($adminSetup, fn ($s) => $s['state'] === 'done'));
        $adminSetupTotal = count($adminSetup);
        $adminSetupPercent = $adminSetupTotal > 0 ? (int) round(($adminSetupDone / $adminSetupTotal) * 100) : 0;

        return view('refactor.pages.admin.ads.dashboard', [
            'period' => $period,
            'days' => $days,
            'stats' => $stats,
            'totals' => $totals,
            'deltas' => $deltas,
            'daily' => $daily,
            'sparklines' => $sparklines,
            'provisioning' => $provisioning,
            'adoption' => [
                'total_customers' => $totalCustomers,
                'customers_with_platform' => $customersWithPlatform,
                'percent' => $adoptionPercent,
            ],
            'topCustomers' => $topCustomers,
            'recentActivity' => $recentActivity,
            'healthSummary' => $healthSummary,
            'alerts' => $alerts,
            'adminSetup' => $adminSetup,
            'adminSetupDone' => $adminSetupDone,
            'adminSetupTotal' => $adminSetupTotal,
            'adminSetupPercent' => $adminSetupPercent,
        ]);
    }
}