<?php

declare(strict_types=1);

namespace App\Http\Controllers\Api\V1;

use App\Domain\Account\Models\Account;
use App\Domain\Database\Models\MysqlDatabase;
use App\Domain\Database\Models\MysqlUser;
use App\Http\Controllers\Controller;
use App\Http\Resources\Api\V1\DatabaseResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

/**
 * Databases resource — CRUD (no update) + nested DB users.
 */
class DatabasesApiController extends Controller
{
    // ─── Databases ───────────────────────────────────────────────────────

    public function index(Request $request): JsonResponse
    {
        $this->requireAbility($request, 'databases:read');

        $query = MysqlDatabase::query();
        $user = $request->user();

        if (! $user->hasRole('admin')) {
            $accountId = Account::where('owner_user_id', $user->id)->value('id');
            $query->where('account_id', $accountId);
        } elseif ($accountId = $request->integer('account_id')) {
            $query->where('account_id', $accountId);
        }

        $databases = $query->latest()->paginate($request->integer('per_page', 25));

        return DatabaseResource::collection($databases)->response();
    }

    public function show(Request $request, MysqlDatabase $database): JsonResponse
    {
        $this->requireAbility($request, 'databases:read');
        $this->authorizeScope($request, $database->account_id);

        return (new DatabaseResource($database))->response();
    }

    public function store(Request $request): JsonResponse
    {
        $this->requireAbility($request, 'databases:write');

        $validated = $request->validate([
            'account_id' => ['required', 'exists:accounts,id'],
            'name' => ['required', 'string', 'max:64'],
            'charset' => ['sometimes', 'string', 'default' => 'utf8mb4'],
            'collation' => ['sometimes', 'string'],
        ]);

        $this->authorizeScope($request, (int) $validated['account_id']);

        $database = MysqlDatabase::create(array_merge($validated, ['status' => 'pending']));

        return (new DatabaseResource($database))->response()->setStatusCode(201);
    }

    public function destroy(Request $request, MysqlDatabase $database): JsonResponse
    {
        $this->requireAbility($request, 'databases:write');
        $this->authorizeScope($request, $database->account_id);

        $database->delete();

        return response()->json(['data' => ['message' => 'Veritabanı silindi.']]);
    }

    // ─── Database users (nested) ─────────────────────────────────────────

    /**
     * GET /databases/{database}/users
     */
    public function dbUsersIndex(Request $request, MysqlDatabase $database): JsonResponse
    {
        $this->requireAbility($request, 'databases:read');
        $this->authorizeScope($request, $database->account_id);

        $users = MysqlUser::where('account_id', $database->account_id)->get()->map(fn ($u) => [
            'id' => $u->id,
            'name' => $u->name,
            'real_user_name' => $u->real_user_name,
            'host' => $u->host,
            'created_at' => $u->created_at?->toIso8601String(),
        ]);

        return response()->json(['data' => $users]);
    }

    /**
     * POST /databases/{database}/users
     */
    public function dbUsersStore(Request $request, MysqlDatabase $database): JsonResponse
    {
        $this->requireAbility($request, 'databases:write');
        $this->authorizeScope($request, $database->account_id);

        $validated = $request->validate([
            'username' => ['required', 'string', 'max:32'],
            'password' => ['required', 'string', 'min:8'],
            'privileges' => ['sometimes', 'array'],
        ]);

        $user = MysqlUser::create([
            'account_id' => $database->account_id,
            'name' => $validated['username'],
            'password_hash' => bcrypt($validated['password']),
            'host' => '%',
            'status' => 'pending',
        ]);

        return response()->json(['data' => [
            'id' => $user->id,
            'name' => $user->name,
        ]], 201);
    }

    /**
     * DELETE /databases/{database}/users/{dbUser}
     */
    public function dbUsersDestroy(Request $request, MysqlDatabase $database, MysqlUser $dbUser): JsonResponse
    {
        $this->requireAbility($request, 'databases:write');
        $this->authorizeScope($request, $database->account_id);

        $dbUser->delete();

        return response()->json(['data' => ['message' => 'DB kullanıcısı silindi.']]);
    }

    // ─── Helpers ─────────────────────────────────────────────────────────

    private function requireAbility(Request $request, string $ability): void
    {
        $token = $request->user()?->currentAccessToken();
        if ($token && ! in_array('*', $token->abilities, true) && ! in_array($ability, $token->abilities, true)) {
            abort(403, "Token için '{$ability}' yetkisi gerekli.");
        }
    }

    private function authorizeScope(Request $request, int $accountId): void
    {
        $user = $request->user();
        if ($user->hasRole('admin')) {
            return;
        }
        $ownAccountId = Account::where('owner_user_id', $user->id)->value('id');
        if ($ownAccountId !== $accountId) {
            abort(403, 'Bu kaynağa erişim yetkiniz yok.');
        }
    }
}
