<?php

declare(strict_types=1);

namespace App\Services;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

final class FollowAnalyticsService
{
    public function recordFollow(int $actorId, int $targetId): void
    {
        if (! Schema::hasTable('user_follow_analytics')) {
            return;
        }

        $this->increment($actorId, 'follows_made');
        $this->increment($targetId, 'followers_gained');
    }

    public function recordUnfollow(int $actorId, int $targetId): void
    {
        if (! Schema::hasTable('user_follow_analytics')) {
            return;
        }

        $this->increment($actorId, 'unfollows_made');
        $this->increment($targetId, 'followers_lost');
    }

    public function summaryForUser(int $userId, int $currentFollowersCount = 0): array
    {
        if (! Schema::hasTable('user_follow_analytics')) {
            return $this->emptySummary();
        }

        $today = now()->toDateString();
        $weekStart = now()->subDays(6)->toDateString();

        $todayRow = DB::table('user_follow_analytics')
            ->where('user_id', $userId)
            ->whereDate('date', $today)
            ->first();

        $weekly = DB::table('user_follow_analytics')
            ->where('user_id', $userId)
            ->whereBetween('date', [$weekStart, $today])
            ->selectRaw('COALESCE(SUM(followers_gained), 0) as gained, COALESCE(SUM(followers_lost), 0) as lost')
            ->first();

        $dailyGained = (int) ($todayRow->followers_gained ?? 0);
        $dailyLost = (int) ($todayRow->followers_lost ?? 0);
        $weeklyGained = (int) ($weekly->gained ?? 0);
        $weeklyLost = (int) ($weekly->lost ?? 0);
        $weeklyNet = $weeklyGained - $weeklyLost;
        $baseline = max(1, $currentFollowersCount - $weeklyNet);

        return [
            'daily' => [
                'gained' => $dailyGained,
                'lost' => $dailyLost,
                'net' => $dailyGained - $dailyLost,
            ],
            'weekly' => [
                'gained' => $weeklyGained,
                'lost' => $weeklyLost,
                'net' => $weeklyNet,
                'growth_rate' => round(($weeklyNet / $baseline) * 100, 1),
            ],
        ];
    }

    private function increment(int $userId, string $column): void
    {
        DB::table('user_follow_analytics')->updateOrInsert(
            [
                'user_id' => $userId,
                'date' => now()->toDateString(),
            ],
            [
                $column => DB::raw("COALESCE({$column}, 0) + 1"),
                'updated_at' => now(),
                'created_at' => now(),
            ]
        );
    }

    private function emptySummary(): array
    {
        return [
            'daily' => ['gained' => 0, 'lost' => 0, 'net' => 0],
            'weekly' => ['gained' => 0, 'lost' => 0, 'net' => 0, 'growth_rate' => 0.0],
        ];
    }
}
