<?php
namespace App\Controllers;

use App\Core\{Auth, Csrf, Lang, Response, Session};
use App\Models\{Comment, Mod};
use App\Services\Translate\ZaloroxTranslateBot;
use Throwable;

class ModController extends BaseController
{
    public function show(string $slug): string
    {
        return $this->showWithLanguage($slug, Lang::current());
    }

    public function showLocalized(string $lang, string $slug): string
    {
        return $this->showWithLanguage($slug, $lang);
    }

    private function showWithLanguage(string $slug, string $language): string
    {
        if (in_array($language, $this->config['supported_languages'] ?? ['tr', 'en', 'de', 'fr'], true)) {
            Session::put('lang', $language);
        }

        try {
            $model = new Mod();
            $mod = $model->findBySlug($slug);

            if (!$mod) {
                return $this->notFound();
            }

            try {
                $model->recordView((int) $mod['id'], Auth::id(), $_SERVER['REMOTE_ADDR'] ?? null);
                $mod['view_count']++;
                $mod['views']++;
            } catch (Throwable) {
                // View counters should never block the public detail page.
            }

            $gallery = $model->galleryItems($mod);
            $related = $model->relatedAdvanced($mod, 12);
            $comments = (new Comment())->listForContent('mod', (int) $mod['id'], 40);
            $userReaction = $model->userReaction((int) $mod['id'], Auth::id());
            $canDownload = Auth::userCanAccessMod($mod);
            $translationNote = null;
            if ($language !== 'tr') {
                $translation = (new ZaloroxTranslateBot($this->config))->translationFor('mod', (int) $mod['id'], $language);
                if ($translation) {
                    $mod['title'] = $translation['title'] ?: $mod['title'];
                    $mod['description'] = $translation['body'] ?: ($translation['description'] ?: $mod['description']);
                } else {
                    $translationNote = 'Ceviri hazirlaniyor; simdilik Turkce orijinal icerik gosteriliyor.';
                }
            }

            if ($related === []) {
                $related = $model->popular(6);
            }

            return $this->view('main', 'mods/show', [
                'title' => $mod['title'],
                'mod' => $mod,
                'galleryItems' => $gallery,
                'related' => $related,
                'comments' => $comments,
                'userReaction' => $userReaction,
                'canDownload' => $canDownload,
                'translationNote' => $translationNote,
                'contentLanguage' => $language,
            ]);
        } catch (Throwable) {
            $data = $this->samples();
            $mod = null;

            foreach ($data['mods'] ?? [] as $item) {
                if (($item['slug'] ?? '') === $slug) {
                    $mod = $item;
                    break;
                }
            }

            if (!$mod) {
                return $this->notFound();
            }

            $related = array_values(array_filter($data['mods'] ?? [], static fn (array $item): bool => ($item['slug'] ?? '') !== $slug));

            return $this->view('main', 'mods/show', [
                'title' => $mod['title'],
                'mod' => $mod,
                'galleryItems' => [],
                'related' => $related,
                'comments' => [],
                'userReaction' => null,
                'canDownload' => empty($mod['premium']),
            ]);
        }
    }

    public function recordViewApi(string $id): Response
    {
        if (!Csrf::verify()) {
            return Response::json(['ok' => false, 'message' => 'Guvenlik oturumu yenilenmeli.'], 419);
        }

        try {
            $model = new Mod();
            $mod = $model->findPublishedById((int) $id);
            if (!$mod) {
                return Response::json(['ok' => false, 'message' => 'Mod bulunamadi.'], 404);
            }

            $model->recordView((int) $mod['id'], Auth::id(), $_SERVER['REMOTE_ADDR'] ?? null);

            return Response::json(['ok' => true, 'view_count' => ((int) $mod['view_count']) + 1]);
        } catch (Throwable) {
            return Response::json(['ok' => false, 'message' => 'Goruntulenme kaydedilemedi.'], 500);
        }
    }

    public function reaction(string $id): Response
    {
        if (!Auth::check()) {
            return Response::json(['ok' => false, 'message' => 'Reaksiyon vermek icin giris yapmalisin.'], 403);
        }

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

        $reaction = strtolower((string) ($_POST['reaction'] ?? ''));
        if (!in_array($reaction, ['like', 'dislike'], true)) {
            return Response::json(['ok' => false, 'message' => 'Reaksiyon gecersiz.'], 422);
        }

        try {
            $model = new Mod();
            $mod = $model->findPublishedById((int) $id);
            if (!$mod) {
                return Response::json(['ok' => false, 'message' => 'Mod bulunamadi.'], 404);
            }

            $result = $model->recordReaction((int) $mod['id'], (int) Auth::id(), $reaction);

            return Response::json(['ok' => true] + $result);
        } catch (Throwable) {
            return Response::json(['ok' => false, 'message' => 'Reaksiyon kaydedilemedi.'], 500);
        }
    }

    public function search(): string
    {
        $q = trim((string) ($_GET['q'] ?? ''));
        $sort = $this->normalizeSort($_GET['sirala'] ?? $_GET['sort'] ?? 'newest');

        try {
            $mods = (new Mod())->list([
                'q' => $q,
                'sort' => $sort,
                'limit' => 36,
            ]);
        } catch (Throwable) {
            $mods = $this->fallbackSearch($q, $sort);
        }

        return $this->view('main', 'mods/list', [
            'title' => $q === '' ? 'Mod Arama' : 'Arama: ' . $q,
            'heading' => $q === '' ? 'Modlar' : 'Arama: ' . $q,
            'mods' => $mods,
            'q' => $q,
            'sort' => $sort,
            'category' => null,
        ]);
    }

    private function normalizeSort(string $sort): string
    {
        return match ($sort) {
            'indirilen', 'downloads', 'downloaded' => 'downloaded',
            'goruntulenen', 'views', 'viewed' => 'viewed',
            'populer', 'popular' => 'popular',
            'onerilen', 'recommended' => 'recommended',
            'premium' => 'premium',
            'ucretsiz', 'free' => 'free',
            default => 'newest',
        };
    }

    private function fallbackSearch(string $q, string $sort): array
    {
        $mods = $this->samples()['mods'] ?? [];

        if ($q !== '') {
            $needle = strtolower($q);
            $mods = array_values(array_filter($mods, static function (array $mod) use ($needle): bool {
                return str_contains(strtolower((string) ($mod['title'] ?? '')), $needle)
                    || str_contains(strtolower((string) ($mod['category'] ?? '')), $needle)
                    || str_contains(strtolower((string) ($mod['author'] ?? '')), $needle);
            }));
        }

        usort($mods, static function (array $a, array $b) use ($sort): int {
            return match ($sort) {
                'downloaded' => ((int) ($b['downloads'] ?? 0)) <=> ((int) ($a['downloads'] ?? 0)),
                'viewed', 'popular' => ((int) ($b['views'] ?? 0)) <=> ((int) ($a['views'] ?? 0)),
                'premium' => ((int) !empty($b['premium'])) <=> ((int) !empty($a['premium'])),
                'free' => ((int) empty($b['premium'])) <=> ((int) empty($a['premium'])),
                default => ((int) ($b['id'] ?? 0)) <=> ((int) ($a['id'] ?? 0)),
            };
        });

        return $mods;
    }

    private function notFound(): string
    {
        http_response_code(404);

        return $this->view('main', 'pages/show', [
            'title' => '404',
            'page' => [
                'title' => 'Mod bulunamadi',
                'content' => 'Aradigin mod yayinda degil veya tasinmis olabilir.',
            ],
        ]);
    }
}
