<?php

namespace App\Console\Commands;

use App\Models\PermissionModule;
use App\Models\RoleTemplate;
use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Str;
use ReflectionClass;
use Symfony\Component\Finder\Finder;

class SyncPermissions extends Command
{
    protected $signature = 'permissions:sync {--dry-run : Chỉ liệt kê, không lưu}';

    protected $description = 'Quét Filament Resources và đồng bộ permission modules. Action mới mặc định TẮT.';

    public function handle(): int
    {
        $dryRun = $this->option('dry-run');

        $this->info('Đang quét Filament Resources...');

        $resourcesPath = app_path('Filament/Resources');
        if (! is_dir($resourcesPath)) {
            $this->error('Không tìm thấy thư mục Filament/Resources');
            return self::FAILURE;
        }

        $modules = [];
        $finder = new Finder();
        $finder->files()->in($resourcesPath)->name('*Resource.php');

        foreach ($finder as $file) {
            $class = $this->getClassFromFile($file->getRealPath());
            if (! $class || ! class_exists($class)) {
                continue;
            }

            $ref = new ReflectionClass($class);

            if (! $ref->hasProperty('permissionActions')) {
                continue;
            }

            $prop = $ref->getProperty('permissionActions');
            $prop->setAccessible(true);
            $actions = $prop->getDefaultValue();

            $label = 'Resource';
            if ($ref->hasProperty('pluralModelLabel')) {
                $labelProp = $ref->getProperty('pluralModelLabel');
                $labelProp->setAccessible(true);
                $label = $labelProp->getDefaultValue() ?? $label;
            }

            $moduleName = Str::snake(class_basename($class));
            $moduleName = str_replace('_resource', '', $moduleName);

            $modules[] = [
                'module' => $moduleName,
                'label' => $label,
                'actions' => $actions ?? [],
            ];
        }

        if (empty($modules)) {
            $this->warn('Không tìm thấy Resource nào có $permissionActions.');
            return self::SUCCESS;
        }

        $this->info('Tìm thấy ' . count($modules) . ' module(s):');

        foreach ($modules as $m) {
            $this->line("  - {$m['module']}: " . implode(', ', $m['actions']));
        }

        if ($dryRun) {
            $this->info('Dry-run: Không lưu thay đổi.');
            return self::SUCCESS;
        }

        foreach ($modules as $m) {
            $existing = PermissionModule::where('module', $m['module'])->first();

            if ($existing) {
                $oldActions = $existing->actions ?? [];
                $newActions = $m['actions'];

                if ($oldActions === $newActions) {
                    continue;
                }

                $added = array_diff($newActions, $oldActions);
                $removed = array_diff($oldActions, $newActions);

                $existing->update([
                    'label' => $m['label'],
                    'actions' => $newActions,
                ]);

                if (! empty($added)) {
                    $this->warn("  [{$m['module']}] Thêm actions: " . implode(', ', $added));
                    // Action mới mặc định TẮT cho tất cả role
                    $this->disableNewActionsForAllRoles($m['module'], $added);
                }
                if (! empty($removed)) {
                    $this->warn("  [{$m['module']}] Xóa actions: " . implode(', ', $removed));
                    $this->removeActionsFromAllRoles($m['module'], $removed);
                }
            } else {
                PermissionModule::create([
                    'module' => $m['module'],
                    'label' => $m['label'],
                    'actions' => $m['actions'],
                ]);
                $this->info("  [{$m['module']}] Tạo mới module.");
                // Module mới mặc định TẮT cho tất cả role
                $this->disableNewActionsForAllRoles($m['module'], $m['actions']);
            }
        }

        $this->info('Đồng bộ hoàn tất.');
        return self::SUCCESS;
    }

    private function getClassFromFile(string $path): ?string
    {
        $contents = file_get_contents($path);

        // Tìm namespace
        $namespace = null;
        if (preg_match('/namespace\s+([^;]+);/', $contents, $matches)) {
            $namespace = $matches[1];
        }

        // Tìm class name
        $class = null;
        if (preg_match('/class\s+(\w+)/', $contents, $matches)) {
            $class = $matches[1];
        }

        if ($namespace && $class) {
            return $namespace . '\\' . $class;
        }

        return null;
    }

    private function disableNewActionsForAllRoles(string $module, array $actions): void
    {
        $roles = RoleTemplate::all();
        foreach ($roles as $role) {
            $perms = $role->permissions ?? [];
            foreach ($actions as $action) {
                if (isset($perms[$module]) && in_array($action, $perms[$module])) {
                    continue; // Đã có thì giữ nguyên
                }
                // Không thêm vào = mặc định TẮT
            }
            // Không cần update vì JSONB không lưu action mới = TẮT
        }
    }

    private function removeActionsFromAllRoles(string $module, array $actions): void
    {
        $roles = RoleTemplate::all();
        foreach ($roles as $role) {
            $perms = $role->permissions ?? [];
            if (isset($perms[$module])) {
                $perms[$module] = array_values(array_diff($perms[$module], $actions));
                if (empty($perms[$module])) {
                    unset($perms[$module]);
                }
                $role->update(['permissions' => $perms]);
            }
        }
    }
}
