<?php

namespace App\Http\Controllers\Admin;

use App\Helpers\TranslationHelper;
use App\Http\Controllers\Controller;
use App\Models\Language;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Response;
use Illuminate\View\View;

/**
 * Admin Translation Editor — manual workflow for translating UI strings
 * into any registered language without FTP / SSH access to the server.
 *
 * Endpoints:
 *   GET   /admin/translations              → editor (defaults to first non-en lang)
 *   GET   /admin/translations?lang=fr      → editor for French
 *   POST  /admin/translations              → save partial edits (AJAX)
 *   POST  /admin/translations/import       → upload/paste JSON to replace file
 *   GET   /admin/translations/export       → download lang/{code}.json
 */
class TranslationController extends Controller
{
    /**
     * Render the editor. The string table is built server-side here so the
     * page is usable without JS — Alpine just adds filter + autosave on top.
     */
    public function index(Request $request): View
    {
        $languages = Language::orderBy('sort_order')->orderBy('name')->get();
        $code = (string) $request->query('lang', '');

        if ($code === '' || !TranslationHelper::isValidLocale($code)) {
            // Pick the first non-English language so the editor lands on a
            // useful default. If only en exists, fall through to en (admin
            // editing en is unusual but not forbidden).
            $code = optional(
                $languages->firstWhere(fn ($l) => $l->code !== 'en')
                    ?: $languages->first()
            )->code ?? 'en';
        }

        return view('admin.translations.index', [
            'languages' => $languages,
            'code'      => $code,
            'rows'      => TranslationHelper::buildEditorRows($code),
            'stats'     => TranslationHelper::getStats($code),
        ]);
    }

    /**
     * Save a partial edit batch. Request shape:
     *   { code: "fr", translations: { "key": "valeur", ... } }
     *
     * Returns the refreshed stats so the progress bar can re-render
     * without a full page reload.
     */
    public function save(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'code' => ['required', 'string', 'max:16'],
            'translations' => ['required', 'array'],
            'translations.*' => ['nullable', 'string', 'max:10000'],
        ]);

        if (!TranslationHelper::isValidLocale($validated['code'])) {
            return response()->json(['ok' => false, 'message' => 'Invalid locale code.'], 422);
        }

        try {
            $stats = TranslationHelper::saveTranslations(
                $validated['code'],
                $validated['translations'] ?? []
            );
        } catch (\Throwable $e) {
            return response()->json(['ok' => false, 'message' => $e->getMessage()], 500);
        }

        return response()->json([
            'ok' => true,
            'stats' => $stats,
            'message' => __('Translations saved.'),
        ]);
    }

    /**
     * Bulk import — replace (merge) all translations from an uploaded
     * `.json` file or a pasted JSON blob. The form accepts EITHER field.
     */
    public function import(Request $request): RedirectResponse
    {
        $request->validate([
            'code' => ['required', 'string', 'max:16'],
            'json_file' => ['nullable', 'file', 'mimetypes:application/json,text/plain', 'max:5120'],
            'json_text' => ['nullable', 'string', 'max:5000000'],
        ]);

        if (!TranslationHelper::isValidLocale($request->input('code'))) {
            return back()->with('error', __('Invalid locale code.'));
        }

        // Prefer the uploaded file if both are provided (matches user intent
        // — uploading is the more explicit action).
        $payload = null;
        if ($request->hasFile('json_file')) {
            $payload = file_get_contents($request->file('json_file')->getRealPath());
        } elseif ($request->filled('json_text')) {
            $payload = (string) $request->input('json_text');
        }

        if (!$payload) {
            return back()->with('error', __('Provide either a JSON file or paste JSON text.'));
        }

        try {
            $result = TranslationHelper::importJson($request->input('code'), $payload);
        } catch (\Throwable $e) {
            return back()->with('error', $e->getMessage());
        }

        return redirect()
            ->route('admin.translations.index', ['lang' => $request->input('code')])
            ->with('success', __('Imported :imported strings. :ignored unrecognized keys ignored.', [
                'imported' => $result['imported'],
                'ignored'  => $result['ignored'],
            ]));
    }

    /**
     * Stream the raw lang/{code}.json so admins (or external translators
     * working offline) can grab a copy. We always stream the on-disk file
     * — not a generated version — so what they download matches exactly
     * what Laravel will resolve at runtime.
     */
    public function export(Request $request, string $code)
    {
        if (!TranslationHelper::isValidLocale($code)) abort(404);

        $path = TranslationHelper::langPath($code);
        if (!file_exists($path)) abort(404);

        return Response::download($path, $code . '.json', [
            'Content-Type' => 'application/json',
        ]);
    }
}
