<?php

namespace Modules\GuidedTour\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Modules\GuidedTour\Entities\TourFlow;
use Modules\GuidedTour\Entities\TourMedia;
use Modules\GuidedTour\Entities\TourStep;

/**
 * Tour builder. Lets an admin author flows + steps and attach an image/video to
 * any step — no code needed to extend the tour. Media is stored on a private
 * disk and only ever reaches the browser through the signed MediaController.
 */
class TourAdminController extends Controller
{
    public function index()
    {
        $this->authorizeTour();

        $flows = TourFlow::with(['steps' => fn ($q) => $q->orderBy('sort_order')])
            ->orderBy('id')->get();

        return view('guidedtour::admin.index', ['flows' => $flows]);
    }

    /* ── Flows ──────────────────────────────────────────────────────────── */

    public function storeFlow(Request $request)
    {
        $this->authorizeTour();
        $data = $request->validate([
            'key'      => 'required|string|max:100|unique:tour_flows,key',
            'title'    => 'required|string|max:150',
            'vertical' => 'nullable|string|max:40',
        ]);
        $flow = TourFlow::create($data + ['is_active' => true, 'autostart_once' => true]);

        return response()->json(['ok' => true, 'flow' => $flow]);
    }

    public function updateFlow(Request $request, TourFlow $flow)
    {
        $this->authorizeTour();
        $data = $request->validate([
            'title'          => 'sometimes|string|max:150',
            'vertical'       => 'nullable|string|max:40',
            'is_active'      => 'sometimes|boolean',
            'autostart_once' => 'sometimes|boolean',
        ]);
        $flow->update($data);

        return response()->json(['ok' => true, 'flow' => $flow]);
    }

    public function destroyFlow(TourFlow $flow)
    {
        $this->authorizeTour();
        $flow->delete(); // cascades to steps

        return response()->json(['ok' => true]);
    }

    /* ── Steps ──────────────────────────────────────────────────────────── */

    public function storeStep(Request $request)
    {
        $this->authorizeTour();
        $data = $request->validate([
            'flow_id'         => 'required|integer|exists:tour_flows,id',
            'title'           => 'required|string|max:200',
            'route'           => 'nullable|string|max:255',
            'target_selector' => 'nullable|string|max:255',
            'body_html'       => 'nullable|string',
            'media_id'        => 'nullable|integer|exists:tour_media,id',
            'placement'       => 'nullable|string|max:20',
        ]);
        $data['sort_order'] = (int) (TourStep::where('flow_id', $data['flow_id'])->max('sort_order')) + 1;
        $step = TourStep::create($data);

        return response()->json(['ok' => true, 'step' => $step]);
    }

    public function updateStep(Request $request, TourStep $step)
    {
        $this->authorizeTour();
        $data = $request->validate([
            'title'           => 'sometimes|string|max:200',
            'route'           => 'nullable|string|max:255',
            'target_selector' => 'nullable|string|max:255',
            'body_html'       => 'nullable|string',
            'media_id'        => 'nullable|integer|exists:tour_media,id',
            'placement'       => 'nullable|string|max:20',
        ]);
        $step->update($data);

        return response()->json(['ok' => true, 'step' => $step]);
    }

    public function destroyStep(TourStep $step)
    {
        $this->authorizeTour();
        $step->delete();

        return response()->json(['ok' => true]);
    }

    public function reorderSteps(Request $request)
    {
        $this->authorizeTour();
        $data = $request->validate(['order' => 'required|array', 'order.*' => 'integer']);
        foreach ($data['order'] as $i => $stepId) {
            TourStep::where('id', $stepId)->update(['sort_order' => $i]);
        }

        return response()->json(['ok' => true]);
    }

    /* ── Media ──────────────────────────────────────────────────────────── */

    public function uploadMedia(Request $request)
    {
        $this->authorizeTour();
        $request->validate([
            'file' => 'required|file|max:51200|mimes:png,jpg,jpeg,webp,gif,svg,mp4,webm,ogg,mov',
        ]);

        $file = $request->file('file');
        $kind = str_starts_with((string) $file->getMimeType(), 'video') ? 'video' : 'image';
        $disk = config('guidedtour.media_disk', 'local');
        $path = $file->store(config('guidedtour.media_folder', 'tour-media'), $disk);

        $media = TourMedia::create([
            'kind'          => $kind,
            'disk'          => $disk,
            'path'          => $path,
            'mime'          => $file->getMimeType(),
            'original_name' => $file->getClientOriginalName(),
            'size'          => $file->getSize(),
        ]);

        return response()->json(['ok' => true, 'media' => ['id' => $media->id, 'kind' => $kind]]);
    }

    /* ── Guard ──────────────────────────────────────────────────────────── */

    protected function authorizeTour(): void
    {
        $user = Auth::user();
        abort_unless($user !== null, 403);

        $perm = config('guidedtour.author_permission', 'guidedtour.manage');

        // Business owners pass via the app's Gate::before superadmin check; other
        // users need the explicit permission.
        $isOwner = false;
        try {
            $bizId = $user->business_id;
            $isOwner = $bizId && DB::table('business')->where('id', $bizId)->where('owner_id', $user->id)->exists();
        } catch (\Throwable) {
            // ignore
        }

        abort_unless($isOwner || $user->can($perm), 403);
    }
}
