<?php

namespace Modules\ClinicCore\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\ClinicCore\Entities\ClcMedicine;
use Modules\ClinicCore\Entities\ClcMedicineCategory;
use Yajra\DataTables\Facades\DataTables;

class ClcMedicineController extends Controller
{
    public function index()
    {
        if (!auth()->user()->can('clinic.manage_medicines')) {
            abort(403, 'Unauthorized action.');
        }

        $businessId = request()->session()->get('user.business_id');
        $categories = ClcMedicineCategory::active()->forBusiness($businessId)->orderBy('name')->get();

        return view('clinicCore::medicines.index', compact('categories'));
    }

    public function list(Request $request)
    {
        if (!auth()->user()->can('clinic.manage_medicines')) {
            abort(403, 'Unauthorized action.');
        }

        $businessId = request()->session()->get('user.business_id');
        $query = ClcMedicine::with(['category', 'product'])->where('business_id', $businessId);

        return DataTables::of($query)
            ->addColumn('category_name', fn($row) => optional($row->category)->name ?? '—')
            ->addColumn('product_col', function ($row) {
                if (!$row->product_id || !$row->product) return '<span class="text-muted">—</span>';
                return '<span class="label label-info" style="font-size:11px;">'
                    . e($row->product->name)
                    . '</span>';
            })
            ->addColumn('status_badge', function ($row) {
                $color = $row->status === 'active' ? 'success' : 'danger';
                return '<span class="label label-' . $color . '">' . ucfirst($row->status) . '</span>';
            })
            ->addColumn('action', function ($row) {
                $edit = '<button class="btn btn-xs btn-primary btn-edit-medicine" data-id="' . $row->id . '"><i class="fa fa-edit"></i></button> ';
                $del  = '<button class="btn btn-xs btn-danger btn-delete-medicine" data-id="' . $row->id . '"><i class="fa fa-trash"></i></button>';
                return $edit . $del;
            })
            ->rawColumns(['action', 'product_col', 'status_badge'])
            ->make(true);
    }

    public function store(Request $request)
    {
        if (!auth()->user()->can('clinic.manage_medicines')) {
            abort(403, 'Unauthorized action.');
        }

        $request->validate(['name' => 'required|string|max:150']);
        $businessId = request()->session()->get('user.business_id');

        $data = array_merge(
            $request->only(['name', 'generic_name', 'company', 'category_id', 'unit', 'product_id', 'description', 'status']),
            ['business_id' => $businessId]
        );
        if (auth()->user()->can('clinic.manage_controlled')) {
            $data['controlled_schedule'] = $this->cleanSchedule($request->controlled_schedule);
            if ($err = $this->controlledLinkError($data['controlled_schedule'], $data['product_id'] ?? null)) {
                return response()->json(['success' => false, 'msg' => $err], 422);
            }
        }
        ClcMedicine::create($data);

        return response()->json(['success' => true, 'msg' => __('clinicCore::lang.saved_successfully')]);
    }

    public function edit($id)
    {
        $businessId = request()->session()->get('user.business_id');
        $medicine   = ClcMedicine::with('product')->where('business_id', $businessId)->findOrFail($id);

        return response()->json([
            'id'            => $medicine->id,
            'name'          => $medicine->name,
            'generic_name'  => $medicine->generic_name,
            'company'       => $medicine->company,
            'category_id'   => $medicine->category_id,
            'unit'          => $medicine->unit,
            'product_id'    => $medicine->product_id,
            'product_name'  => $medicine->product ? $medicine->product->name : null,
            'product_sku'   => $medicine->product ? $medicine->product->sku : null,
            'description'         => $medicine->description,
            'status'              => $medicine->status,
            'controlled_schedule' => $medicine->controlled_schedule,
        ]);
    }

    public function update(Request $request, $id)
    {
        if (!auth()->user()->can('clinic.manage_medicines')) {
            abort(403, 'Unauthorized action.');
        }

        $request->validate(['name' => 'required|string|max:150']);
        $businessId = request()->session()->get('user.business_id');

        $data = $request->only(['name', 'generic_name', 'company', 'category_id', 'unit', 'product_id', 'description', 'status']);
        // Only users with manage_controlled may change the schedule; for
        // everyone else it stays untouched (we just don't include the column).
        if (auth()->user()->can('clinic.manage_controlled')) {
            $data['controlled_schedule'] = $this->cleanSchedule($request->controlled_schedule);
            if ($err = $this->controlledLinkError($data['controlled_schedule'], $data['product_id'] ?? null)) {
                return response()->json(['success' => false, 'msg' => $err], 422);
            }
        }
        ClcMedicine::where('business_id', $businessId)->findOrFail($id)->update($data);

        return response()->json(['success' => true, 'msg' => __('clinicCore::lang.updated_successfully')]);
    }

    /** Whitelist the controlled-schedule input to a known key, or null. */
    private function cleanSchedule($value): ?string
    {
        if ($value === null || $value === '') return null;
        return array_key_exists($value, ClcMedicine::schedules()) ? $value : null;
    }

    /**
     * A controlled medicine MUST be linked to an ERP product — otherwise
     * purchase/sell stock can't flow into the controlled register. Returns
     * an error string when the combination is invalid, or null to proceed.
     */
    private function controlledLinkError(?string $schedule, $productId): ?string
    {
        if (!$schedule) return null;
        if (empty($productId)) {
            return 'A medicine flagged as a controlled substance must be linked to an ERP product (set "Link to ERP Product" first). This is required so purchases and sales of this drug auto-update the controlled register.';
        }
        return null;
    }

    public function destroy($id)
    {
        if (!auth()->user()->can('clinic.manage_medicines')) {
            abort(403, 'Unauthorized action.');
        }

        $businessId = request()->session()->get('user.business_id');
        ClcMedicine::where('business_id', $businessId)->findOrFail($id)->delete();

        return response()->json(['success' => true, 'msg' => __('clinicCore::lang.deleted_successfully')]);
    }

    public function productSearch(Request $request)
    {
        $businessId = request()->session()->get('user.business_id');
        $products   = \App\Product::where('business_id', $businessId)
            ->where('is_inactive', 0)
            ->where(function ($q) use ($request) {
                $q->where('name', 'LIKE', '%' . $request->q . '%')
                  ->orWhere('sku',  'LIKE', '%' . $request->q . '%');
            })
            ->limit(25)
            ->get(['id', 'name', 'sku']);

        return response()->json($products->map(fn($p) => [
            'id'   => $p->id,
            'text' => $p->name . ($p->sku ? ' [' . $p->sku . ']' : ''),
        ]));
    }

    public function search(Request $request)
    {
        $businessId = request()->session()->get('user.business_id');
        $medicines  = ClcMedicine::where('business_id', $businessId)
            ->active()
            ->where(function ($q) use ($request) {
                $q->where('name',         'LIKE', '%' . $request->q . '%')
                  ->orWhere('generic_name', 'LIKE', '%' . $request->q . '%');
            })
            ->get(['id', 'name', 'generic_name', 'unit']);

        return response()->json($medicines->map(fn($m) => [
            'id'   => $m->id,
            'text' => $m->name . ($m->generic_name ? ' (' . $m->generic_name . ')' : ''),
            'unit' => $m->unit,
        ]));
    }
}
