<?php

namespace Modules\MedSurgery\Services;

use Carbon\Carbon;
use Modules\MedSurgery\Entities\MedsxCase;
use Modules\MedSurgery\Entities\MedsxChecklist;

/**
 * ChecklistService (SIFA P6-T4) — seeds and maintains the WHO Surgical Safety
 * Checklist (Sign In / Time Out / Sign Out) for a case.
 *
 * The default item set per phase is config('medsurgery.checklist_defaults');
 * each item is stored as {label, checked:false, by:null}. On case creation all
 * three phases are seeded (idempotent). Ticking items and signing a phase are
 * separate operations so an item can be checked without prematurely signing.
 */
class ChecklistService
{
    /**
     * Ensure the three phase rows exist for a case, seeded with the WHO default
     * items. Idempotent: existing rows are left untouched.
     */
    public function seedForCase(MedsxCase $case): void
    {
        $defaults = (array) config('medsurgery.checklist_defaults', []);

        foreach (MedsxChecklist::PHASES as $phase) {
            $labels = (array) ($defaults[$phase] ?? []);
            $items = array_map(fn ($label) => ['label' => $label, 'checked' => false, 'by' => null], $labels);

            MedsxChecklist::firstOrCreate(
                ['case_id' => $case->id, 'phase' => $phase],
                ['business_id' => $case->business_id, 'items' => $items]
            );
        }
    }

    /**
     * Replace the checked-state of a phase's items. $checked is a 0-based array of
     * booleans aligned to the stored item order; $userId stamps who ticked each.
     */
    public function updateItems(MedsxChecklist $checklist, array $checked, ?int $userId = null): MedsxChecklist
    {
        $items = $checklist->items ?? [];

        foreach ($items as $i => &$item) {
            $isChecked = ! empty($checked[$i]);
            $item['checked'] = $isChecked;
            $item['by'] = $isChecked ? ($item['by'] ?? $userId) : null;
        }
        unset($item);

        $checklist->items = $items;
        $checklist->save();

        return $checklist->fresh();
    }

    /**
     * Sign off a phase: requires every item checked, then stamps completed_by/at.
     * Returns false (no exception) if not all items are checked so the caller can
     * surface a clear message.
     */
    public function sign(MedsxChecklist $checklist, int $userId): bool
    {
        if (! $checklist->allChecked()) {
            return false;
        }

        $checklist->update([
            'completed_by' => $userId,
            'completed_at' => Carbon::now(),
        ]);

        return true;
    }

    /** The time_out checklist row for a case (the incision gate), if any. */
    public function timeOut(MedsxCase $case): ?MedsxChecklist
    {
        return $case->checklists->firstWhere('phase', 'time_out')
            ?? MedsxChecklist::where('case_id', $case->id)->where('phase', 'time_out')->first();
    }
}
