<?php

namespace Modules\Bms\Http\Controllers\Api;

use Illuminate\Http\Request;
use Modules\Bms\Entities\BmsHall;
use Modules\Bms\Entities\BmsLead;
use Modules\Bms\Entities\BmsLeadHall;
use Modules\Bms\Entities\BmsWizardSession;
use Modules\Bms\Services\Contracts\ContactServiceContract;
use Modules\Bms\Services\Notifications\NotificationRouter;

/**
 * Anonymous QA wizard (client funnel). A session is created at step 1 and
 * saved server-side after every step (progressive capture). Once contact
 * details are captured the session converts to an ERP contact + a BMS lead.
 *
 * No bearer token — the unguessable session token is the identity. Public
 * routes are rate-limited + honeypot-guarded in api.php.
 */
class WizardController extends ApiController
{
    /** Start an anonymous session. */
    public function start(Request $request)
    {
        if (! empty($request->input('website'))) {
            return $this->fail('Rejected', 422); // honeypot tripped
        }

        $session = BmsWizardSession::create([
            'business_id'      => $this->publicBusinessId($request),
            'status'           => 'incomplete',
            'current_step'     => 1,
            'ip'               => $request->ip(),
            'user_agent'       => substr((string) $request->userAgent(), 0, 255),
            'last_activity_at' => now(),
        ]);

        return $this->ok(['token' => $session->token, 'session' => $this->present($session)]);
    }

    /** Fetch a session by token. */
    public function show(string $token)
    {
        $session = $this->resolve($token);
        return $session ? $this->ok(['session' => $this->present($session)]) : $this->fail('Not found', 404);
    }

    /**
     * Save a step's answers (progressive capture). Auto-converts to an ERP
     * contact + lead the first time contact phone/email is provided.
     */
    public function step(Request $request, ContactServiceContract $contacts, string $token)
    {
        $session = $this->resolve($token);
        if (! $session) {
            return $this->fail('Not found', 404);
        }

        $data = $request->validate([
            'current_step'     => 'nullable|integer|min:1|max:12',
            'contact_name'     => 'nullable|string|max:191',
            'contact_phone'    => 'nullable|string|max:30',
            'contact_whatsapp' => 'nullable|string|max:30',
            'contact_email'    => 'nullable|email|max:191',
            'source'           => 'nullable|string|max:40',
            'source_detail'    => 'nullable|string|max:191',
            'event_type'       => 'nullable|string|max:60',
            'attendees'        => 'nullable|integer|min:0',
            'fnb_level'        => 'nullable|in:high_tea,drinks_only,set_menu,open_buffet,custom',
            'venue_preference' => 'nullable|in:open,closed,both',
            'candidate_dates'  => 'nullable|array',
            'candidate_dates.*'=> 'date',
            'budget_min'       => 'nullable|numeric|min:0',
            'budget_max'       => 'nullable|numeric|min:0',
            'area_id'          => 'nullable|integer',
        ]);

        $session->fill($data);
        $session->answers = array_merge((array) $session->answers, $data);
        $session->last_activity_at = now();

        // Convert to ERP contact + lead once we have a way to reach them.
        if ($session->contact_id === null && (! empty($session->contact_phone) || ! empty($session->contact_email))) {
            $this->convertToLead($session, $contacts);
        } elseif ($session->lead_id) {
            $this->syncLead($session);
        }

        $session->save();

        return $this->ok(['session' => $this->present($session)]);
    }

    /**
     * Mark the wizard complete → lead stage "Qualified — Awaiting Contact".
     * (Sales-agent notification is wired through NotificationService in M7.)
     */
    public function complete(Request $request, ContactServiceContract $contacts, string $token)
    {
        $session = $this->resolve($token);
        if (! $session) {
            return $this->fail('Not found', 404);
        }

        if ($session->contact_id === null && (! empty($session->contact_phone) || ! empty($session->contact_email))) {
            $this->convertToLead($session, $contacts);
        }

        $session->status = $session->lead_id ? 'converted' : 'complete';
        if ($session->lead_id) {
            $lead = BmsLead::find($session->lead_id);
            if ($lead) {
                $lead->stage = 'qualified_awaiting_contact';
                $lead->last_activity_at = now();
                $lead->save();
            }
        }
        $session->save();

        return $this->ok(['session' => $this->present($session)]);
    }

    /** Persist the client's selected halls (each with package + add-ons). */
    public function select(Request $request, string $token)
    {
        $session = $this->resolve($token);
        if (! $session) {
            return $this->fail('Not found', 404);
        }
        if (! $session->lead_id) {
            return $this->fail('Capture contact details first', 422);
        }

        $payload = $request->validate([
            'halls'                => 'required|array|min:1',
            'halls.*.hall_id'      => 'required|integer',
            'halls.*.package_id'   => 'nullable|integer',
            'halls.*.addons'       => 'nullable|array',
            'halls.*.package_items'=> 'nullable|array',
            'halls.*.score'        => 'nullable|integer',
        ]);

        BmsLeadHall::where('lead_id', $session->lead_id)->delete();
        foreach ($payload['halls'] as $h) {
            BmsLeadHall::create([
                'business_id'   => $session->business_id,
                'lead_id'       => $session->lead_id,
                'hall_id'       => $h['hall_id'],
                'package_id'    => $h['package_id'] ?? null,
                'addons'        => $h['addons'] ?? null,
                'package_items' => $h['package_items'] ?? null,
                'score'         => $h['score'] ?? null,
            ]);
        }

        // WhatsApp the client a summary of their initial choice (best effort).
        $this->notifySelection($session, $payload['halls']);

        return $this->ok(['session' => $this->present($session), 'selected' => count($payload['halls'])]);
    }

    // ---- helpers ---------------------------------------------------------

    /** WhatsApp the client a summary of their initial hall choice (best effort). */
    protected function notifySelection(BmsWizardSession $session, array $halls): void
    {
        $lead = $session->lead_id ? BmsLead::find($session->lead_id) : null;
        $to = $lead?->whatsapp ?: $session->contact_whatsapp ?: $session->contact_phone;
        if (! $to) {
            return;
        }

        $names = BmsHall::whereIn('id', collect($halls)->pluck('hall_id'))->pluck('name')->implode('، ');
        $body = 'شكراً ' . ($session->contact_name ?: '') . "! تم تسجيل اختيارك المبدئي: " . $names
            . '. سيتواصل معك فريق المبيعات لتأكيد التفاصيل وحجز زيارة للقاعة.';

        try {
            app(NotificationRouter::class)->notify(
                (int) $session->business_id, 'lead_selection', $to,
                'اختيارك المبدئي — Askar Group', $body,
                ['lead_id' => $session->lead_id], 'lead_selection:' . $session->id
            );
        } catch (\Throwable $e) {
            \Log::warning('[BMS] selection WhatsApp failed: ' . $e->getMessage());
        }
    }

    protected function convertToLead(BmsWizardSession $session, ContactServiceContract $contacts): void
    {
        $contact = $contacts->findOrCreateCustomer($session->business_id, [
            'name'   => $session->contact_name,
            'phone'  => $session->contact_phone,
            'email'  => $session->contact_email,
            'source' => $session->source,
        ]);

        $lead = BmsLead::create([
            'business_id'       => $session->business_id,
            'contact_id'        => $contact->id,
            'whatsapp'          => $session->contact_whatsapp ?: $session->contact_phone,
            'wizard_session_id' => $session->id,
            'stage'             => $this->stageFor($session),
            'source'            => $session->source,
            'event_type'        => $session->event_type,
            'attendees'         => $session->attendees,
            'fnb_level'         => $session->fnb_level,
            'venue_preference'  => $session->venue_preference,
            'budget_min'        => $session->budget_min,
            'budget_max'        => $session->budget_max,
            'candidate_dates'   => $session->candidate_dates,
            'area_id'           => $session->area_id,
            'last_activity_at'  => now(),
        ]);

        $session->contact_id = $contact->id;
        $session->lead_id = $lead->id;
        $session->status = 'converted';
    }

    protected function syncLead(BmsWizardSession $session): void
    {
        $lead = BmsLead::find($session->lead_id);
        if (! $lead) {
            return;
        }
        $lead->fill([
            'event_type'       => $session->event_type,
            'attendees'        => $session->attendees,
            'fnb_level'        => $session->fnb_level,
            'venue_preference' => $session->venue_preference,
            'budget_min'       => $session->budget_min,
            'budget_max'       => $session->budget_max,
            'candidate_dates'  => $session->candidate_dates,
            'area_id'          => $session->area_id,
            'stage'            => $lead->stage === 'wizard_incomplete' ? $this->stageFor($session) : $lead->stage,
            'last_activity_at' => now(),
        ])->save();
    }

    protected function stageFor(BmsWizardSession $session): string
    {
        $complete = $session->event_type && $session->attendees && $session->fnb_level
            && ! empty($session->candidate_dates);
        return $complete ? 'wizard_complete' : 'wizard_incomplete';
    }

    protected function resolve(string $token): ?BmsWizardSession
    {
        return BmsWizardSession::where('token', $token)->first();
    }

    protected function present(BmsWizardSession $s): array
    {
        return [
            'token'            => $s->token,
            'status'           => $s->status,
            'current_step'     => $s->current_step,
            'contact_name'     => $s->contact_name,
            'contact_phone'    => $s->contact_phone,
            'contact_email'    => $s->contact_email,
            'source'           => $s->source,
            'event_type'       => $s->event_type,
            'attendees'        => $s->attendees,
            'fnb_level'        => $s->fnb_level,
            'venue_preference' => $s->venue_preference,
            'candidate_dates'  => $s->candidate_dates,
            'budget_min'       => $s->budget_min,
            'budget_max'       => $s->budget_max,
            'area_id'          => $s->area_id,
            'lead_id'          => $s->lead_id,
        ];
    }
}
