<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\ApiBaseController;
use App\Http\Requests\Api\IconSet\IndexRequest;
use App\Http\Requests\Api\IconSet\StoreRequest;
use App\Http\Requests\Api\IconSet\UpdateRequest;
use App\Http\Requests\Api\IconSet\DeleteRequest;
use App\Models\IconSet;
use App\Models\Icon;
use Examyou\RestAPI\Exceptions\ApiException;

class IconSetController extends ApiBaseController
{
    /**
     * The model associated with the controller.
     *
     * @var string
     */
    protected $model = IconSet::class;

    /**
     * The request class for index operations.
     *
     * @var string
     */
    protected $indexRequest = IndexRequest::class;

    /**
     * The request class for store operations.
     *
     * @var string
     */
    protected $storeRequest = StoreRequest::class;

    /**
     * The request class for update operations.
     *
     * @var string
     */
    protected $updateRequest = UpdateRequest::class;

    /**
     * The request class for delete operations.
     *
     * @var string
     */
    protected $deleteRequest = DeleteRequest::class;

    /**
     * Store icons temporarily before update
     *
     * @var array|null
     */
    protected $pendingIcons = null;

    /**
     * Modify index query
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    protected function modifyIndex($query)
    {
        $request = request();

        // Add icons count
        $query->withCount('icons');

        // Filter by active status if provided
        if ($request->has('is_active')) {
            $query->where('is_active', $request->input('is_active'));
        }

        // Order by sort_order
        $query->orderBy('sort_order');

        return $query;
    }

    /**
     * Hook: Before storing an icon set
     * Set sort_order and store pending icons
     *
     * @param IconSet $iconSet
     * @return IconSet
     */
    public function storing($iconSet)
    {
        // Set sort_order if not provided
        if (!isset($iconSet->sort_order)) {
            $iconSet->sort_order = IconSet::max('sort_order') + 1;
        }

        // Store icons for later processing and remove from request
        $request = request();
        if ($request->has('icons')) {
            $this->pendingIcons = $request->input('icons');
            $request->request->remove('icons');
        }

        return $iconSet;
    }

    /**
     * Hook: After storing an icon set
     * Process pending icons if provided
     *
     * @param IconSet $iconSet
     * @return IconSet
     */
    public function stored($iconSet)
    {
        // Handle icons that were stored during storing hook
        if ($this->pendingIcons !== null && is_array($this->pendingIcons)) {
            $this->syncIcons($iconSet, $this->pendingIcons);
            $this->pendingIcons = null;
        }

        return $iconSet;
    }

    /**
     * Hook: Before updating an icon set
     * Store pending icons and remove from request
     *
     * @param IconSet $iconSet
     * @return IconSet
     */
    public function updating($iconSet)
    {
        $request = request();

        // Store icons for later processing and remove from request
        if ($request->has('icons')) {
            $this->pendingIcons = $request->input('icons');
            $request->request->remove('icons');
        }

        return $iconSet;
    }

    /**
     * Hook: After updating an icon set
     * Process pending icons if provided
     *
     * @param IconSet $iconSet
     * @return IconSet
     */
    public function updated($iconSet)
    {
        // Handle icons that were stored during updating hook
        if ($this->pendingIcons !== null && is_array($this->pendingIcons)) {
            $this->syncIcons($iconSet, $this->pendingIcons);
            $this->pendingIcons = null;
        }

        return $iconSet;
    }

    /**
     * Sync icons for an icon set
     *
     * @param IconSet $iconSet
     * @param array $icons
     * @return void
     */
    protected function syncIcons(IconSet $iconSet, array $icons)
    {
        // Filter out empty values and trim whitespace
        $icons = array_filter(array_map('trim', $icons), function ($name) {
            return !empty($name);
        });

        // Remove duplicates (case-sensitive)
        $icons = array_unique($icons);

        // Delete existing icons for this set
        $iconSet->icons()->delete();

        // Insert new icons
        foreach ($icons as $iconName) {
            Icon::create([
                'icon_set_id' => $iconSet->id,
                'name' => $iconName,
                'full_name' => $iconSet->prefix . ':' . $iconName,
                'is_active' => true,
            ]);
        }
    }

    /**
     * Get icons for a specific icon set
     *
     * @param string $id
     * @return \Illuminate\Http\JsonResponse
     */
    public function getIcons($id)
    {
        $iconSetId = $this->getIdFromHash($id);
        $iconSet = IconSet::findOrFail($iconSetId);

        $icons = $iconSet->activeIcons()
            ->select('id', 'name', 'full_name', 'tags')
            ->get();

        return response()->json([
            'data' => $icons,
            'icon_set' => [
                'xid' => $iconSet->xid,
                'name' => $iconSet->name,
                'prefix' => $iconSet->prefix,
            ]
        ]);
    }

    /**
     * Get all icons for the icon picker (grouped by set)
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function getAllIcons()
    {
        $iconSets = IconSet::where('is_active', true)
            ->orderBy('sort_order')
            ->with(['activeIcons' => function ($query) {
                $query->select('id', 'icon_set_id', 'name', 'full_name');
            }])
            ->get();

        $result = $iconSets->map(function ($set) {
            return [
                'xid' => $set->xid,
                'name' => $set->name,
                'prefix' => $set->prefix,
                'icons' => $set->activeIcons->pluck('full_name'),
            ];
        });

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

    /**
     * Add icons to an existing icon set
     *
     * @param string $id
     * @return \Illuminate\Http\JsonResponse
     */
    public function addIcons($id)
    {
        // Check permission
        $user = auth('api')->user();
        if (!$user || !$user->ability('admin', 'icon_sets_create')) {
            throw new ApiException('Unauthorized: icon_sets_create permission required.', null, 403, 403);
        }

        $request = request();
        $iconSetId = $this->getIdFromHash($id);
        $iconSet = IconSet::findOrFail($iconSetId);

        $icons = $request->input('icons', []);
        $added = 0;

        foreach ($icons as $iconName) {
            // Check if icon already exists
            $exists = Icon::where('icon_set_id', $iconSet->id)
                ->where('name', $iconName)
                ->exists();

            if (!$exists) {
                Icon::create([
                    'icon_set_id' => $iconSet->id,
                    'name' => $iconName,
                    'full_name' => $iconSet->prefix . ':' . $iconName,
                    'is_active' => true,
                ]);
                $added++;
            }
        }

        return response()->json([
            'success' => true,
            'message' => "{$added} icons added successfully",
            'added_count' => $added,
        ]);
    }

    /**
     * Remove icons from an icon set
     *
     * @param string $id
     * @return \Illuminate\Http\JsonResponse
     */
    public function removeIcons($id)
    {
        // Check permission
        $user = auth('api')->user();
        if (!$user || !$user->ability('admin', 'icon_sets_delete')) {
            throw new ApiException('Unauthorized: icon_sets_delete permission required.', null, 403, 403);
        }

        $request = request();
        $iconSetId = $this->getIdFromHash($id);
        $iconSet = IconSet::findOrFail($iconSetId);

        $icons = $request->input('icons', []);

        $deleted = Icon::where('icon_set_id', $iconSet->id)
            ->whereIn('name', $icons)
            ->delete();

        return response()->json([
            'success' => true,
            'message' => "{$deleted} icons removed successfully",
            'removed_count' => $deleted,
        ]);
    }

    /**
     * Search icons across all sets
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function searchIcons()
    {
        $request = request();
        $query = $request->input('q', '');
        $iconSetId = $request->input('icon_set_id');

        if (strlen($query) < 2) {
            return response()->json(['data' => []]);
        }

        $iconsQuery = Icon::where('is_active', true)
            ->where(function ($q) use ($query) {
                $q->where('name', 'like', "%{$query}%")
                  ->orWhere('full_name', 'like', "%{$query}%");
            });

        if ($iconSetId) {
            $iconsQuery->where('icon_set_id', $this->getIdFromHash($iconSetId));
        }

        $icons = $iconsQuery->with('iconSet:id,name,prefix')
            ->limit(100)
            ->get(['id', 'icon_set_id', 'name', 'full_name']);

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

    /**
     * Bulk add icons to multiple icon sets
     * Request format: { items: [{ icon_set_prefix: 'lucide', icon_name: 'home' }, ...] }
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function bulkAddIcons()
    {
        // Check permission
        $user = auth('api')->user();
        if (!$user || !$user->ability('admin', 'icon_sets_create')) {
            throw new ApiException('Unauthorized: icon_sets_create permission required.', null, 403, 403);
        }

        $request = request();
        $items = $request->input('items', []);

        if (empty($items)) {
            return response()->json([
                'success' => false,
                'message' => 'No icons provided',
            ], 400);
        }

        $added = 0;
        $skipped = 0;
        $errors = [];

        foreach ($items as $item) {
            $prefix = $item['icon_set_prefix'] ?? null;
            $iconName = $item['icon_name'] ?? null;

            if (!$prefix || !$iconName) {
                $errors[] = "Missing prefix or icon name";
                continue;
            }

            // Find icon set by prefix
            $iconSet = IconSet::where('prefix', $prefix)->first();

            if (!$iconSet) {
                $errors[] = "Icon set '{$prefix}' not found";
                continue;
            }

            // Check if icon already exists
            $exists = Icon::where('icon_set_id', $iconSet->id)
                ->where('name', $iconName)
                ->exists();

            if ($exists) {
                $skipped++;
                continue;
            }

            // Create new icon
            Icon::create([
                'icon_set_id' => $iconSet->id,
                'name' => $iconName,
                'full_name' => $prefix . ':' . $iconName,
                'is_active' => true,
            ]);
            $added++;
        }

        return response()->json([
            'success' => true,
            'message' => "{$added} icon(s) added, {$skipped} skipped (already exist)",
            'added_count' => $added,
            'skipped_count' => $skipped,
            'errors' => $errors,
        ]);
    }

    /**
     * Get all active icon sets for dropdown
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function getIconSetsForDropdown()
    {
        $iconSets = IconSet::where('is_active', true)
            ->orderBy('sort_order')
            ->get(['id', 'name', 'prefix']);

        $result = $iconSets->map(function ($set) {
            return [
                'value' => $set->prefix,
                'label' => $set->name,
            ];
        });

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

    /**
     * Update sort order for icon sets
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function updateSortOrder()
    {
        // Check permission
        $user = auth('api')->user();
        if (!$user || !$user->ability('admin', 'icon_sets_edit')) {
            throw new ApiException('Unauthorized: icon_sets_edit permission required.', null, 403, 403);
        }

        $request = request();
        $items = $request->input('items', []);

        if (empty($items)) {
            return response()->json([
                'success' => false,
                'message' => 'No items provided',
            ], 400);
        }

        foreach ($items as $item) {
            $xid = $item['xid'] ?? null;
            $sortOrder = $item['sort_order'] ?? null;

            if (!$xid || $sortOrder === null) {
                continue;
            }

            $iconSetId = $this->getIdFromHash($xid);
            IconSet::where('id', $iconSetId)->update(['sort_order' => $sortOrder]);
        }

        return response()->json([
            'success' => true,
            'message' => 'Sort order updated successfully',
        ]);
    }
}
