<?php
namespace App\Controllers;

use App\Core\{Auth, Csrf, Database, Response, Upload};
use App\Models\{Mod, Music, Notification};
use App\Services\ZaloroxAI\{ContentSuggestionService, TagSuggestionService};
use Throwable;

class ApiController extends BaseController
{
    public function search(): Response
    {
        $q = trim((string) ($_GET['q'] ?? $_POST['q'] ?? ''));
        if (strlen($q) < 2) {
            return Response::json(['ok' => true, 'items' => []]);
        }

        try {
            $mods = (new Mod())->list(['q' => $q, 'sort' => 'popular', 'limit' => 6]);
            $items = array_map(static fn (array $mod): array => [
                'type' => 'mod',
                'title' => (string) ($mod['title'] ?? 'Mod'),
                'subtitle' => (string) ($mod['category_name'] ?? $mod['category'] ?? 'Mod'),
                'url' => '/mod/' . (string) ($mod['slug'] ?? ''),
                'image' => (string) ($mod['cover_image'] ?? $mod['cover_path'] ?? '/uploads/covers/mod-1.svg'),
            ], $mods);

            return Response::json(['ok' => true, 'items' => $items]);
        } catch (Throwable) {
            $needle = strtolower($q);
            $items = [];
            foreach (($this->samples()['mods'] ?? []) as $mod) {
                if (!str_contains(strtolower((string) ($mod['title'] ?? '')), $needle)) {
                    continue;
                }
                $items[] = [
                    'type' => 'mod',
                    'title' => (string) ($mod['title'] ?? 'Mod'),
                    'subtitle' => (string) ($mod['category'] ?? 'Mod'),
                    'url' => '/mod/' . (string) ($mod['slug'] ?? ''),
                    'image' => (string) ($mod['cover'] ?? '/uploads/covers/mod-1.svg'),
                ];
            }

            return Response::json(['ok' => true, 'items' => array_slice($items, 0, 6)]);
        }
    }

    public function musicSearch(): Response
    {
        return Response::json(['items' => $this->samples()['music']]);
    }

    public function suggestTags(): Response
    {
        if (!Auth::check()) {
            return Response::json(['success' => false, 'ok' => false, 'message' => 'Giriş yapmalısın.'], 403);
        }

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

        $type = (string) ($input['type'] ?? 'mod');
        $categoryId = (int) ($input['category_id'] ?? 0);
        $category = $categoryId > 0 ? $this->categoryName($categoryId) : '';
        $description = trim(
            (string) ($input['description'] ?? '') . ' ' .
            (string) ($input['game'] ?? '') . ' ' .
            (string) ($input['file_name'] ?? '') . ' ' .
            (string) ($input['video_title'] ?? '') . ' ' .
            (string) ($input['tags'] ?? '')
        );
        $tags = (new TagSuggestionService())->suggest(
            $type,
            (string) ($input['title'] ?? ''),
            $description,
            $category
        );

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

    public function contentSuggestions(): Response
    {
        if (!Auth::check()) {
            return Response::json(['success' => false, 'ok' => false, 'message' => 'Giris yapmalisin.'], 403);
        }

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

        $suggestions = (new ContentSuggestionService())->suggest($input);

        return Response::json(['success' => true, 'ok' => true] + $suggestions);
    }

    public function notificationsList(): Response
    {
        if (!Auth::check()) {
            return Response::json(['ok' => false, 'message' => 'Giris yapmalisin.'], 401);
        }

        try {
            $model = new Notification();
            $userId = (int) Auth::id();

            return Response::json([
                'ok' => true,
                'notifications' => $model->recentForUser($userId, 14),
                'unread_count' => $model->unreadCount($userId),
            ]);
        } catch (Throwable $exception) {
            $this->logException($exception, 'api.notifications.list');

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

    public function notificationRead(): Response
    {
        if (!Auth::check()) {
            return Response::json(['ok' => false, 'message' => 'Giris yapmalisin.'], 401);
        }

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

        $id = (int) ($input['id'] ?? 0);
        if ($id < 1) {
            return Response::json(['ok' => false, 'message' => 'Bildirim ID gecersiz.'], 422);
        }

        (new Notification())->markRead((int) Auth::id(), $id);

        return Response::json(['ok' => true, 'message' => 'Bildirim okundu.']);
    }

    public function notificationsReadAll(): Response
    {
        if (!Auth::check()) {
            return Response::json(['ok' => false, 'message' => 'Giris yapmalisin.'], 401);
        }

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

        (new Notification())->markAllRead((int) Auth::id());

        return Response::json(['ok' => true, 'message' => 'Tum bildirimler okundu.']);
    }

    public function notificationsClear(): Response
    {
        if (!Auth::check()) {
            return Response::json(['ok' => false, 'message' => 'Giris yapmalisin.'], 401);
        }

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

        $deleted = (new Notification())->clearForUser((int) Auth::id());

        return Response::json(['ok' => true, 'message' => $deleted > 0 ? 'Bildirimler temizlendi.' : 'Temizlenecek bildirim yok.', 'deleted' => $deleted]);
    }

    public function uploadImage(): Response
    {
        if ($response = $this->guardUpload()) {
            return $response;
        }

        $file = $_FILES['file'] ?? $_FILES['image'] ?? $_FILES['cover'] ?? null;
        if (!is_array($file)) {
            return Response::json(['success' => false, 'ok' => false, 'message' => 'Görsel dosyası seçilmedi.'], 422);
        }

        try {
            $context = (string) ($_POST['context'] ?? 'studio');
            $path = match ($context) {
                'music', 'music_cover', 'music-cover' => (string) $this->config['MUSIC_COVER_UPLOAD_PATH'],
                'cover', 'mod_cover', 'mod-cover' => (string) $this->config['MOD_COVER_UPLOAD_PATH'],
                default => (string) $this->config['MOD_GALLERY_UPLOAD_PATH'],
            };
            $stored = Upload::storeImage($file, $path, (int) ($this->config['MOD_GALLERY_MAX_MB'] ?? 12));

            return Response::json(['success' => true, 'ok' => true, 'path' => $stored, 'url' => $stored]);
        } catch (Throwable $exception) {
            $this->logException($exception, 'api.uploadImage');

            return Response::json(['success' => false, 'ok' => false, 'message' => $exception->getMessage()], 422);
        }
    }

    public function uploadAudio(): Response
    {
        if ($response = $this->guardUpload()) {
            return $response;
        }

        $file = $_FILES['file'] ?? $_FILES['audio'] ?? $_FILES['audio_file'] ?? null;
        if (!is_array($file)) {
            return Response::json(['success' => false, 'ok' => false, 'message' => 'Ses dosyası seçilmedi.'], 422);
        }

        try {
            $stored = Upload::storeAudio(
                $file,
                (string) $this->config['MUSIC_UPLOAD_PATH'],
                (array) $this->config['MUSIC_ALLOWED_EXTENSIONS'],
                (int) $this->config['MUSIC_MAX_UPLOAD_MB']
            );

            return Response::json(['success' => true, 'ok' => true, 'path' => $stored, 'url' => $stored]);
        } catch (Throwable $exception) {
            $this->logException($exception, 'api.uploadAudio');

            return Response::json(['success' => false, 'ok' => false, 'message' => $exception->getMessage()], 422);
        }
    }

    private function guardUpload(): ?Response
    {
        if (!Auth::check()) {
            return Response::json(['success' => false, 'ok' => false, 'message' => 'Giriş yapmalısın.'], 403);
        }

        if (!Csrf::verify((string) ($_POST['_csrf'] ?? ''))) {
            return Response::json(['success' => false, 'ok' => false, 'message' => 'Güvenlik oturumu yenilenmeli.'], 419);
        }

        return null;
    }

    private function input(): array
    {
        $input = $_POST;
        $raw = file_get_contents('php://input');
        if (is_string($raw) && $raw !== '') {
            $decoded = json_decode($raw, true);
            if (is_array($decoded)) {
                $input = array_merge($input, $decoded);
            }
        }

        return $input;
    }

    private function categoryName(int $categoryId): string
    {
        try {
            $statement = Database::connection($this->config)->prepare('SELECT name FROM categories WHERE id = :id LIMIT 1');
            $statement->execute(['id' => $categoryId]);

            return (string) ($statement->fetchColumn() ?: '');
        } catch (Throwable) {
            return '';
        }
    }
}
