<?php
declare(strict_types=1);

namespace App\Controllers;

use App\Core\{Auth, Csrf, Response};
use App\Models\{Friendship, User};
use Throwable;

class FriendController extends BaseController
{
    public function request(): Response
    {
        $userId = $this->requireUserId();
        if (!$userId) {
            return $this->jsonError('Giris yapmalisin.', 403);
        }

        if (!Csrf::verify($this->input('_csrf'))) {
            return $this->jsonError('Guvenlik oturumu yenilenmeli.', 419);
        }

        $targetId = (int) $this->input('user_id', $this->input('receiver_id', 0));
        if ($targetId <= 0) {
            return $this->jsonError('Kullanici secimi gecersiz.', 422);
        }

        try {
            $result = (new Friendship())->request($userId, $targetId);

            return Response::json($result + ['ok' => (bool) ($result['ok'] ?? false)], !empty($result['ok']) ? 200 : 422);
        } catch (Throwable $exception) {
            $this->logException($exception, 'friends.request');
            return $this->jsonError('Arkadaslik istegi su anda gonderilemedi.', 500);
        }
    }

    public function accept(): Response
    {
        return $this->changePending('accept');
    }

    public function reject(): Response
    {
        return $this->changePending('reject');
    }

    public function remove(): Response
    {
        $userId = $this->requireUserId();
        if (!$userId) {
            return $this->jsonError('Giris yapmalisin.', 403);
        }

        if (!Csrf::verify($this->input('_csrf'))) {
            return $this->jsonError('Guvenlik oturumu yenilenmeli.', 419);
        }

        $targetId = (int) $this->input('user_id', 0);
        if ($targetId <= 0) {
            return $this->jsonError('Kullanici secimi gecersiz.', 422);
        }

        try {
            (new Friendship())->remove($userId, $targetId);
            return Response::json(['ok' => true, 'state' => 'none', 'message' => 'Arkadaslik kaldirildi.']);
        } catch (Throwable $exception) {
            $this->logException($exception, 'friends.remove');
            return $this->jsonError('Arkadaslik su anda kaldirilamadi.', 500);
        }
    }

    public function block(): Response
    {
        return $this->blockToggle(true);
    }

    public function unblock(): Response
    {
        return $this->blockToggle(false);
    }

    public function search(): Response
    {
        $userId = $this->requireUserId();
        if (!$userId) {
            return $this->jsonError('Giris yapmalisin.', 403);
        }

        $query = trim((string) ($_GET['q'] ?? ''));
        if (strlen($query) < 2) {
            return Response::json(['ok' => true, 'users' => []]);
        }

        try {
            $friendship = new Friendship();
            $users = array_map(function (array $user) use ($friendship, $userId): array {
                $relation = $friendship->relationship($userId, (int) $user['id']);

                return $user + [
                    'relationship' => $relation['state'],
                    'friendship_id' => isset($relation['friendship']['id']) ? (int) $relation['friendship']['id'] : null,
                ];
            }, (new User())->searchPublic($query, $userId));

            return Response::json(['ok' => true, 'users' => $users]);
        } catch (Throwable $exception) {
            $this->logException($exception, 'friends.search');
            return $this->jsonError('Arama su anda tamamlanamadi.', 500);
        }
    }

    public function list(): Response
    {
        $userId = $this->requireUserId();
        if (!$userId) {
            return $this->jsonError('Giris yapmalisin.', 403);
        }

        try {
            return Response::json(['ok' => true, 'data' => (new Friendship())->listForUser($userId)]);
        } catch (Throwable $exception) {
            $this->logException($exception, 'friends.list');
            return $this->jsonError('Arkadas listesi su anda yuklenemedi.', 500);
        }
    }

    private function changePending(string $action): Response
    {
        $userId = $this->requireUserId();
        if (!$userId) {
            return $this->jsonError('Giris yapmalisin.', 403);
        }

        if (!Csrf::verify($this->input('_csrf'))) {
            return $this->jsonError('Guvenlik oturumu yenilenmeli.', 419);
        }

        $friendshipId = (int) $this->input('friendship_id', $this->input('id', 0));
        $otherUserId = (int) $this->input('user_id', 0);

        try {
            $model = new Friendship();
            $friendship = $action === 'accept'
                ? $model->accept($userId, $friendshipId, $otherUserId)
                : $model->reject($userId, $friendshipId, $otherUserId);

            if (!$friendship) {
                return $this->jsonError('Istek bulunamadi veya bu islem icin uygun degil.', 404);
            }

            return Response::json([
                'ok' => true,
                'state' => $action === 'accept' ? 'friends' : 'none',
                'friendship' => $friendship,
                'message' => $action === 'accept' ? 'Arkadaslik istegi kabul edildi.' : 'Arkadaslik istegi reddedildi.',
            ]);
        } catch (Throwable $exception) {
            $this->logException($exception, 'friends.' . $action);
            return $this->jsonError('Istek su anda islenemedi.', 500);
        }
    }

    private function blockToggle(bool $block): Response
    {
        $userId = $this->requireUserId();
        if (!$userId) {
            return $this->jsonError('Giris yapmalisin.', 403);
        }

        if (!Csrf::verify($this->input('_csrf'))) {
            return $this->jsonError('Guvenlik oturumu yenilenmeli.', 419);
        }

        $targetId = (int) $this->input('user_id', 0);
        if ($targetId <= 0 || $targetId === $userId) {
            return $this->jsonError('Kullanici secimi gecersiz.', 422);
        }

        try {
            $model = new Friendship();
            if ($block) {
                $model->block($userId, $targetId);
                return Response::json(['ok' => true, 'state' => 'blocked_by_me', 'message' => 'Kullanici engellendi.']);
            }

            $model->unblock($userId, $targetId);
            return Response::json(['ok' => true, 'state' => 'none', 'message' => 'Engel kaldirildi.']);
        } catch (Throwable $exception) {
            $this->logException($exception, $block ? 'friends.block' : 'friends.unblock');
            return $this->jsonError('Engel islemi su anda tamamlanamadi.', 500);
        }
    }

    private function requireUserId(): ?int
    {
        return Auth::id();
    }

    private function input(string $key, mixed $default = null): mixed
    {
        static $json = null;

        if (array_key_exists($key, $_POST)) {
            return $_POST[$key];
        }

        if ($json === null) {
            $decoded = json_decode(file_get_contents('php://input') ?: '', true);
            $json = is_array($decoded) ? $decoded : [];
        }

        return $json[$key] ?? $default;
    }

    private function jsonError(string $message, int $status): Response
    {
        return Response::json(['ok' => false, 'message' => $message], $status);
    }
}
