<?php

namespace App\Commands;

use App\Models\Control\TenantRecordModel;
use App\Models\GuestModel;
use App\Models\MessageLogModel;
use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\CLI;

/**
 * Batch job (same reasoning as SendPreArrivalReminders — not real-time)
 * that sends a birthday or anniversary offer to every guest whose
 * date_of_birth/anniversary_date falls on today's month+day. Meant to
 * run once a day via cron/Task Scheduler:
 *   php spark guests:send-birthday-offers
 *
 * Runs across every active tenant in one invocation, same as
 * SendPreArrivalReminders — each tenant uses its own message text
 * (Settings: marketing.birthday_offer_message/anniversary_offer_message)
 * and channel preference. A blacklisted guest is skipped — a hotel
 * doesn't send a discount offer to a guest they've flagged as a problem
 * account.
 *
 * "Already sent this year" is MessageLogModel::alreadySentThisYear(),
 * not a new tracking column — message_log already records every attempt
 * with a timestamp, same table every other outbound message uses.
 */
class SendBirthdayOffers extends BaseCommand
{
    protected $group       = 'Messaging';
    protected $name        = 'guests:send-birthday-offers';
    protected $description = 'Sends a birthday/anniversary offer (WhatsApp/SMS per tenant preference) to every guest whose date falls today.';

    private const DEFAULT_BIRTHDAY_MESSAGE    = 'Happy Birthday, {name}! Enjoy 15% off your next stay with us this month.';
    private const DEFAULT_ANNIVERSARY_MESSAGE = 'Happy Anniversary, {name}! Celebrate with a complimentary room upgrade on your next visit.';

    public function run(array $params)
    {
        $tenants = (new TenantRecordModel())->where('status', 'active')->findAll();

        foreach ($tenants as $tenant) {
            $this->sendForTenant($tenant);
        }
    }

    private function sendForTenant(object $tenant): void
    {
        service('tenantContext')->setTenant($tenant);

        $today = date('Y-m-d');
        $sent  = 0;

        $sent += $this->sendForColumn($tenant, 'date_of_birth', 'birthday_offer', self::DEFAULT_BIRTHDAY_MESSAGE, $today);
        $sent += $this->sendForColumn($tenant, 'anniversary_date', 'anniversary_offer', self::DEFAULT_ANNIVERSARY_MESSAGE, $today);

        if ($sent === 0) {
            CLI::write("{$tenant->slug}: no birthday/anniversary offers due.", 'white');

            return;
        }

        CLI::write("{$tenant->slug}: sent {$sent} offer(s).", 'green');
    }

    private function sendForColumn(object $tenant, string $dateColumn, string $messageType, string $defaultMessage, string $today): int
    {
        $guests = new GuestModel();

        // MONTH()/DAY() rather than a full date match — the year on file
        // is the guest's actual birth/anniversary year, never this year.
        $matches = $guests
            ->where('is_blacklisted', 0)
            ->where("MONTH({$dateColumn})", date('n', strtotime($today)), false)
            ->where("DAY({$dateColumn})", date('j', strtotime($today)), false)
            ->findAll();

        if ($matches === []) {
            return 0;
        }

        $messageLog = new MessageLogModel();
        $template   = service('settings')->get("marketing.{$messageType}_message") ?: $defaultMessage;
        $count      = 0;

        foreach ($matches as $guest) {
            if ($messageLog->alreadySentThisYear($guest->id, $messageType)) {
                continue;
            }

            $firstName = trim(explode(' ', $guest->full_name)[0] ?? $guest->full_name);
            $body      = str_replace('{name}', $firstName, $template);

            service('messagingService')->send($messageType, $guest->id, $guest->phone, $body, [$firstName]);

            $count++;
        }

        return $count;
    }
}
