<?php

namespace App\Master\Http\Controllers;

use App\Http\Controllers\Controller;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Mtc\MercuryDataModels\ApiUsage;
use Mtc\MercuryDataModels\ApiUsageSnapshot;

class ApiUsageController extends Controller
{
    /**
     * Get API usage statistics aggregated by date
     */
    public function index(Request $request): array
    {
        $days = $request->input('days', 30);
        $startDate = Carbon::now()->subDays($days)->startOfDay();

        // Aggregate at database level for performance
        // Only show records without api_user_id (non-API user requests)
        $usageData = ApiUsage::query()
            ->where('time_window', '>=', $startDate->format('Y-m-d H'))
            ->whereNull('api_user_id')
            ->selectRaw('DATE(time_window) as date, SUM(hits) as hits')
            ->groupByRaw('DATE(time_window)')
            ->orderBy('date')
            ->get()
            ->keyBy('date');

        // Fill in missing dates with zeros
        $filledData = collect();
        $currentDate = $startDate->copy();
        $endDate = Carbon::now();

        while ($currentDate <= $endDate) {
            $dateKey = $currentDate->format('Y-m-d');
            $row = $usageData->get($dateKey);
            $filledData[$dateKey] = [
                'hits' => (int) ($row->hits ?? 0),
            ];
            $currentDate->addDay();
        }

        return [
            'labels' => $filledData->keys()->toArray(),
            'datasets' => [
                [
                    'label' => 'Total Hits',
                    'backgroundColor' => 'rgba(54, 162, 235, 0.5)',
                    'borderColor' => 'rgb(54, 162, 235)',
                    'data' => $filledData->pluck('hits')->values()->toArray(),
                    'tension' => 0.3,
                ],
            ],
        ];
    }

    /**
     * Get API usage for a specific date broken down by tenant
     */
    public function byDate(Request $request, string $date): array
    {
        // Aggregate at database level for performance
        // Only show records without api_user_id (non-API user requests)
        $usageData = ApiUsage::query()
            ->where('time_window', 'like', $date . '%')
            ->whereNull('api_user_id')
            ->selectRaw('tenant_id, SUM(hits) as hits')
            ->groupBy('tenant_id')
            ->orderByDesc('hits')
            ->limit(20)
            ->get();

        return [
            'date' => $date,
            'labels' => $usageData->pluck('tenant_id')->toArray(),
            'datasets' => [
                [
                    'label' => 'Total Hits',
                    'backgroundColor' => 'rgba(54, 162, 235, 0.7)',
                    'data' => $usageData->pluck('hits')->map(fn ($v) => (int) $v)->toArray(),
                ],
            ],
        ];
    }

    /**
     * Get detailed breakdown of API usage by endpoint
     */
    public function endpoints(Request $request): array
    {
        $days = $request->input('days', 30);
        $startDate = Carbon::now()->subDays($days)->startOfDay();

        // Only show records without api_user_id (non-API user requests).
        // COALESCE serves both new rows (normalized endpoint_id) and legacy rows
        // that still carry the endpoint varchar.
        $endpoints = ApiUsage::query()
            ->leftJoin('api_usage_endpoints as e', 'e.id', '=', 'api_usage.endpoint_id')
            ->where('api_usage.time_window', '>=', $startDate->format('Y-m-d H'))
            ->whereNull('api_usage.api_user_id')
            ->selectRaw(
                'COALESCE(e.endpoint, api_usage.endpoint) as endpoint, api_usage.method,'
                . ' SUM(api_usage.hits) as total_hits, AVG(api_usage.avg) as avg_time, MAX(api_usage.max) as max_time,'
                . ' SUM(api_usage.slow_3s) as slow_3s, SUM(api_usage.slow_10s) as slow_10s'
            )
            ->groupByRaw('COALESCE(e.endpoint, api_usage.endpoint), api_usage.method')
            ->orderByDesc('total_hits')
            ->limit(50)
            ->get();

        return [
            'data' => $endpoints->map(fn ($item) => [
                'endpoint' => $item->endpoint,
                'method' => $item->method,
                'total_hits' => (int) $item->total_hits,
                'avg_time' => round($item->avg_time, 3),
                'max_time' => round($item->max_time, 3),
                'slow_3s' => (int) $item->slow_3s,
                'slow_10s' => (int) $item->slow_10s,
            ])->toArray(),
        ];
    }

    /**
     * Get endpoint breakdown for a specific tenant on a specific date
     */
    public function byTenant(Request $request, string $date, string $tenant): array
    {
        // Only show records without api_user_id (non-API user requests).
        // COALESCE serves both new rows (normalized endpoint_id) and legacy rows
        // that still carry the endpoint varchar.
        $endpoints = ApiUsage::query()
            ->leftJoin('api_usage_endpoints as e', 'e.id', '=', 'api_usage.endpoint_id')
            ->where('api_usage.time_window', 'like', $date . '%')
            ->where('api_usage.tenant_id', $tenant)
            ->whereNull('api_usage.api_user_id')
            ->selectRaw(
                'COALESCE(e.endpoint, api_usage.endpoint) as endpoint, api_usage.method,'
                . ' SUM(api_usage.hits) as total_hits, AVG(api_usage.avg) as avg_time, MAX(api_usage.max) as max_time,'
                . ' SUM(api_usage.slow_3s) as slow_3s, SUM(api_usage.slow_10s) as slow_10s'
            )
            ->groupByRaw('COALESCE(e.endpoint, api_usage.endpoint), api_usage.method')
            ->orderByDesc('total_hits')
            ->limit(50)
            ->get();

        return [
            'date' => $date,
            'tenant' => $tenant,
            'data' => $endpoints->map(fn ($item) => [
                'endpoint' => $item->endpoint,
                'method' => $item->method,
                'total_hits' => (int) $item->total_hits,
                'avg_time' => round($item->avg_time, 3),
                'max_time' => round($item->max_time, 3),
                'slow_3s' => (int) $item->slow_3s,
                'slow_10s' => (int) $item->slow_10s,
            ])->toArray(),
        ];
    }

    /**
     * Get snapshots for a specific endpoint on a specific date for a specific tenant
     */
    public function snapshots(Request $request, string $date, string $tenant, string $method): array
    {
        $endpoint = $request->input('endpoint');

        // Find matching api_usage records. COALESCE matches both new rows (via the
        // normalized endpoint_id) and legacy rows that still carry the varchar.
        $usageIds = ApiUsage::query()
            ->leftJoin('api_usage_endpoints as e', 'e.id', '=', 'api_usage.endpoint_id')
            ->where('api_usage.time_window', 'like', $date . '%')
            ->where('api_usage.tenant_id', $tenant)
            ->where('api_usage.method', $method)
            ->whereRaw('COALESCE(e.endpoint, api_usage.endpoint) = ?', [$endpoint])
            ->whereNull('api_usage.api_user_id')
            ->pluck('api_usage.id');

        $snapshots = ApiUsageSnapshot::query()
            ->whereIn('api_usage_id', $usageIds)
            ->orderByDesc('request_time')
            ->get();

        return [
            'date' => $date,
            'tenant' => $tenant,
            'method' => $method,
            'endpoint' => $endpoint,
            'data' => $snapshots->map(fn ($item) => [
                'id' => $item->id,
                'request_time' => round($item->request_time, 3),
                'created_at' => $item->created_at->format('Y-m-d H:i:s'),
            ])->toArray(),
        ];
    }

    /**
     * Get a single snapshot's input data
     */
    public function snapshotInput(Request $request, int $id): array
    {
        $snapshot = ApiUsageSnapshot::query()->findOrFail($id);

        return [
            'id' => $snapshot->id,
            'input' => $snapshot->input,
            'request_time' => round($snapshot->request_time, 3),
            'created_at' => $snapshot->created_at->format('Y-m-d H:i:s'),
        ];
    }
}
