<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\User;
use App\Services\FollowService;
use App\Support\AvatarUrl;
use App\Support\UsernamePolicy;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

/**
 * API endpoints for the follow system.
 *
 * POST   /api/user/{username}/follow      → follow a user
 * DELETE /api/user/{username}/follow      → unfollow a user
 * GET    /api/user/{username}/followers   → paginated followers list
 * GET    /api/user/{username}/following   → paginated following list
 */
final class FollowController extends Controller
{
    public function __construct(private readonly FollowService $followService) {}

    // ─── POST /api/user/{username}/follow ────────────────────────────────────

    public function follow(Request $request, string $username): JsonResponse
    {
        $target = $this->resolveUser($username);
        $actor  = Auth::user();

        if ($actor->id === $target->id) {
            return response()->json(['error' => 'Cannot follow yourself.'], 422);
        }

        try {
            $this->followService->follow((int) $actor->id, (int) $target->id);
        } catch (\InvalidArgumentException $e) {
            return response()->json(['error' => $e->getMessage()], 422);
        }

        return response()->json([
            'following'       => true,
            'followers_count' => $this->followService->followersCount((int) $target->id),
            'following_count' => $this->followService->followingCount((int) $actor->id),
            'context' => $this->followService->relationshipContext((int) $actor->id, (int) $target->id),
        ]);
    }

    // ─── DELETE /api/user/{username}/follow ──────────────────────────────────

    public function unfollow(Request $request, string $username): JsonResponse
    {
        $target = $this->resolveUser($username);
        $actor  = Auth::user();

        $this->followService->unfollow((int) $actor->id, (int) $target->id);

        return response()->json([
            'following'       => false,
            'followers_count' => $this->followService->followersCount((int) $target->id),
            'following_count' => $this->followService->followingCount((int) $actor->id),
            'context' => $this->followService->relationshipContext((int) $actor->id, (int) $target->id),
        ]);
    }

    // ─── GET /api/user/{username}/followers ──────────────────────────────────

    public function followers(Request $request, string $username): JsonResponse
    {
        $target  = $this->resolveUser($username);
        $perPage = min((int) $request->query('per_page', 24), 100);

        $rows = DB::table('user_followers as uf')
            ->join('users as u', 'u.id', '=', 'uf.follower_id')
            ->leftJoin('user_profiles as up', 'up.user_id', '=', 'u.id')
            ->where('uf.user_id', $target->id)
            ->whereNull('u.deleted_at')
            ->orderByDesc('uf.created_at')
            ->select([
                'u.id', 'u.username', 'u.name',
                'up.avatar_hash',
                'uf.created_at as followed_at',
            ])
            ->paginate($perPage)
            ->through(fn ($row) => [
                'id'          => $row->id,
                'username'    => $row->username,
                'display_name'=> $row->username ?? $row->name,
                'avatar_url'  => AvatarUrl::forUser((int) $row->id, $row->avatar_hash, 50),
                'profile_url' => '/@' . strtolower((string) ($row->username ?? $row->id)),
                'followed_at' => $row->followed_at,
            ]);

        return response()->json($rows);
    }

    // ─── GET /api/user/{username}/following ──────────────────────────────────

    public function following(Request $request, string $username): JsonResponse
    {
        $target  = $this->resolveUser($username);
        $perPage = min((int) $request->query('per_page', 24), 100);

        $rows = DB::table('user_followers as uf')
            ->join('users as u', 'u.id', '=', 'uf.user_id')
            ->leftJoin('user_profiles as up', 'up.user_id', '=', 'u.id')
            ->where('uf.follower_id', $target->id)
            ->whereNull('u.deleted_at')
            ->orderByDesc('uf.created_at')
            ->select([
                'u.id', 'u.username', 'u.name',
                'up.avatar_hash',
                'uf.created_at as followed_at',
            ])
            ->paginate($perPage)
            ->through(fn ($row) => [
                'id'          => $row->id,
                'username'    => $row->username,
                'display_name'=> $row->username ?? $row->name,
                'avatar_url'  => AvatarUrl::forUser((int) $row->id, $row->avatar_hash, 50),
                'profile_url' => '/@' . strtolower((string) ($row->username ?? $row->id)),
                'followed_at' => $row->followed_at,
            ]);

        return response()->json($rows);
    }

    // ─── Private helpers ─────────────────────────────────────────────────────

    private function resolveUser(string $username): User
    {
        $normalized = UsernamePolicy::normalize($username);

        return User::query()
            ->whereRaw('LOWER(username) = ?', [$normalized])
            ->firstOrFail();
    }
}
