<?php

declare(strict_types=1);

namespace App\Http\Controllers\Api\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Symfony\Component\HttpFoundation\Response;

final class FeedPerformanceReportController extends Controller
{
    public function index(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'from' => ['nullable', 'date_format:Y-m-d'],
            'to' => ['nullable', 'date_format:Y-m-d'],
            'limit' => ['nullable', 'integer', 'min:1', 'max:1000'],
        ]);

        $from = (string) ($validated['from'] ?? now()->subDays(29)->toDateString());
        $to = (string) ($validated['to'] ?? now()->toDateString());
        $limit = (int) ($validated['limit'] ?? 100);

        if ($from > $to) {
            return response()->json([
                'message' => 'Invalid date range: from must be before or equal to to.',
            ], Response::HTTP_UNPROCESSABLE_ENTITY);
        }

        $rows = DB::table('feed_daily_metrics')
            ->selectRaw('algo_version, source')
            ->selectRaw('SUM(impressions) as impressions')
            ->selectRaw('SUM(clicks) as clicks')
            ->selectRaw('SUM(saves) as saves')
            ->selectRaw('SUM(dwell_0_5) as dwell_0_5')
            ->selectRaw('SUM(dwell_5_30) as dwell_5_30')
            ->selectRaw('SUM(dwell_30_120) as dwell_30_120')
            ->selectRaw('SUM(dwell_120_plus) as dwell_120_plus')
            ->whereBetween('metric_date', [$from, $to])
            ->groupBy('algo_version', 'source')
            ->orderBy('algo_version')
            ->orderBy('source')
            ->get();

        $byAlgoSource = $rows->map(static function ($row): array {
            $impressions = (int) ($row->impressions ?? 0);
            $clicks = (int) ($row->clicks ?? 0);
            $saves = (int) ($row->saves ?? 0);

            return [
                'algo_version' => (string) $row->algo_version,
                'source' => (string) $row->source,
                'impressions' => $impressions,
                'clicks' => $clicks,
                'saves' => $saves,
                'ctr' => round($impressions > 0 ? $clicks / $impressions : 0.0, 6),
                'save_rate' => round($clicks > 0 ? $saves / $clicks : 0.0, 6),
                'dwell_buckets' => [
                    '0_5' => (int) ($row->dwell_0_5 ?? 0),
                    '5_30' => (int) ($row->dwell_5_30 ?? 0),
                    '30_120' => (int) ($row->dwell_30_120 ?? 0),
                    '120_plus' => (int) ($row->dwell_120_plus ?? 0),
                ],
            ];
        })->values();

        $topClickedArtworks = DB::table('feed_events as e')
            ->leftJoin('artworks as a', 'a.id', '=', 'e.artwork_id')
            ->selectRaw('e.algo_version')
            ->selectRaw('e.source')
            ->selectRaw('e.artwork_id')
            ->selectRaw('a.title as artwork_title')
            ->selectRaw("SUM(CASE WHEN e.event_type = 'feed_impression' THEN 1 ELSE 0 END) AS impressions")
            ->selectRaw("SUM(CASE WHEN e.event_type = 'feed_click' THEN 1 ELSE 0 END) AS clicks")
            ->whereBetween('e.event_date', [$from, $to])
            ->groupBy('e.algo_version', 'e.source', 'e.artwork_id', 'a.title')
            ->get()
            ->map(static function ($row): array {
                $impressions = (int) ($row->impressions ?? 0);
                $clicks = (int) ($row->clicks ?? 0);

                return [
                    'algo_version' => (string) $row->algo_version,
                    'source' => (string) $row->source,
                    'artwork_id' => (int) $row->artwork_id,
                    'artwork_title' => (string) ($row->artwork_title ?? ''),
                    'impressions' => $impressions,
                    'clicks' => $clicks,
                    'ctr' => round($impressions > 0 ? $clicks / $impressions : 0.0, 6),
                ];
            })
            ->sort(static function (array $a, array $b): int {
                $clickCompare = $b['clicks'] <=> $a['clicks'];
                if ($clickCompare !== 0) {
                    return $clickCompare;
                }

                return $b['ctr'] <=> $a['ctr'];
            })
            ->take($limit)
            ->values();

        return response()->json([
            'meta' => [
                'from' => $from,
                'to' => $to,
                'generated_at' => now()->toISOString(),
                'limit' => $limit,
            ],
            'by_algo_source' => $byAlgoSource,
            'top_clicked_artworks' => $topClickedArtworks,
        ], Response::HTTP_OK);
    }
}
