<?php

namespace App\Workflows\Actions;

use App\Workflows\Models\WorkflowTemplate;
use App\Workflows\Traits\HasWorkflow;
use Filament\Schemas\Components\Tabs\Tab;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Auth;

class WorkflowTabs
{
    /**
     * Get workflow-related tabs for a Filament List page.
     *
     * @param  class-string<Model&HasWorkflow>  $modelClass  The model class that has workflow
     * @return array<string, Tab>
     */
    public static function getTabs(string $modelClass): array
    {
        $tabs = [];

        // Add "All" tab - check permission
        if (static::canViewAllTab($modelClass)) {
            $tabs['all'] = Tab::make(__('common.all'))
                ->badge($modelClass::count());
        }

        // Add "New" tab for records without workflow - check permission
        if (static::canViewNewTab($modelClass)) {
            $tabs['no_workflow'] = Tab::make(__('workflow.status.new'))
                ->badge(function () use ($modelClass) {
                    return $modelClass::whereDoesntHave('workflowInstance')->count();
                })
                ->modifyQueryUsing(function (Builder $query) {
                    return $query->whereDoesntHave('workflowInstance');
                });
        }

        // Get the active published workflow template for the model
        $activeTemplate = WorkflowTemplate::where('subject_type', $modelClass)
            ->where('is_active', true)
            ->where('status', 'published')
            ->with('stepTemplates')
            ->first();

        if ($activeTemplate) {
            // Add tabs for each workflow step - check permissions
            foreach ($activeTemplate->stepTemplates as $stepTemplate) {
                // Check if user has permission to view this step tab
                if (static::canViewStepTab($stepTemplate)) {
                    $stepKey = $stepTemplate->system_key;
                    $stepLabel = $stepTemplate->label;

                    // Create unique tab key by combining system_key with step position or ID
                    // This handles multiple steps with same system_key
                    $tabKey = $stepKey.'_'.$stepTemplate->position;

                    $tabs[$tabKey] = Tab::make($stepLabel)
                        ->badge(function () use ($modelClass, $stepTemplate) {
                            return static::getStepCount($modelClass, $stepTemplate);
                        })
                        ->modifyQueryUsing(function (Builder $query) use ($modelClass, $stepTemplate) {
                            return static::filterByStep($query, $modelClass, $stepTemplate);
                        });
                }
            }
        }

        // Add "Completed" tab - check permission
        if (static::canViewCompletedTab($modelClass)) {
            $tabs['completed'] = Tab::make(__('workflow.states.completed'))
                ->badge(function () use ($modelClass) {
                    return $modelClass::whereHas('workflowInstance', function (Builder $query) {
                        $query->where('state', 'completed');
                    })->count();
                })
                ->modifyQueryUsing(function (Builder $query) {
                    return $query->whereHas('workflowInstance', function (Builder $query) {
                        $query->where('state', 'completed');
                    });
                });
        }

        // Add "Rejected" tab - check permission
        if (static::canViewRejectedTab($modelClass)) {
            $tabs['rejected'] = Tab::make(__('workflow.states.rejected'))
                ->badge(function () use ($modelClass) {
                    return $modelClass::whereHas('workflowInstance', function (Builder $query) {
                        $query->where('state', 'rejected');
                    })->count();
                })
                ->modifyQueryUsing(function (Builder $query) {
                    return $query->whereHas('workflowInstance', function (Builder $query) {
                        $query->where('state', 'rejected');
                    });
                });
        }

        return $tabs;
    }

    /**
     * Count records currently on a specific workflow step.
     *
     * @param  class-string<Model&HasWorkflow>  $modelClass
     * @param  \App\Workflows\Models\StepTemplate  $stepTemplate
     */
    protected static function getStepCount(string $modelClass, $stepTemplate): int
    {
        return $modelClass::whereHas('workflowInstance', function (Builder $query) {
            $query->where('state', 'running');
        })->get()->filter(function ($record) use ($stepTemplate) {
            $currentStep = $record->currentStep();

            // Match both system_key and position to identify the specific step
            return $currentStep
                && $currentStep->getSystemKey() === $stepTemplate->system_key
                && ($currentStep->step_template_snapshot['position'] ?? null) == $stepTemplate->position;
        })->count();
    }

    /**
     * Filter query to show only records currently on a specific workflow step.
     *
     * @param  class-string<Model&HasWorkflow>  $modelClass
     * @param  \App\Workflows\Models\StepTemplate  $stepTemplate
     */
    protected static function filterByStep(Builder $query, string $modelClass, $stepTemplate): Builder
    {
        // Get IDs of records where current step matches this specific step
        $recordIds = $modelClass::whereHas('workflowInstance', function (Builder $query) {
            $query->where('state', 'running');
        })->get()->filter(function ($record) use ($stepTemplate) {
            $currentStep = $record->currentStep();

            // Match both system_key and position to identify the specific step
            return $currentStep
                && $currentStep->getSystemKey() === $stepTemplate->system_key
                && ($currentStep->step_template_snapshot['position'] ?? null) == $stepTemplate->position;
        })->pluck('id');

        return $query->whereIn('id', $recordIds);
    }

    /**
     * Get workflow-related tabs with custom options.
     *
     * @param  class-string<Model&HasWorkflow>  $modelClass
     * @return array<string, Tab>
     */
    public static function getTabsWithOptions(string $modelClass, array $options = []): array
    {
        $tabs = static::getTabs($modelClass);

        // Apply custom options
        if (isset($options['exclude']) && is_array($options['exclude'])) {
            foreach ($options['exclude'] as $tabKey) {
                unset($tabs[$tabKey]);
            }
        }

        if (isset($options['include']) && is_array($options['include'])) {
            $tabs = array_intersect_key($tabs, array_flip($options['include']));
        }

        return $tabs;
    }

    /**
     * Get only step-specific tabs (excludes All, Completed, Rejected, No Workflow).
     *
     * @param  class-string<Model&HasWorkflow>  $modelClass
     * @return array<string, Tab>
     */
    public static function getStepTabs(string $modelClass): array
    {
        return static::getTabsWithOptions($modelClass, [
            'exclude' => ['all', 'completed', 'rejected', 'no_workflow'],
        ]);
    }

    /**
     * Get only status tabs (All, Completed, Rejected, No Workflow).
     *
     * @param  class-string<Model&HasWorkflow>  $modelClass
     * @return array<string, Tab>
     */
    public static function getStatusTabs(string $modelClass): array
    {
        $allTabs = static::getTabs($modelClass);
        $stepTabs = static::getStepTabs($modelClass);

        return array_diff_key($allTabs, $stepTabs);
    }

    /**
     * Check if user can view the "All" tab for a model.
     *
     * @param  class-string<Model&HasWorkflow>  $modelClass
     */
    protected static function canViewAllTab(string $modelClass): bool
    {
        $permission = static::getAllTabPermission($modelClass);

        return Auth::check() && Auth::user()->can($permission);
    }

    /**
     * Check if user can view the "New" tab for a model.
     *
     * @param  class-string<Model&HasWorkflow>  $modelClass
     */
    protected static function canViewNewTab(string $modelClass): bool
    {
        $permission = static::getNewTabPermission($modelClass);

        return Auth::check() && Auth::user()->can($permission);
    }

    /**
     * Check if user can view the "Completed" tab for a model.
     *
     * @param  class-string<Model&HasWorkflow>  $modelClass
     */
    protected static function canViewCompletedTab(string $modelClass): bool
    {
        $permission = static::getCompletedTabPermission($modelClass);

        return Auth::check() && Auth::user()->can($permission);
    }

    /**
     * Check if user can view the "Rejected" tab for a model.
     *
     * @param  class-string<Model&HasWorkflow>  $modelClass
     */
    protected static function canViewRejectedTab(string $modelClass): bool
    {
        $permission = static::getRejectedTabPermission($modelClass);

        return Auth::check() && Auth::user()->can($permission);
    }

    /**
     * Check if user can view a specific step tab.
     *
     * @param  \App\Workflows\Models\StepTemplate  $stepTemplate
     */
    protected static function canViewStepTab($stepTemplate): bool
    {
        $permission = $stepTemplate->getPermissionName();

        return Auth::check() && Auth::user()->can($permission);
    }

    /**
     * Get the permission name for viewing the "All" tab.
     *
     * @param  class-string<Model&HasWorkflow>  $modelClass
     */
    protected static function getAllTabPermission(string $modelClass): string
    {
        $subjectType = class_basename($modelClass);
        $orgId = static::getOrgIdForPermission();

        return "workflow_{$orgId}_{$subjectType}_view_all";
    }

    /**
     * Get the permission name for viewing the "New" tab.
     *
     * @param  class-string<Model&HasWorkflow>  $modelClass
     */
    protected static function getNewTabPermission(string $modelClass): string
    {
        $subjectType = class_basename($modelClass);
        $orgId = static::getOrgIdForPermission();

        return "workflow_{$orgId}_{$subjectType}_view_new";
    }

    /**
     * Get the permission name for viewing the "Completed" tab.
     *
     * @param  class-string<Model&HasWorkflow>  $modelClass
     */
    protected static function getCompletedTabPermission(string $modelClass): string
    {
        $subjectType = class_basename($modelClass);
        $orgId = static::getOrgIdForPermission();

        return "workflow_{$orgId}_{$subjectType}_view_completed";
    }

    /**
     * Get the permission name for viewing the "Rejected" tab.
     *
     * @param  class-string<Model&HasWorkflow>  $modelClass
     */
    protected static function getRejectedTabPermission(string $modelClass): string
    {
        $subjectType = class_basename($modelClass);
        $orgId = static::getOrgIdForPermission();

        return "workflow_{$orgId}_{$subjectType}_view_rejected";
    }

    /**
     * Get the organization ID for permission naming.
     */
    protected static function getOrgIdForPermission(): string
    {
        // Use similar logic to StepTemplate for consistency
        try {
            $tenant = \Filament\Facades\Filament::getTenant();

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