<?php
namespace App\Controllers;

use App\Core\{Auth, Csrf, Database, Response};
use App\Models\Comment;
use App\Services\Security\ZaloroxShield;
use Throwable;

class CommentController extends BaseController
{
    public function create(): Response
    {
        if (!Auth::check()) {
            return Response::json(['ok' => false, 'message' => 'Yorum yazmak icin giris yapmalisin.'], 403);
        }

        if (!Csrf::verify($this->input('_csrf'))) {
            return Response::json(['ok' => false, 'message' => 'Guvenlik oturumu yenilenmeli. Sayfayi yenileyip tekrar dene.'], 419);
        }

        $contentType = strtolower((string) $this->input('content_type', 'mod'));
        $contentId = (int) $this->input('content_id', 0);
        $parentId = (int) $this->input('parent_id', 0);
        $content = trim(strip_tags((string) $this->input('content', '')));

        if (!in_array($contentType, ['mod', 'music', 'community', 'community_post'], true) || $contentId <= 0) {
            return Response::json(['ok' => false, 'message' => 'Yorum hedefi gecersiz.'], 422);
        }

        if ($content === '' || strlen($content) < 2) {
            return Response::json(['ok' => false, 'message' => 'Yorum biraz daha uzun olmali.'], 422);
        }

        if (strlen($content) > 3000) {
            return Response::json(['ok' => false, 'message' => 'Yorum 3000 karakterden kisa olmali.'], 422);
        }

        try {
            $model = new Comment();
            if ($model->tooManyRecent((int) Auth::id())) {
                return Response::json(['ok' => false, 'message' => 'Cok hizli yorum gonderiyorsun. Biraz bekle.'], 429);
            }

            $scan = (new ZaloroxShield($this->config))->scanComment($content, Auth::id());
            $status = match ((string) ($scan['action_taken'] ?? 'allow')) {
                'blocked' => 'blocked',
                'pending_review' => 'pending_review',
                default => 'published',
            };

            if (($scan['status'] ?? '') === 'blocked') {
                $status = 'blocked';
            } elseif (($scan['status'] ?? '') === 'review' && $status !== 'blocked') {
                $status = 'pending_review';
            }

            $comment = $model->createForContent(
                $contentType,
                $contentId,
                (int) Auth::id(),
                $content,
                $status,
                (int) ($scan['risk_score'] ?? 0),
                $parentId > 0 ? $parentId : null
            );

            if ($status === 'blocked') {
                return Response::json([
                    'ok' => false,
                    'status' => 'blocked',
                    'message' => 'Zalorox Shield bu yorumu engelledi.',
                    'risk_score' => (int) ($scan['risk_score'] ?? 0),
                ], 422);
            }

            if ($status === 'pending_review') {
                return Response::json([
                    'ok' => true,
                    'status' => 'pending_review',
                    'message' => 'Yorum incelemeye alindi.',
                    'comment' => $comment,
                ]);
            }

            return Response::json([
                'ok' => true,
                'status' => 'published',
                'message' => 'Yorum yayinlandi.',
                'comment' => $comment,
            ]);
        } catch (Throwable $exception) {
            $this->logException($exception, 'comments.create');

            return Response::json(['ok' => false, 'message' => 'Yorum su anda kaydedilemedi.'], 500);
        }
    }

    public function reply(): Response
    {
        $_POST['parent_id'] = $_POST['parent_id'] ?? $this->input('parent_id', 0);

        return $this->create();
    }

    public function listComments(): Response
    {
        $contentType = strtolower((string) ($_GET['content_type'] ?? 'mod'));
        $contentId = (int) ($_GET['content_id'] ?? 0);

        if (!in_array($contentType, ['mod', 'music', 'community', 'community_post'], true) || $contentId <= 0) {
            return Response::json(['ok' => false, 'comments' => [], 'message' => 'Yorum hedefi gecersiz.'], 422);
        }

        try {
            $comments = (new Comment())->listForContent($contentType, $contentId, 60, Auth::role('admin'), Auth::id());

            return Response::json(['ok' => true, 'comments' => $comments]);
        } catch (Throwable $exception) {
            $this->logException($exception, 'comments.list');

            return Response::json(['ok' => true, 'comments' => []]);
        }
    }

    public function update(): Response
    {
        if (!Auth::check()) {
            return Response::json(['ok' => false, 'message' => 'Yorum duzenlemek icin giris yapmalisin.'], 403);
        }

        if (!Csrf::verify($this->input('_csrf'))) {
            return Response::json(['ok' => false, 'message' => 'Guvenlik oturumu yenilenmeli.'], 419);
        }

        $commentId = (int) $this->input('comment_id', $this->input('id', 0));
        $content = trim(strip_tags((string) $this->input('content', '')));

        if ($commentId <= 0 || strlen($content) < 2) {
            return Response::json(['ok' => false, 'message' => 'Yorum metni gecersiz.'], 422);
        }

        try {
            $scan = (new ZaloroxShield($this->config))->scanComment($content, Auth::id(), $commentId);
            $status = match ((string) ($scan['action_taken'] ?? 'allow')) {
                'blocked' => 'blocked',
                'pending_review' => 'pending_review',
                default => 'published',
            };
            $comment = (new Comment())->updateComment($commentId, (int) Auth::id(), $content, $status, (int) ($scan['risk_score'] ?? 0));

            if (!$comment) {
                return Response::json(['ok' => false, 'message' => 'Yorum bulunamadi veya sana ait degil.'], 404);
            }

            return Response::json([
                'ok' => $status !== 'blocked',
                'status' => $status,
                'comment' => $comment,
                'message' => $status === 'pending_review' ? 'Yorum incelemeye alindi.' : ($status === 'blocked' ? 'Zalorox Shield bu yorumu engelledi.' : 'Yorum guncellendi.'),
            ], $status === 'blocked' ? 422 : 200);
        } catch (Throwable $exception) {
            $this->logException($exception, 'comments.update');
            return Response::json(['ok' => false, 'message' => 'Yorum su anda guncellenemedi.'], 500);
        }
    }

    public function delete(): Response
    {
        if (!Auth::check()) {
            return Response::json(['ok' => false, 'message' => 'Yorum silmek icin giris yapmalisin.'], 403);
        }

        if (!Csrf::verify($this->input('_csrf'))) {
            return Response::json(['ok' => false, 'message' => 'Guvenlik oturumu yenilenmeli.'], 419);
        }

        $commentId = (int) $this->input('comment_id', $this->input('id', 0));

        try {
            $model = new Comment();
            $comment = $model->findDetailed($commentId);
            if (!$comment) {
                return Response::json(['ok' => false, 'message' => 'Yorum bulunamadi.'], 404);
            }

            $canDelete = (int) $comment['user_id'] === (int) Auth::id()
                || Auth::role('admin')
                || $this->currentUserOwnsContent((string) $comment['content_type'], (int) $comment['content_id']);

            if (!$canDelete) {
                return Response::json(['ok' => false, 'message' => 'Bu yorumu silme yetkin yok.'], 403);
            }

            $model->softDelete($commentId);

            return Response::json(['ok' => true, 'message' => 'Yorum silindi.']);
        } catch (Throwable $exception) {
            $this->logException($exception, 'comments.delete');
            return Response::json(['ok' => false, 'message' => 'Yorum su anda silinemedi.'], 500);
        }
    }

    public function like(): Response
    {
        if (!Auth::check()) {
            return Response::json(['ok' => false, 'message' => 'Yorum begenmek icin giris yapmalisin.'], 403);
        }

        if (!Csrf::verify($this->input('_csrf'))) {
            return Response::json(['ok' => false, 'message' => 'Guvenlik oturumu yenilenmeli.'], 419);
        }

        $commentId = (int) $this->input('comment_id', $this->input('id', 0));
        if ($commentId <= 0) {
            return Response::json(['ok' => false, 'message' => 'Yorum secimi gecersiz.'], 422);
        }

        try {
            $result = (new Comment())->toggleLike($commentId, (int) Auth::id());

            return Response::json(['ok' => true] + $result);
        } catch (Throwable $exception) {
            $this->logException($exception, 'comments.like');
            return Response::json(['ok' => false, 'message' => 'Begeni su anda kaydedilemedi.'], 500);
        }
    }

    private function currentUserOwnsContent(string $contentType, int $contentId): bool
    {
        $userId = (int) Auth::id();
        if ($userId <= 0 || $contentId <= 0) {
            return false;
        }

        try {
            $pdo = Database::connection($this->config);
            if ($contentType === 'mod') {
                $statement = $pdo->prepare('SELECT 1 FROM mods WHERE id = :id AND (user_id = :user_id_a OR creator_id = :user_id_b) LIMIT 1');
                $statement->execute(['id' => $contentId, 'user_id_a' => $userId, 'user_id_b' => $userId]);
                return (bool) $statement->fetchColumn();
            }

            if ($contentType === 'music') {
                $statement = $pdo->prepare('SELECT 1 FROM music_tracks WHERE id = :id AND user_id = :user_id LIMIT 1');
                $statement->execute(['id' => $contentId, 'user_id' => $userId]);
                return (bool) $statement->fetchColumn();
            }

            if (in_array($contentType, ['community', 'community_post'], true)) {
                $statement = $pdo->prepare('SELECT 1 FROM community_posts WHERE id = :id AND user_id = :user_id LIMIT 1');
                $statement->execute(['id' => $contentId, 'user_id' => $userId]);
                return (bool) $statement->fetchColumn();
            }
        } catch (Throwable $exception) {
            $this->logException($exception, 'comments.owner-check');
        }

        return false;
    }

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

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

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

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