<?php
declare(strict_types=1);

namespace App\Controllers;

use App\Core\{Auth, Csrf, Response};
use App\Models\Package;
use Throwable;

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

    public function studioPackages(): Response
    {
        if (!$this->requireJsonUser()) {
            return Response::json(['ok' => false, 'message' => 'Giris yapmalisin.'], 403);
        }

        if (!$this->canManagePackages()) {
            return Response::json(['ok' => false, 'message' => 'Paketleri sadece creator hesaplari yonetebilir.'], 403);
        }

        try {
            return Response::json([
                'ok' => true,
                'packages' => (new Package())->listForCreator((int) Auth::id(), true),
            ]);
        } catch (Throwable $exception) {
            $this->logException($exception, 'package.studioPackages');

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

    public function creatorPackages(string $userId): Response
    {
        $creatorId = (int) $userId;
        if ($creatorId <= 0) {
            return Response::json(['ok' => false, 'message' => 'Creator gecersiz.'], 422);
        }

        try {
            $packages = (new Package())->activeForCreator($creatorId);
            $viewerId = Auth::id() ?? 0;

            foreach ($packages as &$package) {
                $package['viewer_is_subscribed'] = $viewerId > 0
                    && Auth::hasActiveSubscription($viewerId, $creatorId, (int) $package['id']);
            }
            unset($package);

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

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

    public function create(): Response
    {
        if (!$this->guardWrite()) {
            return Response::json(['ok' => false, 'message' => 'Paket olusturma yetkin yok.'], 403);
        }

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

        $payload = $this->payload();
        $model = new Package();
        $errors = $model->validatePayload($payload);
        if ($errors !== []) {
            return Response::json(['ok' => false, 'message' => $errors[0], 'errors' => $errors], 422);
        }

        try {
            $package = $model->createForCreator((int) Auth::id(), $payload);

            return Response::json(['ok' => true, 'message' => 'Paket olusturuldu.', 'package' => $package]);
        } catch (Throwable $exception) {
            $this->logException($exception, 'package.create');

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

    public function update(): Response
    {
        if (!$this->guardWrite()) {
            return Response::json(['ok' => false, 'message' => 'Paket duzenleme yetkin yok.'], 403);
        }

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

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

        $model = new Package();
        $errors = $model->validatePayload($payload);
        if ($errors !== []) {
            return Response::json(['ok' => false, 'message' => $errors[0], 'errors' => $errors], 422);
        }

        try {
            $package = $model->updateOwned($packageId, (int) Auth::id(), $this->isAdmin(), $payload);
            if (!$package) {
                return Response::json(['ok' => false, 'message' => 'Paket bulunamadi veya bu paket sana ait degil.'], 404);
            }

            return Response::json(['ok' => true, 'message' => 'Paket guncellendi.', 'package' => $package]);
        } catch (Throwable $exception) {
            $this->logException($exception, 'package.update');

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

    public function toggle(): Response
    {
        if (!$this->guardWrite()) {
            return Response::json(['ok' => false, 'message' => 'Paket durumu degistirme yetkin yok.'], 403);
        }

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

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

        try {
            $model = new Package();
            $current = $model->findPublic($packageId);
            $nextStatus = (string) ($payload['status'] ?? '');
            if (!in_array($nextStatus, ['active', 'inactive'], true)) {
                $nextStatus = (($current['status'] ?? 'inactive') === 'active') ? 'inactive' : 'active';
            }

            $package = $model->setStatusOwned($packageId, (int) Auth::id(), $this->isAdmin(), $nextStatus);
            if (!$package) {
                return Response::json(['ok' => false, 'message' => 'Paket bulunamadi veya bu paket sana ait degil.'], 404);
            }

            return Response::json(['ok' => true, 'message' => 'Paket durumu guncellendi.', 'package' => $package]);
        } catch (Throwable $exception) {
            $this->logException($exception, 'package.toggle');

            return Response::json(['ok' => false, 'message' => 'Paket durumu guncellenemedi.'], 500);
        }
    }

    public function delete(): Response
    {
        if (!$this->guardWrite()) {
            return Response::json(['ok' => false, 'message' => 'Paket silme yetkin yok.'], 403);
        }

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

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

        try {
            $package = (new Package())->softDeleteOwned($packageId, (int) Auth::id(), $this->isAdmin());
            if (!$package) {
                return Response::json(['ok' => false, 'message' => 'Paket bulunamadi veya bu paket sana ait degil.'], 404);
            }

            return Response::json(['ok' => true, 'message' => 'Paket pasife alindi.', 'package' => $package]);
        } catch (Throwable $exception) {
            $this->logException($exception, 'package.delete');

            return Response::json(['ok' => false, 'message' => 'Paket pasife alinamadi.'], 500);
        }
    }

    private function requireJsonUser(): bool
    {
        return Auth::check();
    }

    private function guardWrite(): bool
    {
        return Auth::check() && $this->canManagePackages();
    }

    private function canManagePackages(): bool
    {
        $role = (string) (Auth::user()['role'] ?? 'user');

        return in_array($role, ['creator', 'admin'], true);
    }

    private function isAdmin(): bool
    {
        return (string) (Auth::user()['role'] ?? '') === 'admin';
    }

    private function validCsrf(): bool
    {
        return Csrf::verify((string) ($this->payload()['_csrf'] ?? ''));
    }

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

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

        $decoded = json_decode(file_get_contents('php://input') ?: '', true);
        $this->jsonPayload = is_array($decoded) ? $decoded : [];

        return $this->jsonPayload;
    }
}
