<?php

declare(strict_types=1);

require dirname(__DIR__) . '/app/bootstrap.php';
require_once DENTAL_ROOT . '/app/inventory_integrity.php';
header('Content-Type: application/json; charset=utf-8');

function inventory_context_reply(int $status,array $payload): never
{
    http_response_code($status);
    echo json_encode($payload,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
    exit;
}

if(!current_user()) inventory_context_reply(401,['ok'=>false,'message'=>'Your session has expired. Sign in again.']);
if(!has_role(['super_admin','clinic_admin','inventory_officer','dentist','dental_assistant'])){
    inventory_context_reply(403,['ok'=>false,'message'=>'Your role cannot open controlled inventory context.']);
}
if(!inventory_schema_ready()) inventory_context_reply(503,['ok'=>false,'message'=>'Apply the pending inventory update first.']);

try{
    $pdo=db();
    $mode=trim((string)($_GET['mode']??''));
    $branchId=max(0,(int)($_GET['branch_id']??0));
    $userBranch=inventory_user_branch_id();
    if(!has_role('super_admin')){
        if($branchId>0&&$userBranch>0&&$branchId!==$userBranch) throw new RuntimeException('That branch is outside your assignment.');
        $branchId=$userBranch;
    }
    inventory_require_branch($branchId);

    if($mode==='item'){
        $itemId=max(0,(int)($_GET['item_id']??0));
        if($itemId<1) throw new RuntimeException('Choose an inventory item.');
        $stmt=$pdo->prepare(
            'SELECT i.id,i.sku,i.barcode,i.name,i.category,i.unit,i.purchase_cost,i.usage_cost,'
            . 'COALESCE(bs.current_stock,0) current_stock,COALESCE(bs.reorder_level,i.reorder_level,0) reorder_level '
            . 'FROM `' . table('inventory_items') . '` i LEFT JOIN `' . table('inventory_branch_stocks') . '` bs ON bs.item_id=i.id AND bs.branch_id=? '
            . 'WHERE i.id=? AND i.status="active" AND (i.branch_id=? OR i.branch_id IS NULL) LIMIT 1'
        );
        $stmt->execute([$branchId,$itemId,$branchId]);$item=$stmt->fetch();
        if(!$item) throw new RuntimeException('The inventory item is inactive or unavailable for this branch.');
        $lots=$pdo->prepare(
            'SELECT id,lot_number,quantity_remaining,expiry_date,status,unit_cost '
            . 'FROM `' . table('inventory_lots') . '` WHERE item_id=? AND branch_id=? AND status="active" AND quantity_remaining>0 '
            . 'AND (expiry_date IS NULL OR expiry_date>=CURDATE()) ORDER BY expiry_date IS NULL,expiry_date,received_at,id'
        );
        $lots->execute([$itemId,$branchId]);$lotRows=$lots->fetchAll();
        inventory_context_reply(200,['ok'=>true,'item'=>[
            'id'=>(int)$item['id'],'sku'=>(string)$item['sku'],'barcode'=>(string)($item['barcode']??''),'name'=>(string)$item['name'],
            'category'=>(string)($item['category']??''),'unit'=>(string)$item['unit'],'current_stock'=>(float)$item['current_stock'],
            'reorder_level'=>(float)$item['reorder_level'],'purchase_cost'=>(float)$item['purchase_cost'],'usage_cost'=>(float)$item['usage_cost'],
        ],'lots'=>array_map(static fn(array $row):array=>[
            'id'=>(int)$row['id'],'lot_number'=>(string)$row['lot_number'],'quantity_remaining'=>(float)$row['quantity_remaining'],
            'expiry_date'=>(string)($row['expiry_date']??''),'status'=>(string)$row['status'],'unit_cost'=>(float)($row['unit_cost']??0),
        ],$lotRows),'suggested_lot_id'=>(int)($lotRows[0]['id']??0)]);
    }

    if($mode==='encounter'){
        $encounterId=max(0,(int)($_GET['encounter_id']??0));
        if($encounterId<1) throw new RuntimeException('Choose an active encounter.');
        $stmt=$pdo->prepare(
            'SELECT c.id,c.patient_id,c.status,c.dentist_user_id,c.dentist_name,c.assistant_user_id,c.assistant_name,'
            . 'p.patient_no,p.first_name,p.last_name,q.chair_id,ch.chair_name chair_name '
            . 'FROM `' . table('clinical_encounters') . '` c JOIN `' . table('patients') . '` p ON p.id=c.patient_id '
            . 'LEFT JOIN `' . table('queue_entries') . '` q ON q.id=c.queue_entry_id LEFT JOIN `' . table('clinic_chairs') . '` ch ON ch.id=q.chair_id '
            . 'WHERE c.id=? AND c.branch_id=? AND c.status IN ("draft","pending_review") LIMIT 1'
        );
        $stmt->execute([$encounterId,$branchId]);$encounter=$stmt->fetch();
        if(!$encounter) throw new RuntimeException('The encounter is no longer active for this branch.');
        $procedures=$pdo->prepare('SELECT id,procedure_name,tooth_region,status FROM `' . table('procedures') . '` WHERE encounter_id=? AND status IN ("in_progress","completed") ORDER BY created_at DESC,id DESC');
        $procedures->execute([$encounterId]);
        inventory_context_reply(200,['ok'=>true,'encounter'=>[
            'id'=>(int)$encounter['id'],'patient_id'=>(int)$encounter['patient_id'],'patient_no'=>(string)$encounter['patient_no'],
            'patient_name'=>trim((string)$encounter['last_name'].', '.(string)$encounter['first_name']),
            'dentist_user_id'=>(int)($encounter['dentist_user_id']??0),'dentist_name'=>(string)($encounter['dentist_name']??''),
            'assistant_user_id'=>(int)($encounter['assistant_user_id']??0),'assistant_name'=>(string)($encounter['assistant_name']??''),
            'chair_id'=>(int)($encounter['chair_id']??0),'chair_name'=>(string)($encounter['chair_name']??''),'status'=>(string)$encounter['status'],
        ],'procedures'=>array_map(static fn(array $row):array=>[
            'id'=>(int)$row['id'],'name'=>(string)$row['procedure_name'],'tooth_region'=>(string)($row['tooth_region']??''),'status'=>(string)$row['status'],
        ],$procedures->fetchAll())]);
    }

    if($mode==='issue'){
        $documentId=max(0,(int)($_GET['document_id']??0));
        if($documentId<1) throw new RuntimeException('Choose the original issue document.');
        $stmt=$pdo->prepare('SELECT * FROM `' . table('inventory_documents') . '` WHERE id=? AND branch_id=? AND document_type="issue" AND status="posted" LIMIT 1');
        $stmt->execute([$documentId,$branchId]);$doc=$stmt->fetch();
        if(!$doc) throw new RuntimeException('The original posted issue was not found for this branch.');
        $lineStmt=$pdo->prepare(
            'SELECT l.id,l.item_id,l.lot_id,l.quantity,i.sku,i.name,i.unit,lot.lot_number,lot.expiry_date,lot.status lot_status,'
            . 'COALESCE((SELECT SUM(rl.quantity) FROM `' . table('inventory_document_lines') . '` rl '
            . 'JOIN `' . table('inventory_documents') . '` rd ON rd.id=rl.document_id '
            . 'WHERE rd.source_document_id=? AND rd.document_type="return" AND rd.status IN ("submitted","approved","posted") AND rl.source_line_id=l.id),0) returned_quantity '
            . 'FROM `' . table('inventory_document_lines') . '` l JOIN `' . table('inventory_items') . '` i ON i.id=l.item_id '
            . 'LEFT JOIN `' . table('inventory_lots') . '` lot ON lot.id=l.lot_id WHERE l.document_id=? ORDER BY l.id'
        );
        $lineStmt->execute([$documentId,$documentId]);$lines=[];
        foreach($lineStmt->fetchAll() as $line){
            $returnable=max(0,round((float)$line['quantity']-(float)$line['returned_quantity'],2));
            if($returnable<=0) continue;
            $lines[]=[
                'source_line_id'=>(int)$line['id'],'item_id'=>(int)$line['item_id'],'lot_id'=>(int)($line['lot_id']??0),
                'sku'=>(string)$line['sku'],'item_name'=>(string)$line['name'],'unit'=>(string)$line['unit'],
                'lot_number'=>(string)($line['lot_number']??''),'expiry_date'=>(string)($line['expiry_date']??''),
                'issued_quantity'=>(float)$line['quantity'],'returned_quantity'=>(float)$line['returned_quantity'],'returnable_quantity'=>$returnable,
            ];
        }
        inventory_context_reply(200,['ok'=>true,'document'=>[
            'id'=>(int)$doc['id'],'document_no'=>(string)$doc['document_no'],'patient_id'=>(int)($doc['patient_id']??0),
            'encounter_id'=>(int)($doc['encounter_id']??0),'procedure_id'=>(int)($doc['procedure_id']??0),
            'requested_for_user_id'=>(int)($doc['requested_for_user_id']??0),'usage_destination'=>(string)($doc['usage_destination']??''),
            'chair_id'=>(int)($doc['chair_id']??0),
        ],'lines'=>$lines]);
    }

    throw new RuntimeException('Unsupported inventory context request.');
}catch(Throwable $e){
    inventory_context_reply(422,['ok'=>false,'message'=>$e->getMessage()]);
}
