<?php
declare(strict_types=1);

/**
 * Booking request validation (sample project built to show the approach).
 * Returns a list of field => message errors; an empty array means the request is valid.
 */
final class Validator
{
    public const SERVICES = [
        'consult'  => ['label' => 'Systems consult (1 h)',        'price' => 120.00],
        'cleanup'  => ['label' => 'Spreadsheet cleanup (half day)', 'price' => 340.00],
        'workflow' => ['label' => 'Workflow automation (1 day)',   'price' => 680.00],
    ];
    public const OPEN_HOUR = 9;
    public const CLOSE_HOUR = 17;

    /** @param array<string,mixed> $in */
    public static function booking(array $in, DateTimeImmutable $now): array
    {
        $e = [];
        $name = trim((string)($in['name'] ?? ''));
        if ($name === '' || mb_strlen($name) < 2) $e['name'] = 'Please enter your name.';
        elseif (mb_strlen($name) > 80) $e['name'] = 'Name is too long (80 characters max).';

        $email = trim((string)($in['email'] ?? ''));
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) $e['email'] = 'Please enter a valid email address.';

        $service = (string)($in['service'] ?? '');
        if (!isset(self::SERVICES[$service])) $e['service'] = 'Please choose a service from the list.';

        $rawDate = (string)($in['date'] ?? '');
        $date = DateTimeImmutable::createFromFormat('!Y-m-d', $rawDate);
        if (!$date || $date->format('Y-m-d') !== $rawDate) $e['date'] = 'Please pick a real calendar date.';
        elseif ($date < $now->setTime(0, 0)->modify('+1 day')) $e['date'] = 'Bookings start from tomorrow.';
        elseif ((int)$date->format('N') >= 6) $e['date'] = 'Weekdays only (Monday to Friday).';

        $time = (string)($in['time'] ?? '');
        if (!preg_match('/^([01]\d|2[0-3]):(00|30)$/', $time)) $e['time'] = 'Pick a start time on the hour or half hour.';
        else {
            $h = (int)substr($time, 0, 2);
            if ($h < self::OPEN_HOUR || $h >= self::CLOSE_HOUR) $e['time'] = 'Start time must be between 09:00 and 16:30.';
        }

        $qty = filter_var($in['qty'] ?? '', FILTER_VALIDATE_INT, ['options' => ['min_range' => 1, 'max_range' => 10]]);
        if ($qty === false) $e['qty'] = 'Quantity must be a whole number from 1 to 10.';

        $notes = (string)($in['notes'] ?? '');
        if (mb_strlen($notes) > 500) $e['notes'] = 'Notes are limited to 500 characters.';

        if (($in['website'] ?? '') !== '') $e['form'] = 'Submission rejected.'; // honeypot field
        return $e;
    }
}
