<?php

namespace Modules\MedBloodBank\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Validation\ValidationException;
use Modules\MedBloodBank\Entities\MbbCrossmatch;
use Modules\MedBloodBank\Entities\MbbIssue;
use Modules\MedBloodBank\Services\BloodBankService;
use Yajra\DataTables\Facades\DataTables;

/**
 * Issues / transfusions screen (SIFA P6-T6). Issue a compatible crossmatched bag,
 * start / complete the transfusion, and record an adverse reaction (which flags
 * the issue + raises a critical patient alert). Guarded by mbb.issue.manage.
 */
class IssueController extends MedBloodBankBaseController
{
    public function __construct(private BloodBankService $service)
    {
    }

    public function index(Request $request)
    {
        $this->guard('mbb.issue.manage');

        if ($request->ajax()) {
            $query = MbbIssue::forBusiness($this->businessId())
                ->leftJoin('mbb_donations', 'mbb_donations.id', '=', 'mbb_issues.donation_id')
                ->select([
                    'mbb_issues.id',
                    'mbb_issues.patient_id',
                    'mbb_issues.issued_to',
                    'mbb_issues.issued_at',
                    'mbb_issues.status',
                    'mbb_issues.reaction',
                    'mbb_issues.reaction_type',
                    'mbb_donations.bag_no',
                    'mbb_donations.blood_group',
                ]);

            return DataTables::of($query)
                ->addColumn('patient_name', fn ($r) => e($this->patientName((int) $r->patient_id)))
                ->editColumn('issued_to', fn ($r) => __('medbloodbank::lang.issued_to_' . $r->issued_to))
                ->editColumn('issued_at', fn ($r) => $r->issued_at ? \Carbon\Carbon::parse($r->issued_at)->toDateString() : '—')
                ->editColumn('status', fn ($r) => $this->statusLabel($r->status))
                ->addColumn('reaction_flag', fn ($r) => $r->reaction
                    ? '<span class="label label-danger" title="' . e(__('medbloodbank::lang.reaction_type_' . $r->reaction_type)) . '">'
                        . '<i class="fa fa-exclamation-triangle"></i> ' . __('medbloodbank::lang.reaction') . '</span>'
                    : '<span class="text-muted">—</span>')
                ->addColumn('action', function ($r) {
                    $btns = '';
                    if ($r->status === 'issued') {
                        $btns .= '<button class="btn btn-xs btn-info mbb-action-btn" data-href="'
                            . route('mbb.issues.start', $r->id) . '"><i class="fa fa-play"></i> '
                            . __('medbloodbank::lang.start_transfusion') . '</button> ';
                    }
                    if (in_array($r->status, ['issued', 'transfusing'])) {
                        $btns .= '<button class="btn btn-xs btn-success mbb-modal-btn" data-href="'
                            . route('mbb.issues.complete.form', $r->id) . '"><i class="fa fa-check"></i> '
                            . __('medbloodbank::lang.complete') . '</button>';
                    }

                    return $btns ?: '<span class="text-muted">—</span>';
                })
                ->rawColumns(['status', 'reaction_flag', 'action'])
                ->make(true);
        }

        // Compatible crossmatches not yet issued — the issuance candidates.
        $pending = MbbCrossmatch::forBusiness($this->businessId())
            ->where('result', 'compatible')
            ->whereDoesntHave('issue')
            ->leftJoin('mbb_donations', 'mbb_donations.id', '=', 'mbb_crossmatches.donation_id')
            ->select([
                'mbb_crossmatches.id',
                'mbb_crossmatches.patient_id',
                'mbb_donations.bag_no',
                'mbb_donations.blood_group',
                'mbb_donations.status as bag_status',
            ])
            ->get()
            ->map(function ($c) {
                $c->patient_name = $this->patientName((int) $c->patient_id);

                return $c;
            });

        return view('medbloodbank::issues.index', [
            'pending'   => $pending,
            'issuedTo'  => MbbIssue::ISSUED_TO,
        ]);
    }

    /** Issue a compatible crossmatched bag. */
    public function issue(Request $request)
    {
        $this->guard('mbb.issue.manage');

        $data = $this->validate($request, [
            'crossmatch_id' => 'required|integer',
            'issued_to'     => 'required|in:' . implode(',', MbbIssue::ISSUED_TO),
        ]);

        $crossmatch = MbbCrossmatch::forBusiness($this->businessId())->find($data['crossmatch_id']);
        if (! $crossmatch) {
            return $this->fail(__('medbloodbank::lang.crossmatch_not_found'));
        }

        try {
            $this->service->issueBag($crossmatch, [
                'issued_to' => $data['issued_to'],
                'issued_by' => $this->userId(),
            ]);

            return $this->ok(__('medbloodbank::lang.bag_issued'));
        } catch (ValidationException $e) {
            return $this->fail($this->firstError($e));
        } catch (\Exception $e) {
            \Log::emergency($e->getMessage());

            return $this->fail();
        }
    }

    /** Start the transfusion clock. */
    public function start($id)
    {
        $this->guard('mbb.issue.manage');

        $issue = MbbIssue::forBusiness($this->businessId())->findOrFail($id);
        if ($issue->status !== 'issued') {
            return $this->fail(__('medbloodbank::lang.cannot_start'));
        }

        try {
            $this->service->startTransfusion($issue);

            return $this->ok(__('medbloodbank::lang.transfusion_started'));
        } catch (\Exception $e) {
            \Log::emergency($e->getMessage());

            return $this->fail();
        }
    }

    /** The complete-transfusion + reaction modal. */
    public function completeForm($id)
    {
        $this->guard('mbb.issue.manage');

        $issue = MbbIssue::forBusiness($this->businessId())->findOrFail($id);

        return view('medbloodbank::issues.complete', [
            'issue'            => $issue,
            'patientName'      => $this->patientName((int) $issue->patient_id),
            'reactionTypes'    => MbbIssue::REACTION_TYPES,
            'reactionSeverities' => MbbIssue::REACTION_SEVERITIES,
        ]);
    }

    public function complete(Request $request, $id)
    {
        $this->guard('mbb.issue.manage');

        $issue = MbbIssue::forBusiness($this->businessId())->findOrFail($id);
        if (! in_array($issue->status, ['issued', 'transfusing'])) {
            return $this->fail(__('medbloodbank::lang.cannot_complete'));
        }

        $data = $this->validate($request, [
            'reaction'            => 'nullable|boolean',
            'reaction_type'       => 'nullable|in:' . implode(',', MbbIssue::REACTION_TYPES),
            'reaction_severity'   => 'nullable|in:' . implode(',', MbbIssue::REACTION_SEVERITIES),
            'reaction_management' => 'nullable|string',
        ]);

        $reaction = null;
        if ($request->boolean('reaction')) {
            if (empty($data['reaction_type'])) {
                return $this->fail(__('medbloodbank::lang.reaction_type_required'));
            }
            $reaction = [
                'type'       => $data['reaction_type'],
                'severity'   => $data['reaction_severity'] ?? null,
                'management' => $data['reaction_management'] ?? null,
            ];
        }

        try {
            $issue = $this->service->completeTransfusion($issue, $reaction);

            return $this->ok(
                $issue->reaction
                    ? __('medbloodbank::lang.completed_with_reaction')
                    : __('medbloodbank::lang.transfusion_completed')
            );
        } catch (\Exception $e) {
            \Log::emergency($e->getMessage());

            return $this->fail();
        }
    }

    // ── helpers ──────────────────────────────────────────────────────────

    private function statusLabel(string $s): string
    {
        $map = ['issued' => 'primary', 'transfusing' => 'info', 'completed' => 'success', 'returned' => 'default'];

        return '<span class="label label-' . ($map[$s] ?? 'default') . '">' . __('medbloodbank::lang.issue_status_' . $s) . '</span>';
    }

    private function patientName(int $patientId): string
    {
        if (! Schema::hasTable('clc_patients')) {
            return '#' . $patientId;
        }

        $p = DB::table('clc_patients')
            ->leftJoin('contacts', 'contacts.id', '=', 'clc_patients.contact_id')
            ->where('clc_patients.id', $patientId)
            ->first(['clc_patients.patient_name', 'contacts.name as contact_name']);

        if (! $p) {
            return '#' . $patientId;
        }

        return trim($p->patient_name ?? '') ?: trim($p->contact_name ?? '') ?: ('#' . $patientId);
    }

    private function firstError(ValidationException $e): string
    {
        foreach ($e->errors() as $msgs) {
            if (! empty($msgs)) {
                return $msgs[0];
            }
        }

        return __('messages.something_went_wrong');
    }
}
