<?php

namespace Modules\Bms\Services\Qc;

use Modules\Bms\Entities\BmsBooking;
use Modules\Bms\Entities\BmsQcChecklist;
use Modules\Bms\Entities\BmsQcInspection;

/**
 * Quality-control engine. Inspections are instantiated from a checklist
 * template, scored pass/fail, and (optionally) gate booking completion.
 */
class QcService
{
    /** Default checklist seeded the first time a business has none. */
    public const DEFAULT_ITEMS = [
        ['label' => 'Hall cleanliness & readiness',     'label_ar' => 'نظافة القاعة وجاهزيتها'],
        ['label' => 'Tables, chairs & linens set',      'label_ar' => 'تجهيز الطاولات والكراسي والمفارش'],
        ['label' => 'Stage / Kosha décor complete',     'label_ar' => 'اكتمال ديكور المسرح/الكوشة'],
        ['label' => 'Lighting & AV tested',             'label_ar' => 'اختبار الإضاءة والصوتيات'],
        ['label' => 'F&B stations ready & temperature',  'label_ar' => 'جاهزية محطات الطعام ودرجة الحرارة'],
        ['label' => 'Air-conditioning & comfort',       'label_ar' => 'التكييف والراحة'],
        ['label' => 'Safety: exits, extinguishers',     'label_ar' => 'السلامة: المخارج وطفايات الحريق'],
        ['label' => 'Staff briefed & in position',      'label_ar' => 'إطلاع الطاقم وتمركزه'],
    ];

    /** Resolve the checklist for a booking stage (most specific first). */
    public function checklistFor(BmsBooking $booking, string $stage): ?BmsQcChecklist
    {
        $this->ensureDefaults((int) $booking->business_id);

        return BmsQcChecklist::where('business_id', $booking->business_id)
            ->where('is_active', true)
            ->where(fn ($q) => $q->where('stage', $stage)->orWhere('stage', 'any'))
            ->orderByRaw('event_type = ? desc', [$booking->event_type])
            ->orderBy('sort_order')
            ->first();
    }

    /** Get (or create) the open inspection for a booking + stage. */
    public function inspectionFor(BmsBooking $booking, string $stage = 'pre_event'): BmsQcInspection
    {
        $existing = BmsQcInspection::where('booking_id', $booking->id)->where('stage', $stage)->first();
        if ($existing) {
            return $existing;
        }

        $checklist = $this->checklistFor($booking, $stage);
        $items = collect($checklist->items ?? self::DEFAULT_ITEMS)
            ->map(fn ($i) => ['label' => $i['label'], 'label_ar' => $i['label_ar'] ?? null, 'status' => 'pass', 'note' => null])
            ->all();

        $insp = BmsQcInspection::create([
            'business_id'  => (int) $booking->business_id,
            'booking_id'   => $booking->id,
            'checklist_id' => optional($checklist)->id,
            'stage'        => $stage,
            'items'        => $items,
            'status'       => 'open',
        ]);
        \Modules\Bms\Entities\BmsQcEvent::record($insp, 'started');

        return $insp;
    }

    /** Editable QC failure reasons (code + localized label). */
    public function reasons(int $businessId): array
    {
        $r = \Modules\Bms\Entities\BmsSetting::get($businessId, 'qc_reasons', null);
        return (is_array($r) && ! empty($r)) ? $r : (array) config('bms.qc_reasons', []);
    }

    /** Attach a recorded voice note (stored path) to an inspection. */
    public function addVoice(BmsQcInspection $inspection, string $path, ?int $userId = null): \Modules\Bms\Entities\BmsQcEvent
    {
        return \Modules\Bms\Entities\BmsQcEvent::record($inspection, 'voice', $path, $userId);
    }

    /** Record results: compute score + pass/fail (any 'fail' fails). */
    public function record(BmsQcInspection $inspection, array $items, ?int $inspectorId = null): BmsQcInspection
    {
        $clean = collect($items)->map(fn ($i) => [
            'label'       => $i['label'] ?? '',
            'label_ar'    => $i['label_ar'] ?? null,
            'status'      => in_array(($i['status'] ?? 'pass'), ['pass', 'fail', 'na'], true) ? $i['status'] : 'pass',
            'reason_code' => $i['reason_code'] ?? null,
            'note'        => $i['note'] ?? null,
        ])->all();

        $scored = collect($clean)->reject(fn ($i) => $i['status'] === 'na');
        $passed = $scored->where('status', 'pass')->count();
        $score = $scored->count() > 0 ? (int) round($passed / $scored->count() * 100) : 100;
        $anyFail = $scored->contains(fn ($i) => $i['status'] === 'fail');

        $inspection->update([
            'items'        => $clean,
            'score'        => $score,
            'status'       => $anyFail ? 'failed' : 'passed',
            'inspector_id' => $inspectorId,
            'completed_at' => now(),
        ]);
        \Modules\Bms\Entities\BmsQcEvent::record($inspection, 'submitted',
            ($anyFail ? 'failed' : 'passed') . ' · ' . $score . '%', $inspectorId);

        return $inspection->fresh();
    }

    /**
     * Completion gate: a booking may complete only when it has no failed/open
     * inspection. No inspections at all → not gated (true).
     */
    public function passesCompletionGate(BmsBooking $booking): bool
    {
        $inspections = BmsQcInspection::where('booking_id', $booking->id)->get();
        if ($inspections->isEmpty()) {
            return true;
        }
        return $inspections->every(fn ($i) => $i->status === 'passed');
    }

    /** Seed a default checklist the first time (per business). */
    public function ensureDefaults(int $businessId): void
    {
        if (BmsQcChecklist::where('business_id', $businessId)->exists()) {
            return;
        }
        BmsQcChecklist::create([
            'business_id' => $businessId,
            'name'        => 'Standard event QC',
            'name_ar'     => 'فحص الجودة القياسي',
            'event_type'  => null,
            'stage'       => 'pre_event',
            'items'       => self::DEFAULT_ITEMS,
            'is_active'   => true,
            'sort_order'  => 1,
        ]);
    }
}
