<?php

namespace App\Http\Controllers\Dashboard;

use App\Http\Controllers\Controller;
use App\Models\AdminAuditLog;
use App\Services\EmojiCatalog\EmojiCatalogService;
use App\Services\System\SettingsService;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;
use Throwable;

class AdminEmojiCatalogController extends Controller
{
    public function __construct(
        private readonly EmojiCatalogService $catalog,
        private readonly SettingsService $settings
    ) {}

    public function index(Request $request): View
    {
        $q = trim((string) $request->query('q', ''));
        $items = $this->listItems($q);

        return view('dashboard.admin.catalog', [
            'items' => $items,
            'totalRows' => (int) DB::table('emojis')->count(),
            'snapshots' => $this->catalog->listSnapshots(),
            'activeVersion' => (string) $this->settings->get('emoji_dataset_active_version', ''),
            'activePath' => (string) $this->settings->get('emoji_dataset_active_path', ''),
            'filters' => ['q' => $q],
        ]);
    }

    public function create(Request $request): View
    {
        return view('dashboard.admin.catalog-form', [
            'mode' => 'create',
            'selected' => null,
        ]);
    }

    public function edit(Request $request, int $emojiId): View
    {
        $selected = $this->catalog->findItem($emojiId);
        abort_if($selected === null, 404);

        return view('dashboard.admin.catalog-form', [
            'mode' => 'edit',
            'selected' => $selected,
        ]);
    }

    public function store(Request $request): RedirectResponse
    {
        $validated = $this->validateItemPayload($request);
        unset($validated['emoji_id']);

        try {
            $emojiId = $this->catalog->saveItem($validated);
        } catch (Throwable $e) {
            report($e);

            return back()->withInput()->with('error', $e->getMessage() ?: 'Failed to create catalog item.');
        }

        $this->logAdminAction($request, 'emoji_catalog_create', [
            'emoji_id' => $emojiId,
            'slug' => $validated['slug'],
        ]);

        return redirect()->route('dashboard.admin.catalog.edit', ['emojiId' => $emojiId])
            ->with('status', 'Catalog item created.');
    }

    public function update(Request $request, int $emojiId): RedirectResponse
    {
        $validated = $this->validateItemPayload($request);
        $validated['emoji_id'] = $emojiId;

        try {
            $savedId = $this->catalog->saveItem($validated);
        } catch (Throwable $e) {
            report($e);

            return back()
                ->withInput()
                ->with('error', $e->getMessage() ?: 'Failed to save catalog item.');
        }

        $this->logAdminAction($request, 'emoji_catalog_upsert', [
            'emoji_id' => $savedId,
            'slug' => $validated['slug'],
        ]);

        return back()->with('status', 'Catalog item updated.');
    }

    public function destroy(Request $request, int $emojiId): RedirectResponse
    {
        try {
            $selected = $this->catalog->findItem($emojiId);
            $this->catalog->deleteItem($emojiId);
        } catch (Throwable $e) {
            report($e);

            return back()->with('error', $e->getMessage() ?: 'Failed to delete catalog item.');
        }

        $this->logAdminAction($request, 'emoji_catalog_delete', [
            'emoji_id' => $emojiId,
            'slug' => (string) ($selected['slug'] ?? ''),
        ]);

        return back()->with('status', 'Catalog item deleted.');
    }

    public function importCurrentJson(Request $request): RedirectResponse
    {
        $path = (string) config('dewemoji.data_path');
        try {
            $result = $this->catalog->importFromDataFile($path);
        } catch (Throwable $e) {
            report($e);

            return back()->with('error', $e->getMessage() ?: 'Failed to import dataset.');
        }

        $this->logAdminAction($request, 'emoji_catalog_import_json', [
            'path' => $path,
            'total' => $result['total'],
            'imported' => $result['imported'],
            'skipped' => $result['skipped'],
        ]);

        return back()->with(
            'status',
            "Import completed. New rows: {$result['imported']}, skipped existing: {$result['skipped']}, total scanned: {$result['total']}."
        );
    }

    public function publish(Request $request): RedirectResponse
    {
        try {
            $result = $this->catalog->publishSnapshot($request->user()?->email);
        } catch (Throwable $e) {
            report($e);

            return back()->with('error', $e->getMessage() ?: 'Failed to publish snapshot.');
        }

        $this->logAdminAction($request, 'emoji_catalog_publish', $result);

        return back()->with('status', "Published snapshot version {$result['version']} ({$result['count']} emojis).");
    }

    public function activateSnapshot(Request $request): RedirectResponse
    {
        $validated = $request->validate([
            'snapshot' => 'required|string',
        ]);

        try {
            $result = $this->catalog->activateSnapshot($validated['snapshot'], $request->user()?->email);
        } catch (Throwable $e) {
            report($e);

            return back()->with('error', $e->getMessage() ?: 'Failed to activate snapshot.');
        }

        $this->logAdminAction($request, 'emoji_catalog_activate_snapshot', $result);

        return back()->with('status', "Snapshot {$result['version']} is now active.");
    }

    /**
     * @param  array<string,mixed>  $payload
     */
    private function logAdminAction(Request $request, string $action, array $payload): void
    {
        $admin = $request->user();
        if (! $admin) {
            return;
        }

        AdminAuditLog::create([
            'admin_id' => $admin->id,
            'admin_email' => $admin->email,
            'action' => $action,
            'payload' => $payload,
            'ip_address' => $request->ip(),
        ]);
    }

    private function listItems(string $q): LengthAwarePaginator
    {
        $itemsQuery = DB::table('emojis')->select([
            'emoji_id',
            'slug',
            'emoji_char as emoji',
            'name',
            'category',
            'subcategory',
            'updated_at',
        ]);

        if ($q !== '') {
            $itemsQuery->where(function ($sub) use ($q): void {
                $sub->where('slug', 'like', '%'.$q.'%')
                    ->orWhere('name', 'like', '%'.$q.'%')
                    ->orWhere('category', 'like', '%'.$q.'%')
                    ->orWhere('subcategory', 'like', '%'.$q.'%');
            });
        }

        return $itemsQuery->orderBy('emoji_id')->paginate(30)->withQueryString();
    }

    /**
     * @return array<string,mixed>
     */
    private function validateItemPayload(Request $request): array
    {
        return $request->validate([
            'emoji_id' => 'nullable|integer',
            'slug' => 'required|string|max:160',
            'emoji' => 'nullable|string|max:32',
            'name' => 'required|string|max:200',
            'category' => 'nullable|string|max:120',
            'subcategory' => 'nullable|string|max:120',
            'aliases' => 'nullable|string',
            'shortcodes' => 'nullable|string',
            'alt_shortcodes' => 'nullable|string',
            'keywords_en' => 'nullable|string',
            'keywords_id' => 'nullable|string',
            'description' => 'nullable|string',
            'unified' => 'nullable|string|max:120',
            'default_presentation' => 'nullable|string|max:16',
            'version' => 'nullable|string|max:16',
            'supports_skin_tone' => 'nullable|boolean',
            'permalink' => 'nullable|string|max:255',
            'title' => 'nullable|string|max:255',
            'meta_title' => 'nullable|string|max:255',
            'meta_description' => 'nullable|string|max:255',
        ]);
    }
}
