<?php

namespace App\Http\Controllers\Mentorship;

use App\Http\Controllers\Controller;
use App\Models\Mentorship\Category;
use App\Services\Mentorship\CategoryService;
use App\Http\Requests\Mentorship\CategoryRequest;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;

class CategoryController extends Controller
{
    protected CategoryService $categoryService;

    public function __construct(CategoryService $categoryService)
    {
        $this->categoryService = $categoryService;
    }

    /**
     * Display a listing of categories.
     */
    public function index(Request $request)
    {
        abort_unless(auth()->user()->can('view mentorship categories'), 403);

        $filters = [
            'is_active' => $request->get('is_active'),
            'search' => $request->get('search'),
            'sort_by' => $request->get('sort_by', 'sort_order'),
            'sort_order' => $request->get('sort_order', 'asc'),
        ];

        $categories = Category::with(['parent', 'children'])
            ->withCount(['programmes', 'activeProgrammes'])
            ->when($filters['is_active'] !== null, fn($q) => $q->where('is_active', $filters['is_active']))
            ->when($filters['search'], function ($q) use ($filters) {
                $q->where('name', 'like', '%' . $filters['search'] . '%')
                    ->orWhere('description', 'like', '%' . $filters['search'] . '%');
            })
            ->orderBy($filters['sort_by'], $filters['sort_order'])
            ->paginate(15);

        // Get tree structure for display
        $tree = $this->categoryService->getTree();

        return view('mentorship.categories.index', compact('categories', 'tree', 'filters'));
    }

    /**
     * Show the form for creating a new category.
     */
    public function create()
    {
        abort_unless(auth()->user()->can('create mentorship categories'), 403);

        $parentCategories = Category::parents()
            ->active()
            ->ordered()
            ->get();

        return view('mentorship.categories.create', compact('parentCategories'));
    }

    /**
     * Store a newly created category.
     */
    public function store(CategoryRequest $request)
    {
        abort_unless(auth()->user()->can('create mentorship categories'), 403);

        try {
            $category = $this->categoryService->create($request->validated());

            return redirect()
                ->route('mentorship.categories.index')
                ->with('success', 'Category created successfully.');
        } catch (\Exception $e) {
            return back()
                ->withInput()
                ->withErrors(['error' => $e->getMessage()]);
        }
    }

    /**
     * Display the specified category.
     */
    public function show(Category $category)
    {
        abort_unless(auth()->user()->can('view mentorship categories'), 403);

        $category->load([
            'parent',
            'children' => fn($q) => $q->withCount(['programmes'])->orderBy('sort_order'),
            'programmes' => fn($q) => $q->withCount(['applications', 'assignments'])->latest()->limit(10),
        ]);

        $statistics = $this->categoryService->getStatistics($category);

        return view('mentorship.categories.show', compact('category', 'statistics'));
    }

    /**
     * Show the form for editing the specified category.
     */
    public function edit(Category $category)
    {
        abort_unless(auth()->user()->can('edit mentorship categories'), 403);

        $parentCategories = Category::parents()
            ->active()
            ->where('id', '!=', $category->id)
            ->ordered()
            ->get();

        return view('mentorship.categories.edit', compact('category', 'parentCategories'));
    }

    /**
     * Update the specified category.
     */
    public function update(CategoryRequest $request, Category $category)
    {
        abort_unless(auth()->user()->can('edit mentorship categories'), 403);

        try {
            $this->categoryService->update($category, $request->validated());

            return redirect()
                ->route('mentorship.categories.show', $category)
                ->with('success', 'Category updated successfully.');
        } catch (\Exception $e) {
            return back()
                ->withInput()
                ->withErrors(['error' => $e->getMessage()]);
        }
    }

    /**
     * Remove the specified category.
     */
    public function destroy(Category $category)
    {
        abort_unless(auth()->user()->can('delete mentorship categories'), 403);

        try {
            $this->categoryService->delete($category);

            return redirect()
                ->route('mentorship.categories.index')
                ->with('success', 'Category deleted successfully.');
        } catch (\Exception $e) {
            return back()->withErrors(['error' => $e->getMessage()]);
        }
    }

    /**
     * Activate a category.
     */
    public function activate(Category $category): JsonResponse
    {
        abort_unless(auth()->user()->can('edit mentorship categories'), 403);

        $this->categoryService->activate($category);

        return response()->json([
            'success' => true,
            'message' => 'Category activated successfully.',
        ]);
    }

    /**
     * Deactivate a category.
     */
    public function deactivate(Category $category): JsonResponse
    {
        abort_unless(auth()->user()->can('edit mentorship categories'), 403);

        $this->categoryService->deactivate($category);

        return response()->json([
            'success' => true,
            'message' => 'Category deactivated successfully.',
        ]);
    }

    /**
     * Get categories as tree (AJAX).
     */
    public function getTree(): JsonResponse
    {
        $tree = $this->categoryService->getTree(true);

        return response()->json([
            'success' => true,
            'data' => $tree,
        ]);
    }

    /**
     * Get categories for select dropdown (AJAX).
     */
    public function getForSelect(Request $request): JsonResponse
    {
        $query = Category::active()->ordered();

        if ($request->has('programme_id')) {
            // Get categories associated with the programme
            $programmeCategories = \App\Models\Mentorship\Programme::find($request->programme_id)
                ?->categories()
                ->pluck('mentorship_categories.id')
                ->toArray();
            
            if (!empty($programmeCategories)) {
                $query->whereIn('id', $programmeCategories);
            }
        }

        $categories = $query->get(['id', 'name', 'parent_id']);

        return response()->json([
            'success' => true,
            'data' => $categories,
        ]);
    }

    /**
     * Move category to new parent.
     */
    public function move(Request $request, Category $category): JsonResponse
    {
        abort_unless(auth()->user()->can('edit mentorship categories'), 403);

        $request->validate([
            'parent_id' => 'nullable|exists:mentorship_categories,id',
        ]);

        try {
            $this->categoryService->moveTo($category, $request->parent_id);

            return response()->json([
                'success' => true,
                'message' => 'Category moved successfully.',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 422);
        }
    }

    /**
     * Update sort order.
     */
    public function updateSortOrder(Request $request): JsonResponse
    {
        abort_unless(auth()->user()->can('edit mentorship categories'), 403);

        $request->validate([
            'order' => 'required|array',
            'order.*' => 'integer|exists:mentorship_categories,id',
        ]);

        try {
            $this->categoryService->updateSortOrder($request->order);

            return response()->json([
                'success' => true,
                'message' => 'Sort order updated successfully.',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 422);
        }
    }
}
