$APP = __DIR__ . '/../app/'; require_once $APP.'layout_shell.php'; require_once $APP.'bootstrap.php'; $pdo = legacy_pdo(); $scope = $_POST['scope'] ?? 'global'; $id = trim($_POST['context_id'] ?? ''); $q = trim($_POST['q'] ?? ''); header('Content-Type: text/plain; charset=utf-8'); $ctx = []; try { switch ($scope) { case 'estate': if ($id!=='') { $e = $pdo->prepare("SELECT id,name,domicile_state,date_of_death FROM estates WHERE id=?"); $e->execute([$id]); $ctx['estate'] = $e->fetch() ?: []; // assets & debts summary $assets = 0.0; $debts = 0.0; try { $assets = (float)$pdo->query("SELECT COALESCE(SUM(value_at_death),0) FROM assets WHERE estate_id=".$pdo->quote($id))->fetchColumn(); } catch(Throwable $e){} try { $debts = (float)$pdo->query("SELECT COALESCE(SUM(amount_at_death),0) FROM estate_debts_at_death WHERE estate_id=".$pdo->quote($id))->fetchColumn(); } catch(Throwable $e){} $ctx['assets_at_death'] = $assets; $ctx['debts_at_death'] = $debts; // tasks next 30 days try{ $st=$pdo->prepare("SELECT title,status,due_date FROM tasks WHERE estate_id=? AND due_date BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 30 DAY) ORDER BY due_date"); $st->execute([$id]); $ctx['tasks_30d']=$st->fetchAll(); }catch(Throwable $e){} } break; case 'case': if ($id!=='') { $c=$pdo->prepare("SELECT id, case_number, estate_id FROM cases WHERE id=?"); $c->execute([$id]); $ctx['case']=$c->fetch() ?: []; try{ $dq=$pdo->prepare("SELECT event_date,title FROM dockets WHERE case_id=? AND event_date>=CURDATE() ORDER BY event_date LIMIT 10"); $dq->execute([$id]); $ctx['upcoming_dockets']=$dq->fetchAll(); }catch(Throwable $e){} } break; case 'account': if ($id!=='') { $a=$pdo->prepare("SELECT id,name,email,phone FROM accounts WHERE id=?"); $a->execute([$id]); $ctx['account']=$a->fetch() ?: []; try{ $op=$pdo->prepare("SELECT title,amount,stage,close_date FROM opportunities WHERE account_id=? ORDER BY updated_at DESC LIMIT 5"); $op->execute([$id]); $ctx['opps']=$op->fetchAll(); }catch(Throwable $e){} } break; case 'document': if ($id!=='') { $d=$pdo->prepare("SELECT id,owner_type,owner_id,filename,mime,path,size_bytes,created_at FROM documents WHERE id=?"); $d->execute([$id]); $ctx['document']=$d->fetch() ?: []; } break; default: /* global */ break; } } catch (Throwable $e) { echo "Context error: ".$e->getMessage()."\n"; } function summarize_estate($ctx){ $e = $ctx['estate'] ?? null; if (!$e) return "No estate found for this ID."; $net = ($ctx['assets_at_death'] ?? 0) - ($ctx['debts_at_death'] ?? 0); $out = "Estate: {$e['name']} (domicile {$e['domicile_state']}, DoD {$e['date_of_death']})\n"; $out.= "Assets@Death: $".number_format((float)($ctx['assets_at_death'] ?? 0),2).", Debts@Death: $".number_format((float)($ctx['debts_at_death'] ?? 0),2).", Net: $".number_format($net,2)."\n"; if (!empty($ctx['tasks_30d'])) { $out.="Next 30 days tasks:\n"; foreach ($ctx['tasks_30d'] as $t) $out.=" - [{$t['due_date']}] {$t['title']} ({$t['status']})\n"; } return $out; } function answer_global($q){ $qL=strtolower($q); if (strpos($qL,'inventory at death')!==false) return "Inventory at death = list of assets valued as of date of death. Use Assets@Death and Debts@Death to compute the net estate; attach valuations, statements, and appraisals."; if (strpos($qL,'distribution')!==false) return "Before distribution: confirm net estate, clear liabilities, verify heirs/percents and bequests, prepare receipts, then post to ledger and update distributions report."; return "Ask about estate summaries, tasks due, ledger/cashflow, distributions, compliance steps, or drafting outbound messages."; } if ($scope==='estate' && !empty($ctx['estate'])) echo summarize_estate($ctx)."\n\n"; echo answer_global($q);