<?php
declare(strict_types=1);

namespace App\Controllers;

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

class StoryController extends BaseController
{
    private ?array $jsonPayload = null;

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

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

        $payload = $this->payload();
        $type = strtolower((string) ($payload['story_type'] ?? 'text'));
        $type = $type === 'image' ? 'image' : 'text';
        $content = $this->clean((string) ($payload['content'] ?? ''), 600);
        $link = trim((string) ($payload['link_url'] ?? ''));
        $errors = [];

        if ($link !== '' && filter_var($link, FILTER_VALIDATE_URL) === false) {
            $errors['link_url'] = 'Gecerli bir URL yaz.';
        }

        if ($type === 'text' && $content === '') {
            $errors['content'] = 'Metin story bos olamaz.';
        }

        if ($type === 'image' && empty($_FILES['media']['name'])) {
            $errors['media'] = 'Gorsel story icin dosya sec.';
        }

        if ($errors !== []) {
            return Response::json(['ok' => false, 'message' => 'Story alanlarini kontrol et.', 'errors' => $errors], 422);
        }

        try {
            $scan = (new ZaloroxShield($this->config))->scanCommunityPost($content . "\n" . $link, Auth::id());
            if (($scan['status'] ?? 'safe') === 'blocked' || ($scan['action_taken'] ?? '') === 'blocked') {
                return Response::json(['ok' => false, 'message' => 'Zalorox Shield bu story icerigini engelledi.'], 422);
            }

            $media = null;
            if ($type === 'image') {
                $media = Upload::storeImage(
                    $_FILES['media'],
                    (string) ($this->config['STORY_IMAGE_UPLOAD_PATH'] ?? '/public/uploads/stories/'),
                    (int) ($this->config['STORY_IMAGE_MAX_MB'] ?? 12)
                );
            }

            $story = (new Story())->createStory((int) Auth::id(), $type, $content, $media, $link !== '' ? $link : null);

            return Response::json(['ok' => true, 'message' => 'Story yayinlandi. 24 saat sonra otomatik sona erer.', 'story' => $story]);
        } catch (Throwable $exception) {
            $this->logException($exception, 'stories.create');

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

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

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

        $id = (int) ($this->payload()['id'] ?? $this->payload()['story_id'] ?? 0);
        if ($id <= 0) {
            return Response::json(['ok' => false, 'message' => 'Story secimi gecersiz.'], 422);
        }

        try {
            $deleted = (new Story())->softDelete($id, (int) Auth::id(), Auth::role('admin'));

            return Response::json(['ok' => $deleted, 'message' => $deleted ? 'Story silindi.' : 'Story bulunamadi veya yetkin yok.'], $deleted ? 200 : 404);
        } catch (Throwable $exception) {
            $this->logException($exception, 'stories.delete');

            return Response::json(['ok' => false, 'message' => 'Story silinemedi.'], 500);
        }
    }

    public function list(): Response
    {
        try {
            $storyModel = new Story();
            $userId = (int) ($_GET['user_id'] ?? 0);
            $stories = $userId > 0
                ? $storyModel->listActiveForUser($userId, Auth::id())
                : $storyModel->listActiveFeed(Auth::id(), 40);

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

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

    public function viewStory(): Response
    {
        $id = (int) ($this->payload()['id'] ?? $this->payload()['story_id'] ?? 0);
        if ($id <= 0) {
            return Response::json(['ok' => false, 'message' => 'Story secimi gecersiz.'], 422);
        }

        try {
            $model = new Story();
            $story = $model->findActive($id, Auth::id());
            if (!$story) {
                return Response::json(['ok' => false, 'message' => 'Story bulunamadi veya suresi doldu.'], 404);
            }

            if (Auth::check()) {
                $model->markViewed($id, (int) Auth::id());
                $story['viewer_seen'] = true;
            }

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

            return Response::json(['ok' => false, 'message' => 'Story yuklenemedi.'], 500);
        }
    }

    private function validCsrf(): bool
    {
        $payload = $this->payload();

        return Csrf::verify((string) ($payload['_csrf'] ?? ($_SERVER['HTTP_X_CSRF_TOKEN'] ?? '')));
    }

    private function payload(): array
    {
        if ($_POST !== []) {
            return $_POST;
        }

        if ($this->jsonPayload !== null) {
            return $this->jsonPayload;
        }

        $raw = file_get_contents('php://input') ?: '';
        $decoded = json_decode($raw, true);
        if (is_array($decoded)) {
            $this->jsonPayload = $decoded;
            return $this->jsonPayload;
        }

        parse_str($raw, $parsed);
        $this->jsonPayload = is_array($parsed) ? $parsed : [];

        return $this->jsonPayload;
    }

    private function clean(string $value, int $limit): string
    {
        $value = trim(preg_replace('/\s+/', ' ', strip_tags($value)) ?: '');

        return function_exists('mb_substr') ? mb_substr($value, 0, $limit) : substr($value, 0, $limit);
    }
}
