<?php
namespace ApplicationBundle\Modules\BookingDemo\Controller;
use ApplicationBundle\Controller\GenericController;
use CompanyGroupBundle\Entity\DemoRequest;
use CompanyGroupBundle\Entity\DemoRequestSlot;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class BookingDemoPublicController extends GenericController
{
private static $slotHours = [
'09:00', '09:20', '09:40',
'10:00', '10:20', '10:40',
'11:00', '11:20', '11:40',
'14:00', '14:20', '14:40',
'15:00', '15:20', '15:40',
'16:00', '16:20', '16:40',
];
public function BookingPageAction(Request $request)
{
return $this->render('@BookingDemo/pages/book_demo.html.twig', [
'page_title' => 'Book a Demo — HoneyBee ERP',
]);
}
public function GetAvailableSlotsAction(Request $request, $date = '')
{
if (!$date || !preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) {
return new JsonResponse(['success' => false, 'slots' => []]);
}
$em = $this->getDoctrine()->getManager('company_group');
$dayStart = new \DateTime($date . ' 00:00:00');
$dayEnd = new \DateTime($date . ' 23:59:59');
$confirmedSlots = $em->getRepository('CompanyGroupBundle\Entity\DemoConfirmed')
->createQueryBuilder('c')
->where('c.confirmedStart >= :dayStart AND c.confirmedStart <= :dayEnd')
->setParameter('dayStart', $dayStart)
->setParameter('dayEnd', $dayEnd)
->getQuery()
->getResult();
$bookedTimes = [];
foreach ($confirmedSlots as $cs) {
$bookedTimes[] = $cs->getConfirmedStart()->format('H:i');
}
$now = new \DateTime();
$slots = [];
foreach (self::$slotHours as $time) {
$slotDt = new \DateTime($date . ' ' . $time . ':00');
if ($slotDt <= $now) continue;
$slots[] = [
'time' => $time,
'available' => !in_array($time, $bookedTimes),
];
}
return new JsonResponse(['success' => true, 'slots' => $slots]);
}
public function SubmitBookingAction(Request $request)
{
if (!$request->isMethod('POST')) {
return $this->redirectToRoute('book_demo_page');
}
$name = trim($request->request->get('name', ''));
$email = trim($request->request->get('email', ''));
$phone = trim($request->request->get('phone', ''));
$companyName = trim($request->request->get('company_name', ''));
$businessType = trim($request->request->get('business_type', ''));
$slots = $request->request->get('slots', []);
if (!$name || !filter_var($email, FILTER_VALIDATE_EMAIL) || empty($slots)) {
return new JsonResponse(['success' => false, 'message' => 'Please fill all required fields and select at least one slot.']);
}
$em = $this->getDoctrine()->getManager('company_group');
$demoRequest = new DemoRequest();
$demoRequest->setName($name)
->setEmail($email)
->setPhone($phone)
->setCompanyName($companyName)
->setBusinessType($businessType)
->setStatus('pending')
->setMeetingToken(bin2hex(random_bytes(24)));
$em->persist($demoRequest);
$em->flush();
$priority = 1;
foreach (array_slice($slots, 0, 3) as $slotStr) {
$parts = explode('|', $slotStr);
if (count($parts) !== 2) continue;
[$dateStr, $timeStr] = $parts;
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $dateStr)) continue;
if (!preg_match('/^\d{2}:\d{2}$/', $timeStr)) continue;
$start = new \DateTime($dateStr . ' ' . $timeStr . ':00');
$end = clone $start;
$end->modify('+20 minutes');
$slot = new DemoRequestSlot();
$slot->setRequestId($demoRequest->getId())
->setStartTime($start)
->setEndTime($end)
->setPriorityOrder($priority++);
$em->persist($slot);
}
$em->flush();
$this->sendPendingEmails($demoRequest, $em);
return new JsonResponse([
'success' => true,
'message' => 'Your demo request has been submitted! We will confirm shortly.',
]);
}
public function MeetingPageAction(Request $request, $token = '')
{
if (!$token) {
throw $this->createNotFoundException('Invalid meeting link.');
}
$em = $this->getDoctrine()->getManager('company_group');
$demoRequest = $em->getRepository('CompanyGroupBundle\Entity\DemoRequest')
->findOneBy(['meetingToken' => $token, 'status' => 'confirmed']);
if (!$demoRequest) {
throw $this->createNotFoundException('Meeting not found or not yet confirmed.');
}
$confirmed = $em->getRepository('CompanyGroupBundle\Entity\DemoConfirmed')
->findOneBy(['requestId' => $demoRequest->getId()]);
if (!$confirmed) {
throw $this->createNotFoundException('Confirmed meeting details not found.');
}
$now = new \DateTime();
$start = $confirmed->getConfirmedStart();
$end = $confirmed->getConfirmedEnd();
$phase = 'upcoming';
if ($now >= $start && $now <= $end) {
$phase = 'live';
} elseif ($now > $end) {
$phase = 'expired';
}
return $this->render('@BookingDemo/pages/meeting.html.twig', [
'page_title' => 'HoneyBee ERP Demo Meeting',
'demoRequest' => $demoRequest,
'confirmed' => $confirmed,
'phase' => $phase,
'startTs' => $start->getTimestamp() * 1000,
'endTs' => $end->getTimestamp() * 1000,
]);
}
private function getAdminEmails(): array
{
$default = ['emrul.hasan@ourhoneybee.eu', 'mozibul.yasser@ourhoneybee.eu'];
try {
$raw = $this->getParameter('demo_admin_emails');
if (!$raw) return $default;
$parsed = array_filter(array_map('trim', explode(',', $raw)));
return $parsed ?: $default;
} catch (\Exception $e) {
return $default;
}
}
private function smtpBase(): array
{
try {
return [
'senderHash' => '_CUSTOM_',
'smtpServer' => $this->getParameter('mailer_host'),
'smtpPort' => (int) $this->getParameter('mailer_port'),
'userName' => $this->getParameter('mailer_user'),
'password' => $this->getParameter('mailer_password'),
'fromAddress'=> $this->getParameter('mailer_user'),
];
} catch (\Exception $e) {
return ['senderHash' => '_DEFAULT_'];
}
}
private function sendPendingEmails(DemoRequest $demoRequest, $em)
{
try {
$mailModule = $this->get('mail_module');
$smtp = $this->smtpBase();
$mailModule->sendMyMail(array_merge($smtp, [
'toAddress' => $demoRequest->getEmail(),
'subject' => 'Your HoneyBee ERP Demo Request — Pending Confirmation',
'mailTemplate' => '@BookingDemo/email/booking_pending_user.html.twig',
'templateData' => [
'name' => $demoRequest->getName(),
'companyName' => $demoRequest->getCompanyName() ?: '',
],
]));
$subject = 'New Demo Request — ' . $demoRequest->getName() . ' (' . ($demoRequest->getCompanyName() ?: 'N/A') . ')';
$templateData = [
'demoRequest' => [
'id' => $demoRequest->getId(),
'name' => $demoRequest->getName(),
'email' => $demoRequest->getEmail(),
'phone' => $demoRequest->getPhone() ?: '',
'companyName' => $demoRequest->getCompanyName() ?: '',
'businessType' => $demoRequest->getBusinessType() ?: '',
],
];
foreach ($this->getAdminEmails() as $adminEmail) {
$mailModule->sendMyMail(array_merge($smtp, [
'toAddress' => $adminEmail,
'subject' => $subject,
'mailTemplate' => '@BookingDemo/email/booking_pending_admin.html.twig',
'templateData' => $templateData,
]));
}
} catch (\Exception $e) {
// Email failure must not break the booking flow
}
}
}