<?php
namespace App\Controllers;

use App\Core\Auth;
use App\Core\Database;
use App\Core\Response;
use App\Core\Csrf;
use App\Core\Session;
use App\Models\Mod;
use App\Services\Security\ZaloroxShield;
use function App\Core\url;
use Throwable;

class DownloadController extends BaseController
{
    public function download(string $id): Response
    {
        try {
            $model = new Mod();
            $mod = $model->findPublishedById((int) $id);

            if (!$mod) {
                return Response::redirect(url('/arama'));
            }

            if (!Auth::userCanAccessMod($mod)) {
                Session::flash('toast', ['type' => 'warning', 'message' => 'Bu mod premium. Erisim icin abone olmalisin.']);

                return Response::redirect(url('/mod/' . ($mod['slug'] ?? '')));
            }

            $target = $this->downloadTarget($mod);
            if ($target === null) {
                Session::flash('toast', ['type' => 'error', 'message' => 'Indirme linki henuz hazir degil.']);

                return Response::redirect(url('/mod/' . ($mod['slug'] ?? '')));
            }

            $scan = $this->scanAndStore($target, (int) $mod['id']);

            if ($this->scanBlocksRedirect($scan)) {
                Session::flash('toast', ['type' => 'error', 'message' => 'Zalorox Shield bu indirme linkini yonlendirmeden durdurdu.']);

                return Response::redirect(url('/mod/' . ($mod['slug'] ?? '')));
            }

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


            return Response::redirect($target);
        } catch (Throwable) {
            Session::flash('toast', ['type' => 'error', 'message' => 'Indirme linki guvenli sekilde hazirlanamadi.']);

            return Response::redirect(url('/arama'));
        }
    }

    public function apiDownload(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);
            }

            if (!Auth::userCanAccessMod($mod)) {
                return Response::json([
                    'ok' => false,
                    'code' => 'subscription_required',
                    'message' => 'Bu mod premium. Erisim icin abone ol.',
                    'cta_url' => url('/kullanici/' . (string) ($mod['author'] ?? $mod['creator_username'] ?? 'creator')) . '#packages',
                ], 403);
            }

            $target = $this->downloadTarget($mod);
            if ($target === null) {
                return Response::json(['ok' => false, 'message' => 'Indirme linki henuz hazir degil.'], 404);
            }

            $scan = $this->scanAndStore($target, (int) $mod['id']);
            if ($this->scanBlocksRedirect($scan)) {
                return Response::json([
                    'ok' => false,
                    'code' => ($scan['status'] ?? '') === 'review' ? 'suspicious_link' : 'blocked_link',
                    'message' => ($scan['status'] ?? '') === 'review'
                        ? 'Zalorox Shield bu linki supheli buldu. Yonlendirme durduruldu.'
                        : 'Zalorox Shield bu indirme linkini engelledi.',
                    'risk_score' => (int) ($scan['risk_score'] ?? 0),
                    'reasons' => $scan['reasons'] ?? [],
                ], 422);
            }

            $confirmed = (string) ($_POST['confirm'] ?? '') === '1';
            if (!$confirmed) {
                return Response::json([
                    'ok' => true,
                    'needs_confirmation' => true,
                    'message' => 'Harici baglantiya yonlendiriliyorsun.',
                    'provider' => parse_url($target, PHP_URL_HOST) ?: 'external',
                    'risk_score' => (int) ($scan['risk_score'] ?? 0),
                    'download_count' => (int) ($mod['download_count'] ?? 0),
                ]);
            }

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

            return Response::json([
                'ok' => true,
                'external_url' => $target,
                'download_count' => $downloadCount,
            ]);
        } catch (Throwable) {
            return Response::json(['ok' => false, 'message' => 'Indirme akisi su anda calisamadi.'], 500);
        }
    }

    private function downloadTarget(array $mod): ?string
    {
        $target = trim((string) (($mod['external_link'] ?? '') ?: ($mod['file_url'] ?? '')));

        return $target !== '' && $target !== '#' ? $target : null;
    }

    private function scanAndStore(string $target, int $modId): array
    {
        $scan = (new ZaloroxShield($this->config))->scanLink($target, Auth::id(), 'mod_external_link', $modId);
        $linkStatus = match ((string) ($scan['status'] ?? 'safe')) {
            'blocked' => 'blocked',
            'review' => 'suspicious',
            default => 'safe',
        };

        try {
            $pdo = Database::connection($this->config);
            $pdo->prepare('UPDATE mods SET external_link_status = :status, external_link_risk_score = :risk_score WHERE id = :id')->execute([
                'status' => $linkStatus,
                'risk_score' => (int) ($scan['risk_score'] ?? 0),
                'id' => $modId,
            ]);
        } catch (Throwable) {
            // Link status cache is useful, but the scan decision above is authoritative for this request.
        }

        return $scan;
    }

    private function scanBlocksRedirect(array $scan): bool
    {
        return in_array((string) ($scan['status'] ?? 'safe'), ['review', 'blocked'], true)
            || in_array((string) ($scan['action_taken'] ?? 'allow'), ['pending_review', 'blocked'], true);
    }
}
