<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Admin;
use App\Support\AdminProjectPermissionRegistry;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rule;
use Illuminate\View\View;

class SubAdminController extends Controller
{
    public function index(Request $request): View|RedirectResponse
    {
        if ($redirect = $this->ensureRoleColumns()) {
            return $redirect;
        }

        $query = trim((string) $request->query('q', ''));

        $superAdmins = Admin::query()
            ->where('is_super_admin', true)
            ->orderBy('id')
            ->get();

        $subAdmins = Admin::query()
            ->where('is_super_admin', false)
            ->when($query !== '', function ($builder) use ($query) {
                $builder->where(function ($inner) use ($query) {
                    $inner->where('name', 'like', "%{$query}%")
                        ->orWhere('email', 'like', "%{$query}%");
                });
            })
            ->orderByDesc('id')
            ->paginate(20)
            ->withQueryString();

        return view('admin.sub_admins.index', [
            'superAdmins' => $superAdmins,
            'subAdmins' => $subAdmins,
            'query' => $query,
            'projectDefinitions' => AdminProjectPermissionRegistry::projects(),
        ]);
    }

    public function create(): View|RedirectResponse
    {
        if ($redirect = $this->ensureRoleColumns()) {
            return $redirect;
        }

        return view('admin.sub_admins.create', [
            'projects' => AdminProjectPermissionRegistry::assignableProjects(),
        ]);
    }

    public function store(Request $request): RedirectResponse
    {
        if ($redirect = $this->ensureRoleColumns()) {
            return $redirect;
        }

        $validated = $request->validate([
            'name' => ['required', 'string', 'max:120'],
            'email' => ['required', 'string', 'email', 'max:190', 'unique:admins,email'],
            'password' => ['required', 'string', 'min:6', 'confirmed'],
            'project_permissions' => ['required', 'array', 'min:1'],
            'project_permissions.*' => ['string'],
        ]);

        $projectPermissions = AdminProjectPermissionRegistry::sanitizeProjectKeys($validated['project_permissions']);

        if (count($projectPermissions) === 0) {
            return back()
                ->withInput()
                ->withErrors(['project_permissions' => 'Select at least one valid project permission.']);
        }

        $admin = new Admin();
        $admin->name = $validated['name'];
        $admin->email = $validated['email'];
        $admin->password = Hash::make($validated['password']);
        $admin->is_super_admin = false;
        $admin->setProjectPermissions($projectPermissions);
        $admin->save();

        return redirect()
            ->route('admin.sub-admins.index')
            ->with('success', 'Sub-admin created successfully.');
    }

    public function edit(Admin $subAdmin): View|RedirectResponse
    {
        if ($redirect = $this->ensureRoleColumns()) {
            return $redirect;
        }
        $this->ensureSubAdminModel($subAdmin);

        return view('admin.sub_admins.edit', [
            'subAdmin' => $subAdmin,
            'projects' => AdminProjectPermissionRegistry::assignableProjects(),
            'selectedPermissions' => $subAdmin->assignedProjectPermissions(),
        ]);
    }

    public function update(Request $request, Admin $subAdmin): RedirectResponse
    {
        if ($redirect = $this->ensureRoleColumns()) {
            return $redirect;
        }
        $this->ensureSubAdminModel($subAdmin);

        $validated = $request->validate([
            'name' => ['required', 'string', 'max:120'],
            'email' => [
                'required',
                'string',
                'email',
                'max:190',
                Rule::unique('admins', 'email')->ignore($subAdmin->id),
            ],
            'password' => ['nullable', 'string', 'min:6', 'confirmed'],
            'project_permissions' => ['required', 'array', 'min:1'],
            'project_permissions.*' => ['string'],
        ]);

        $projectPermissions = AdminProjectPermissionRegistry::sanitizeProjectKeys($validated['project_permissions']);

        if (count($projectPermissions) === 0) {
            return back()
                ->withInput()
                ->withErrors(['project_permissions' => 'Select at least one valid project permission.']);
        }

        $subAdmin->name = $validated['name'];
        $subAdmin->email = $validated['email'];
        $subAdmin->setProjectPermissions($projectPermissions);

        if (!empty($validated['password'])) {
            $subAdmin->password = Hash::make($validated['password']);
        }

        $subAdmin->save();

        return redirect()
            ->route('admin.sub-admins.index')
            ->with('success', 'Sub-admin updated successfully.');
    }

    public function destroy(Admin $subAdmin): RedirectResponse
    {
        if ($redirect = $this->ensureRoleColumns()) {
            return $redirect;
        }
        $this->ensureSubAdminModel($subAdmin);

        if ((int) auth('admin')->id() === (int) $subAdmin->id) {
            return back()->with('error', 'You cannot delete your own account.');
        }

        $subAdmin->delete();

        return redirect()
            ->route('admin.sub-admins.index')
            ->with('success', 'Sub-admin deleted successfully.');
    }

    protected function ensureRoleColumns(): ?RedirectResponse
    {
        if (Admin::supportsRolePermissions()) {
            return null;
        }

        return redirect()
            ->route('admin.dashboard')
            ->with('error', 'Sub-admin setup incomplete. Please run migration first: php artisan migrate');
    }

    protected function ensureSubAdminModel(Admin $subAdmin): void
    {
        if (!$subAdmin->isSuperAdmin()) {
            return;
        }

        abort(404);
    }
}
