<?php

namespace App\Filament\Admin\Resources\Roles\Forms;

use App\Workflows\Models\StepTemplate;
use BezhanSalleh\FilamentShield\Support\Utils;
use BezhanSalleh\FilamentShield\Traits\HasShieldFormComponents;
use Filament\Facades\Filament;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Component;
use Filament\Schemas\Components\Grid;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Components\Tabs;
use Filament\Schemas\Components\Tabs\Tab;
use Filament\Schemas\Schema;
use Illuminate\Validation\Rules\Unique;

class RoleForm
{
    use HasShieldFormComponents;

    public static function configure(Schema $schema): Schema
    {
        return $schema
            ->components([
                Grid::make()
                    ->schema([
                        Section::make()
                            ->schema([
                                TextInput::make('name')
                                    ->label(__('filament-shield::filament-shield.field.name'))
                                    ->unique(
                                        modifyRuleUsing: fn (Unique $rule): Unique => Utils::isTenancyEnabled() ? $rule->where(Utils::getTenantModelForeignKey(), Filament::getTenant()?->id) : $rule
                                    )
                                    ->required()
                                    ->maxLength(255),

                                TextInput::make('guard_name')
                                    ->label(__('filament-shield::filament-shield.field.guard_name'))
                                    ->default(Utils::getFilamentAuthGuard())
                                    ->nullable()
                                    ->maxLength(255),

                                Select::make(config('permission.column_names.team_foreign_key'))
                                    ->label(__('filament-shield::filament-shield.field.team'))
                                    ->placeholder(__('filament-shield::filament-shield.field.team.placeholder'))
                                    /** @phpstan-ignore-next-line */
                                    ->default(Filament::getTenant()?->id)
                                    ->options(fn (): array => in_array(Utils::getTenantModel(), [null, '', '0'], true) ? [] : Utils::getTenantModel()::pluck('name', 'id')->toArray())
                                    ->visible(fn (): bool => static::shield()->isCentralApp() && Utils::isTenancyEnabled())
                                    ->dehydrated(fn (): bool => static::shield()->isCentralApp() && Utils::isTenancyEnabled()),
                                static::getSelectAllFormComponent(),

                            ])
                            ->columns([
                                'sm' => 2,
                                'lg' => 3,
                            ])
                            ->columnSpanFull(),
                    ])
                    ->columnSpanFull(),
                static::getShieldFormComponents(),
            ]);
    }

    public static function getShieldFormComponents(): Component
    {
        return Tabs::make('Permissions')
            ->contained()
            ->tabs([
                static::getTabFormComponentForResources(),
                static::getTabFormComponentForPage(),
                static::getTabFormComponentForWidget(),
                static::getTabFormComponentForCustomPermissions(),
                static::getTabFormComponentForWorkflowStepPermissions(),
            ])
            ->columnSpan('full');
    }

    public static function getTabFormComponentForWorkflowStepPermissions(): Tab
    {
        $workflowGroups = static::getWorkflowPermissionGroups();
        $totalCount = collect($workflowGroups)->sum(fn ($group) => count($group['permissions']));

        return Tab::make('workflow_step_permissions')
            ->label('Workflow Step Permissions')
            ->visible(fn (): bool => $totalCount > 0)
            ->badge($totalCount)
            ->schema([
                Grid::make()
                    ->schema(static::getWorkflowPermissionSections($workflowGroups))
                    ->columns(static::shield()->getGridColumns()),
            ]);
    }

    protected static function getWorkflowPermissionGroups(): array
    {
        $groups = [];

        // Get all step templates from published workflows grouped by workflow
        $stepTemplates = StepTemplate::with('workflowTemplate')
            ->whereHas('workflowTemplate', function ($query) {
                $query->where('status', 'published');
                $query->where('is_active', true);
            })
            ->orderBy('workflow_template_id')
            ->orderBy('position')
            ->get()
            ->groupBy('workflow_template_id');

        foreach ($stepTemplates as $workflowTemplateId => $steps) {
            $firstStep = $steps->first();
            $workflowName = $firstStep->workflowTemplate->name;
            $subjectType = class_basename($firstStep->workflowTemplate->subject_type);

            $permissions = [];

            // Add step permissions
            foreach ($steps as $stepTemplate) {
                $permissionName = $stepTemplate->getPermissionName();
                $label = $stepTemplate->label; // Use just the step label, not full permission label

                $permissions[$permissionName] = $label;
            }

            // Add status tab permissions for this workflow's model
            $modelClass = $firstStep->workflowTemplate->subject_type;
            $statusPermissions = static::getStatusTabPermissions($modelClass);

            $permissions = array_merge($permissions, $statusPermissions);

            $groups[$workflowTemplateId] = [
                'name' => $workflowName,
                'subject_type' => $subjectType,
                'permissions' => $permissions,
            ];
        }

        return $groups;
    }

    /**
     * Get status tab permissions for a model class.
     *
     * @param  class-string  $modelClass
     */
    protected static function getStatusTabPermissions(string $modelClass): array
    {
        $subjectType = class_basename($modelClass);
        $orgId = static::getOrgIdForRolePermission();

        return [
            "workflow_{$orgId}_{$subjectType}_view_all" => __('workflow.tab_permissions.view_all'),
            "workflow_{$orgId}_{$subjectType}_view_new" => __('workflow.tab_permissions.view_new'),
            "workflow_{$orgId}_{$subjectType}_view_completed" => __('workflow.tab_permissions.view_completed'),
            "workflow_{$orgId}_{$subjectType}_view_rejected" => __('workflow.tab_permissions.view_rejected'),
        ];
    }

    /**
     * Get organization ID for role permission naming.
     */
    protected static function getOrgIdForRolePermission(): string
    {
        try {
            $tenant = \Filament\Facades\Filament::getTenant();

            return $tenant?->id ?? 'global';
        } catch (\Exception $e) {
            return 'global';
        }
    }

    protected static function getWorkflowPermissionSections(array $workflowGroups): array
    {
        $sections = [];

        foreach ($workflowGroups as $workflowId => $group) {
            $sectionLabel = $group['name'];
            $permissionCount = count($group['permissions']);
            $stepCount = count($group['permissions']) - 4; // Subtract 4 status tab permissions

            $sections[] = Section::make($sectionLabel)
                ->description("Permissions for {$group['subject_type']} workflow ({$stepCount} steps + 4 status tabs)")
                ->compact()
                ->schema([
                    static::getCheckboxListFormComponent(
                        name: "workflow_{$workflowId}_permissions",
                        options: $group['permissions'],
                        searchable: false,
                        columns: static::shield()->getResourceCheckboxListColumns(),
                        columnSpan: static::shield()->getResourceCheckboxListColumnSpan()
                    ),
                ])
                ->columnSpan(static::shield()->getSectionColumnSpan())
                ->collapsible();
        }

        return $sections;
    }
}
