<?php

namespace App\Services\Roles;

use App\Models\Role;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class RoleCrudService
{
    public function create(array $payload): Role
    {
        $data = $this->normalizePayload($payload);

        try {
            return DB::transaction(function () use ($data) {
                return Role::query()->create($data);
            });
        } catch (\Throwable $e) {
            Log::error('Role create failed: ' . $e->getMessage());
            throw $e;
        }
    }

    public function update(Role $role, array $payload): Role
    {
        $data = $this->normalizePayload($payload, $role->id, $role->slug ?? null);

        try {
            return DB::transaction(function () use ($role, $data) {
                $role->fill($data);
                $role->save();
                return $role;
            });
        } catch (\Throwable $e) {
            Log::error('Role update failed: ' . $e->getMessage());
            throw $e;
        }
    }

    public function delete(Role $role): void
    {
        try {
            DB::transaction(function () use ($role) {
                $role->delete();
            });
        } catch (\Throwable $e) {
            Log::error('Role delete failed: ' . $e->getMessage());
            throw $e;
        }
    }

    private function normalizePayload(array $payload, ?int $ignoreId = null, ?string $currentSlug = null): array
    {
        $rawName = trim((string) ($payload['name'] ?? ''));
        $rawSlug = trim((string) ($payload['slug'] ?? ''));
        $route = trim((string) ($payload['dashboard_route'] ?? ''));
        $desc = trim((string) ($payload['description'] ?? ''));
        $priority = (int) ($payload['priority'] ?? 0);
        $isActive = !empty($payload['is_active']) ? 1 : 0;

        $name = strtolower($rawName);
        $dashboardRoute = strtolower($route);
        $description = strtolower($desc);

        $slug = $rawSlug !== '' ? $rawSlug : $name;
        $slug = strtolower(preg_replace('/[^a-z0-9]+/i', '_', $slug));
        $slug = trim($slug, '_');

        if ($slug !== $currentSlug) {
            $slug = $this->ensureUniqueSlug($slug, $ignoreId);
        }

        return [
            'name' => $name,
            'slug' => $slug,
            'description' => $description,
            'dashboard_route' => $dashboardRoute,
            'priority' => $priority,
            'is_active' => $isActive,
        ];
    }

    private function ensureUniqueSlug(string $baseSlug, ?int $ignoreId = null): string
    {
        $slug = $baseSlug;
        $i = 2;

        while (true) {
            $query = Role::query()->where('slug', $slug);
            if ($ignoreId !== null) {
                $query->where('id', '!=', $ignoreId);
            }

            if (!$query->exists()) {
                return $slug;
            }

            $slug = $baseSlug . '_' . $i;
            $i++;

            if ($i > 100000) {
                return $slug;
            }
        }
    }
}
