<?php

declare(strict_types=1);

require DENTAL_ROOT . '/app/bootstrap.php';
require_login();
require_permission('clinical.view', ['super_admin','clinic_admin','dentist']);
require DENTAL_ROOT . '/app/layout.php';
require DENTAL_ROOT . '/app/module_helpers.php';

$pdo = db();
$user = current_user() ?? [];
$userId = (int)($user['id'] ?? 0);
$role = active_role();
$taskRole = $role;
if (!clinical_task_assignment_schema_ready()) {
    throw new RuntimeException('Apply Version 0.5.9.8.3 before using specific clinical task assignments.');
}

function clinical_task_item(PDO $pdo, int $itemId, bool $lock = false): ?array
{
    // Keep clinical task routing usable while an older database is waiting for
    // the v0.5.9.8.4 branch backfill migration.
    $planBranchExpr=schema_column_exists(table('treatment_plans'),'branch_id')
        ? 'COALESCE(p.branch_id,ce.branch_id,pt.branch_id)'
        : 'COALESCE(ce.branch_id,pt.branch_id)';
    $sql = 'SELECT i.*,p.patient_id,'.$planBranchExpr.' branch_id,p.dentist_user_id plan_dentist_user_id,p.title plan_title,p.status plan_status,'
        . 'CONCAT(pt.first_name," ",pt.last_name) patient_name,u.name responsible_dentist '
        . 'FROM `' . table('treatment_plan_items') . '` i '
        . 'JOIN `' . table('treatment_plans') . '` p ON p.id=i.treatment_plan_id '
        . 'LEFT JOIN `' . table('clinical_encounters') . '` ce ON ce.id=p.encounter_id '
        . 'JOIN `' . table('patients') . '` pt ON pt.id=p.patient_id '
        . 'LEFT JOIN `' . table('users') . '` u ON u.id=p.dentist_user_id WHERE i.id=? LIMIT 1' . ($lock ? ' FOR UPDATE' : '');
    $stmt=$pdo->prepare($sql);$stmt->execute([$itemId]);return $stmt->fetch() ?: null;
}

function clinical_task_row(PDO $pdo, int $taskId, bool $lock = false): ?array
{
    $sql='SELECT t.*,i.procedure_name,i.procedure_code,i.status item_status,p.status plan_status,p.dentist_user_id plan_dentist_user_id '
        . 'FROM `' . table('clinical_task_assignments') . '` t '
        . 'LEFT JOIN `' . table('treatment_plan_items') . '` i ON i.id=t.treatment_plan_item_id '
        . 'LEFT JOIN `' . table('treatment_plans') . '` p ON p.id=t.treatment_plan_id WHERE t.id=? LIMIT 1' . ($lock?' FOR UPDATE':'');
    $stmt=$pdo->prepare($sql);$stmt->execute([$taskId]);return $stmt->fetch() ?: null;
}

if ($_SERVER['REQUEST_METHOD']==='POST') {
    verify_csrf();
    if (!active_role_can_operate($role)) throw new RuntimeException('This clinical task is read-only in the selected role. Switch to a role assigned to your account.');
    $action=(string)($_POST['action']??'');

    if ($action==='request_task') {
        if (!in_array($role,['dentist','clinic_admin','super_admin'],true)) throw new RuntimeException('Only the responsible Dentist or an Administrator may route a clinical task.');
        $itemId=(int)($_POST['item_id']??0);$targetId=(int)($_POST['assigned_dentist_user_id']??0);$reason=trim((string)($_POST['reason']??''));
        if ($reason==='') throw new RuntimeException('Enter why another Dentist is required for this specific task.');
        $pdo->beginTransaction();
        try {
            $item=clinical_task_item($pdo,$itemId,true);if(!$item)throw new RuntimeException('Treatment item not found.');
            require_patient((int)$item['patient_id']);
            if($role==='dentist'&&(int)$item['plan_dentist_user_id']!==$userId)throw new RuntimeException('Only the responsible Dentist may request another Dentist for this treatment item.');
            if((int)$item['plan_dentist_user_id']===$targetId)throw new RuntimeException('The responsible Dentist already owns this treatment item.');
            if(in_array((string)$item['status'],['completed','declined','cancelled'],true)||in_array((string)$item['plan_status'],['completed','cancelled','expired'],true))throw new RuntimeException('This treatment item can no longer be assigned.');
            $required=clinical_privilege_code_for_text(trim((string)($item['procedure_code']??'').' '.(string)$item['procedure_name']));
            $eligible=false;foreach(qualified_dentists_for_privilege((int)($item['branch_id']??0),$required,(int)$item['plan_dentist_user_id']) as $doctor){if((int)$doctor['id']===$targetId){$eligible=true;break;}}
            if(!$eligible)throw new RuntimeException('The selected Dentist is not active, credentialed, branch-authorized, or granted the required privilege.');
            $open=$pdo->prepare('SELECT id FROM `' . table('clinical_task_assignments') . '` WHERE treatment_plan_item_id=? AND status IN ("pending","accepted","in_progress") LIMIT 1 FOR UPDATE');$open->execute([$itemId]);if($open->fetchColumn())throw new RuntimeException('This treatment item already has an open Dentist task assignment.');
            $title=trim((string)$item['procedure_name'])?:'Specific clinical task';
            $stmt=$pdo->prepare('INSERT INTO `' . table('clinical_task_assignments') . '` (patient_id,branch_id,treatment_plan_id,treatment_plan_item_id,task_code,task_title,required_privilege_code,requesting_dentist_user_id,assigned_dentist_user_id,reason,status,requested_by,requested_at,created_at) VALUES (?,?,?,?,?,?,?,?,?,?,"pending",?,NOW(),NOW())');
            $stmt->execute([(int)$item['patient_id'],(int)($item['branch_id']??0)?:null,(int)$item['treatment_plan_id'],$itemId,$required?:'consultation',$title,$required,(int)$item['plan_dentist_user_id']?:null,$targetId,$reason,$userId]);
            $taskId=(int)$pdo->lastInsertId();
            audit('clinical_task_assignment_requested','clinical_task_assignment',$taskId,['patient_id'=>(int)$item['patient_id'],'item_id'=>$itemId,'assigned_dentist_user_id'=>$targetId,'required_privilege'=>$required,'reason'=>$reason]);
            workflow_event((int)$item['patient_id'],'clinical_task_assignment_requested','Specific Dentist task requested',['clinical_task_assignment_id'=>$taskId,'treatment_plan_item_id'=>$itemId],$title.' · '.$reason);
            $pdo->commit();
        } catch(Throwable $e){if($pdo->inTransaction())$pdo->rollBack();throw $e;}
        module_return('clinical_tasks.php?item_id='.$itemId,'success','The qualified Dentist was notified. The task remains pending until accepted.');
    }

    if ($action==='decide_task') {
        if($role!=='dentist')throw new RuntimeException('Only the assigned Dentist may accept or decline this task.');
        $taskId=(int)($_POST['task_id']??0);$decision=(string)($_POST['decision']??'');$note=trim((string)($_POST['decision_note']??''));
        if(!in_array($decision,['accepted','declined'],true))throw new RuntimeException('Choose accept or decline.');
        if($decision==='declined'&&$note==='')throw new RuntimeException('Enter the reason for declining so the clinic can reroute the task.');
        $pdo->beginTransaction();
        try{
            $task=clinical_task_row($pdo,$taskId,true);if(!$task||$task['status']!=='pending')throw new RuntimeException('This task is no longer pending.');
            if((int)$task['assigned_dentist_user_id']!==$userId)throw new RuntimeException('This task is assigned to another Dentist.');
            require_patient((int)$task['patient_id']);
            if($decision==='accepted'){
                $reason=null;if(!dentist_has_clinical_privilege($userId,(string)($task['required_privilege_code']?:'consultation'),$reason))throw new RuntimeException($reason?:'Required clinical privilege is unavailable.');
                if(in_array((string)$task['item_status'],['completed','declined','cancelled'],true))throw new RuntimeException('The treatment item changed and can no longer be accepted.');
            }
            $stmt=$pdo->prepare('UPDATE `' . table('clinical_task_assignments') . '` SET status=?,decided_by=?,decided_at=NOW(),decision_note=?,updated_at=NOW() WHERE id=? AND status="pending"');$stmt->execute([$decision,$userId,$note?:null,$taskId]);if($stmt->rowCount()!==1)throw new RuntimeException('The task was resolved in another session.');
            audit('clinical_task_assignment_'.$decision,'clinical_task_assignment',$taskId,['decision_note'=>$note]);
            workflow_event((int)$task['patient_id'],'clinical_task_assignment_'.$decision,'Specific Dentist task '.$decision,['clinical_task_assignment_id'=>$taskId,'treatment_plan_item_id'=>(int)$task['treatment_plan_item_id']],$note);
            $pdo->commit();
        }catch(Throwable $e){if($pdo->inTransaction())$pdo->rollBack();throw $e;}
        module_return('clinical_tasks.php','success','Clinical task '.$decision.'.');
    }

    if ($action==='cancel_task') {
        $taskId=(int)($_POST['task_id']??0);$note=trim((string)($_POST['decision_note']??''));
        $task=clinical_task_row($pdo,$taskId,false);if(!$task||$task['status']!=='pending')throw new RuntimeException('This task is no longer pending.');
        $allowed=in_array($role,['super_admin','clinic_admin'],true)||(int)$task['requested_by']===$userId||(int)$task['requesting_dentist_user_id']===$userId;
        if(!$allowed)throw new RuntimeException('You cannot cancel this task.');
        $stmt=$pdo->prepare('UPDATE `' . table('clinical_task_assignments') . '` SET status="cancelled",decided_by=?,decided_at=NOW(),decision_note=?,updated_at=NOW() WHERE id=? AND status="pending"');$stmt->execute([$userId,$note?:'Cancelled before acceptance',$taskId]);if($stmt->rowCount()!==1)throw new RuntimeException('The task was resolved in another session.');
        audit('clinical_task_assignment_cancelled','clinical_task_assignment',$taskId,['reason'=>$note]);
        module_return('clinical_tasks.php','success','Clinical task assignment cancelled.');
    }
}

$itemId=(int)($_GET['item_id']??0);$item=$itemId?clinical_task_item($pdo,$itemId,false):null;
if($item)require_patient((int)$item['patient_id']);
$qualified=[];$required=null;$ownerReady=true;$ownerReason=null;
if($item){$required=clinical_privilege_code_for_text(trim((string)($item['procedure_code']??'').' '.(string)$item['procedure_name']));$ownerReady=dentist_has_clinical_privilege((int)$item['plan_dentist_user_id'],(string)($required?:'consultation'),$ownerReason);$qualified=qualified_dentists_for_privilege((int)($item['branch_id']??0),$required,(int)$item['plan_dentist_user_id']);}

$state=module_management_state('page','per_page',25);$page=$state['page'];$perPage=$state['per_page'];$offset=$state['offset'];
$q=trim((string)($_GET['q']??''));$statusFilter=module_safe_status_filter('status',['','pending','accepted','in_progress','declined','completed','cancelled']);$manageId=max(0,(int)($_GET['manage_id']??0));
$whereParts=['1=1'];$args=[];
if($role==='dentist'){$whereParts[]='(t.assigned_dentist_user_id=? OR t.requesting_dentist_user_id=?)';$args=[$userId,$userId];}
if($itemId){$whereParts[]='t.treatment_plan_item_id=?';$args[]=$itemId;}
if($statusFilter!==''){$whereParts[]='t.status=?';$args[]=$statusFilter;}
if($q!==''){$like=module_like_term($q);$whereParts[]='(CONCAT(pt.first_name," ",pt.last_name) LIKE ? OR i.procedure_name LIKE ? OR t.task_title LIKE ? OR t.reason LIKE ? OR au.name LIKE ?)';array_push($args,$like,$like,$like,$like,$like);}
$where=implode(' AND ',$whereParts);
$taskFrom=' FROM `' . table('clinical_task_assignments') . '` t JOIN `' . table('patients') . '` pt ON pt.id=t.patient_id LEFT JOIN `' . table('treatment_plan_items') . '` i ON i.id=t.treatment_plan_item_id LEFT JOIN `' . table('treatment_plans') . '` p ON p.id=t.treatment_plan_id LEFT JOIN `' . table('users') . '` ru ON ru.id=t.requesting_dentist_user_id LEFT JOIN `' . table('users') . '` au ON au.id=t.assigned_dentist_user_id LEFT JOIN `' . table('branches') . '` cb ON cb.id=t.branch_id ';
$countStmt=$pdo->prepare('SELECT COUNT(*)'.$taskFrom.'WHERE '.$where);$countStmt->execute($args);$tasksTotal=(int)$countStmt->fetchColumn();
$stmt=$pdo->prepare('SELECT t.*,CONCAT(pt.first_name," ",pt.last_name) patient_name,i.procedure_name,p.title plan_title,ru.name requesting_dentist,au.name assigned_dentist,cb.name branch_name'.$taskFrom.'WHERE '.$where.' ORDER BY FIELD(t.status,"pending","accepted","in_progress","declined","completed","cancelled"),t.requested_at DESC,t.id DESC LIMIT '.$perPage.' OFFSET '.$offset);$stmt->execute($args);$tasks=$stmt->fetchAll();
$managedTask=null;if($manageId>0){$stmt=$pdo->prepare('SELECT t.*,CONCAT(pt.first_name," ",pt.last_name) patient_name,i.procedure_name,p.title plan_title,ru.name requesting_dentist,au.name assigned_dentist,cb.name branch_name'.$taskFrom.'WHERE t.id=? LIMIT 1');$stmt->execute([$manageId]);$candidate=$stmt->fetch();if($candidate&&($role!=='dentist'||(int)$candidate['assigned_dentist_user_id']===$userId||(int)$candidate['requesting_dentist_user_id']===$userId))$managedTask=$candidate;}

render_header('Clinical Tasks');
render_module_intro('Specific Dentist task routing','Assign one procedure or clinical task to another qualified Dentist without transferring the patient or the complete treatment plan.',null,null);
?>
<?php if($item):?><section class="card"><div class="card-head"><div><span class="eyebrow">Selected treatment item</span><h2><?=e((string)$item['procedure_name'])?></h2><p><?=e((string)$item['patient_name'])?> · <?=e((string)$item['plan_title'])?> · Responsible Dentist: <?=e((string)($item['responsible_dentist']?:'Unassigned'))?></p></div><span class="badge"><?=e(module_status((string)($required?:'consultation')))?></span></div><?php if(!$ownerReady):?><div class="alert warning"><strong>The responsible Dentist cannot perform this task:</strong> <?=e((string)$ownerReason)?> Assign a qualified Dentist for this item only.</div><?php else:?><div class="notice success">The responsible Dentist currently has the required credential and privilege. Assignment is still available for documented specialty coverage or approved assistance.</div><?php endif;?><?php $canRequest=in_array($role,['clinic_admin','super_admin'],true)||($role==='dentist'&&(int)$item['plan_dentist_user_id']===$userId);if($canRequest&&!in_array((string)$item['status'],['completed','declined','cancelled'],true)):?><form method="post" class="form-grid"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="request_task"><input type="hidden" name="item_id" value="<?=$itemId?>"><label>Qualified receiving Dentist<select name="assigned_dentist_user_id" required><option value="">Select Dentist</option><?php foreach($qualified as $doctor):?><option value="<?=(int)$doctor['id']?>"><?=e((string)($doctor['display_name']??$doctor['name']))?></option><?php endforeach;?></select></label><label class="wide">Assignment reason<textarea name="reason" required></textarea></label><div class="wide"><button class="btn primary" <?=$qualified?'':'disabled'?>>Send task assignment</button></div></form><?php endif;?></section><?php endif;?>
<form method="get" class="management-filter-bar"><?php if($itemId):?><input type="hidden" name="item_id" value="<?=$itemId?>"><?php endif;?><label>Search<input name="q" value="<?=e($q)?>" placeholder="Patient, task, Dentist or reason"></label><label>Status<select name="status"><option value="">All statuses</option><?php foreach(['pending','accepted','in_progress','declined','completed','cancelled'] as $taskStatus):?><option value="<?=e($taskStatus)?>" <?=$statusFilter===$taskStatus?'selected':''?>><?=e(module_status($taskStatus))?></option><?php endforeach;?></select></label><label>Rows<select name="per_page"><?php foreach([10,25,50,100] as $size):?><option value="<?=$size?>" <?=$perPage===$size?'selected':''?>><?=$size?></option><?php endforeach;?></select></label><button class="btn primary">Apply</button><a class="btn ghost" href="clinical_tasks.php<?=$itemId?'?item_id='.$itemId:''?>">Reset</a></form>
<section class="card server-list-card"><?php module_render_list_count($tasksTotal,'clinical tasks');module_render_server_pagination($tasksTotal,$page,$perPage,'page','per_page','clinical-tasks');?><div class="table-wrap"><table><thead><tr><th>Status</th><th>Patient / task</th><th>Responsibility</th><th>Reason</th><th>Action</th></tr></thead><tbody><?php foreach($tasks as $task):?><tr><td><span class="badge <?=in_array($task['status'],['pending','declined'],true)?'warning':''?>"><?=e(module_status((string)$task['status']))?></span><small><?=e(date('M j, Y g:i A',strtotime((string)$task['requested_at'])))?></small></td><td><strong><?=e((string)$task['patient_name'])?></strong><small><?=e((string)($task['procedure_name']?:$task['task_title']))?> · <?=e((string)($task['branch_name']?:'Branch not recorded'))?></small></td><td><?=e((string)($task['requesting_dentist']?:'Clinic administration'))?> → <strong><?=e((string)$task['assigned_dentist'])?></strong><small>Required: <?=e(module_status((string)($task['required_privilege_code']?:'consultation')))?></small></td><td><?=e((string)$task['reason'])?><?php if($task['decision_note']):?><small>Decision: <?=e((string)$task['decision_note'])?></small><?php endif;?></td><td><a class="btn ghost" href="<?=e(module_management_url(['manage_id'=>(int)$task['id'],'page'=>$page,'per_page'=>$perPage]))?>">Manage</a></td></tr><?php endforeach;if(!$tasks):?><tr><td colspan="5" class="muted">No clinical task assignments match this view.</td></tr><?php endif;?></tbody></table></div><?php module_render_server_pagination($tasksTotal,$page,$perPage,'page','per_page','clinical-tasks');?></section>
<?php if($managedTask):?><dialog id="task-manage" class="wide-dialog" data-auto-open-dialog="task-manage"><form method="dialog"><button type="submit" class="dialog-close">×</button></form><div class="dialog-scroll"><h2><?=e((string)($managedTask['procedure_name']?:$managedTask['task_title']))?></h2><p><strong><?=e((string)$managedTask['patient_name'])?></strong> · <?=e(module_status((string)$managedTask['status']))?></p><div class="detail-grid"><div><small>Requested by</small><strong><?=e((string)($managedTask['requesting_dentist']?:'Clinic administration'))?></strong></div><div><small>Assigned to</small><strong><?=e((string)$managedTask['assigned_dentist'])?></strong></div><div><small>Required privilege</small><strong><?=e(module_status((string)($managedTask['required_privilege_code']?:'consultation')))?></strong></div><div><small>Branch</small><strong><?=e((string)($managedTask['branch_name']?:'Not recorded'))?></strong></div></div><div class="notice info"><?=e((string)$managedTask['reason'])?></div><div class="status-actions"><a class="btn ghost" href="treatment.php?patient_id=<?=(int)$managedTask['patient_id']?>&amp;plan_id=<?=(int)$managedTask['treatment_plan_id']?>">Open treatment plan</a><?php if(in_array($managedTask['status'],['accepted','in_progress'],true)&&$role==='dentist'&&(int)$managedTask['assigned_dentist_user_id']===$userId):?><a class="btn primary" href="patients.php?action=view&amp;id=<?=(int)$managedTask['patient_id']?>&amp;tab=clinical">Patient profile</a><?php endif;?></div><?php if($managedTask['status']==='pending'&&$role==='dentist'&&(int)$managedTask['assigned_dentist_user_id']===$userId):?><hr><form method="post" class="form-grid"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="decide_task"><input type="hidden" name="task_id" value="<?=(int)$managedTask['id']?>"><label class="wide">Decision note<input name="decision_note"></label><div class="status-actions wide"><button class="btn primary" name="decision" value="accepted">Accept</button><button class="btn ghost" name="decision" value="declined">Decline</button></div></form><?php elseif($managedTask['status']==='pending'&&(in_array($role,['super_admin','clinic_admin'],true)||(int)$managedTask['requested_by']===$userId||(int)$managedTask['requesting_dentist_user_id']===$userId)):?><hr><form method="post" class="form-grid"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="cancel_task"><input type="hidden" name="task_id" value="<?=(int)$managedTask['id']?>"><label class="wide">Cancellation note<input name="decision_note"></label><button class="btn danger">Cancel assignment</button></form><?php endif;?></div></dialog><?php endif;?>
<?php render_footer();
