<?php

namespace Core\App\Services;

use Core\App\Models\SecurityLog;
use Core\App\Models\TeamMeetingModel;
use Core\System\Mailer;

class MeetingReminderService
{
    private TeamMeetingModel $meetings;
    private Mailer $mailer;

    public function __construct()
    {
        $this->meetings = new TeamMeetingModel();
        $this->mailer   = new Mailer();
    }

    public function run(string $trigger = 'cron'): array
    {
        $this->log(sprintf('run started trigger=%s now_utc=%s', $trigger, gmdate('Y-m-d H:i:s')));

        $report = [
            'success' => true,
            'trigger' => $trigger,
            'due_meetings' => 0,
            'processed_meetings' => 0,
            'email_sent' => 0,
            'email_failed' => 0,
            'whatsapp_sent' => 0,
            'whatsapp_failed' => 0,
            'skipped' => [],
        ];

        $due = $this->meetings->claimDueReminders();
        $report['due_meetings'] = count($due);

        if (empty($due)) {
            $this->log(sprintf('no due meetings trigger=%s', $trigger));
            return $report;
        }

        $wa = WhatsAppService::fromSettings();
        $waEnabled = ($wa !== null && $wa->isEnabled('meeting_reminder'));
        $waTpl = $waEnabled ? $this->getWhatsappTemplate() : '';
        $mailTpl = $this->getReminderTemplateText();

        foreach ($due as $meeting) {
            $meetingId = (int)($meeting['id'] ?? 0);
            $title = (string)($meeting['title'] ?? '');
            $scheduledAt = (string)($meeting['scheduled_at'] ?? '');
            $dueAt = $this->computeDueAt($scheduledAt, (int)($meeting['reminder_minutes'] ?? 0));
            $minutesLeft = max(0, (int)floor((strtotime($scheduledAt . ' UTC') - time()) / 60));
            $meetingTimeLocal = app_format_datetime($scheduledAt, 'd/m/Y H:i', $scheduledAt);
            $storeName = $this->getStoreName();

            $this->log(sprintf(
                'meeting due meeting_id=%d trigger=%s scheduled_at_utc=%s due_at_utc=%s reminder_minutes=%d minutes_left=%d',
                $meetingId,
                $trigger,
                $scheduledAt,
                $dueAt,
                (int)($meeting['reminder_minutes'] ?? 0),
                $minutesLeft
            ));

            $attendeeIds = array_filter(array_map('intval', explode(',', (string)($meeting['attendee_ids'] ?? ''))));
            if (empty($attendeeIds)) {
                $report['skipped'][] = ['meeting_id' => $meetingId, 'reason' => 'no_attendees'];
                $this->log(sprintf('meeting skipped meeting_id=%d reason=no_attendees', $meetingId));
                continue;
            }

            $attendees = $this->meetings->getActiveReminderRecipients($meetingId, $attendeeIds);
            if (empty($attendees)) {
                $report['skipped'][] = ['meeting_id' => $meetingId, 'reason' => 'no_active_attendees'];
                $this->log(sprintf('meeting skipped meeting_id=%d reason=no_active_attendees', $meetingId));
                continue;
            }

            $report['processed_meetings']++;

            foreach ($attendees as $attendee) {
                $attendeeId = (int)($attendee['id'] ?? 0);
                $attendeeName = (string)($attendee['username'] ?? '');
                $attendeeEmail = trim((string)($attendee['email'] ?? ''));
                $attendeePhone = trim((string)($attendee['phone'] ?? ''));

                if ($attendeeEmail !== '') {
                    $subject = $this->buildReminderSubject($title);
                    $messageText = $this->buildReminderText($attendeeName, $title, $meetingTimeLocal, $minutesLeft, $storeName, $mailTpl);
                    $body = $this->buildEmailBody($messageText);
                    try {
                        $this->mailer->send($attendeeEmail, $subject, $body);
                        $report['email_sent']++;
                        $this->log(sprintf('email sent meeting_id=%d admin_id=%d email=%s', $meetingId, $attendeeId, $attendeeEmail));
                    } catch (\Throwable $e) {
                        $report['email_failed']++;
                        $this->log(sprintf('email failed meeting_id=%d admin_id=%d email=%s error=%s', $meetingId, $attendeeId, $attendeeEmail, $e->getMessage()));
                    }
                } else {
                    $report['skipped'][] = ['meeting_id' => $meetingId, 'admin_id' => $attendeeId, 'reason' => 'missing_email'];
                }

                if ($waEnabled && $waTpl !== '' && $attendeePhone !== '') {
                    $message = $this->buildReminderText($attendeeName, $title, $meetingTimeLocal, $minutesLeft, $storeName, $waTpl);

                    try {
                        $result = $wa->send($attendeePhone, $message, [
                            'event' => 'meeting_reminder',
                            'type'  => 'auto',
                        ]);

                        if (!empty($result['success'])) {
                            $report['whatsapp_sent']++;
                            $this->log(sprintf('whatsapp sent meeting_id=%d admin_id=%d phone=%s', $meetingId, $attendeeId, $attendeePhone));
                        } else {
                            $report['whatsapp_failed']++;
                            $this->log(sprintf('whatsapp failed meeting_id=%d admin_id=%d phone=%s error=%s', $meetingId, $attendeeId, $attendeePhone, (string)($result['error'] ?? 'unknown')));
                        }
                    } catch (\Throwable $e) {
                        $report['whatsapp_failed']++;
                        $this->log(sprintf('whatsapp failed meeting_id=%d admin_id=%d phone=%s error=%s', $meetingId, $attendeeId, $attendeePhone, $e->getMessage()));
                    }
                } elseif ($waEnabled && $attendeePhone === '') {
                    $report['skipped'][] = ['meeting_id' => $meetingId, 'admin_id' => $attendeeId, 'reason' => 'missing_phone'];
                } elseif ($waEnabled && $waTpl === '') {
                    $report['skipped'][] = ['meeting_id' => $meetingId, 'reason' => 'missing_whatsapp_template'];
                }
            }
        }

        $this->log(sprintf(
            'run finished trigger=%s due=%d processed=%d email_sent=%d email_failed=%d whatsapp_sent=%d whatsapp_failed=%d',
            $trigger,
            $report['due_meetings'],
            $report['processed_meetings'],
            $report['email_sent'],
            $report['email_failed'],
            $report['whatsapp_sent'],
            $report['whatsapp_failed']
        ));

        return $report;
    }

    private function buildEmailBody(string $messageText): string
    {
        return '<!DOCTYPE html><html><body style="font-family:sans-serif;padding:20px;color:#333;line-height:1.8">'
            . nl2br(htmlspecialchars($messageText, ENT_QUOTES, 'UTF-8'))
            . '</body></html>';
    }

    private function buildReminderSubject(string $title): string
    {
        return \Core\System\Language::code() === 'ar'
            ? ('📅 تذكير بالاجتماع: ' . $title)
            : ('📅 Meeting Reminder: ' . $title);
    }

    private function buildReminderText(string $attendeeName, string $title, string $meetingTimeLocal, int $minutesLeft, string $storeName, string $template): string
    {
        return str_replace(
            ['{attendee_name}', '{meeting_title}', '{meeting_time}', '{minutes_left}', '{store_name}'],
            [$attendeeName, $title, $meetingTimeLocal, (string)$minutesLeft, $storeName],
            $template
        );
    }

    private function getWhatsappTemplate(): string
    {
        return $this->getReminderTemplateText();
    }

    private function getReminderTemplateText(): string
    {
        try {
            $row = \db()->query("SELECT config FROM tracking_integrations WHERE provider='whatsapp' LIMIT 1")->fetch(\PDO::FETCH_ASSOC);
            $cfg = $row ? (json_decode((string)$row['config'], true) ?: []) : [];
            $template = trim((string)($cfg['templates']['meeting_reminder'] ?? ''));
            if ($template === '' || strpos($template, '{meeting_title}') === false || strpos($template, '{meeting_time}') === false) {
                return $this->defaultReminderTemplate();
            }

            return $template;
        } catch (\Throwable $e) {
            return $this->defaultReminderTemplate();
        }
    }

    private function defaultReminderTemplate(): string
    {
        return \Core\System\Language::code() === 'ar'
            ? "📅 تذكير بالاجتماع!
مرحبًا {attendee_name}، لديك اجتماع خلال {minutes_left} دقائق.
اجتماع: {meeting_title}
الوقت: {meeting_time}
نراكم هناك! 👋"
            : "📅 Meeting Reminder!
Hello {attendee_name}, you have a meeting in {minutes_left} minutes.
Meeting: {meeting_title}
Time: {meeting_time}
See you there! 👋";
    }

    private function getStoreName(): string
    {
        try {
            $stmt = \db()->prepare("SELECT setting_value FROM settings WHERE setting_key='site_name' LIMIT 1");
            $stmt->execute();
            return (string)($stmt->fetchColumn() ?: 'Store');
        } catch (\Throwable $e) {
            return 'Store';
        }
    }

    private function computeDueAt(string $scheduledAtUtc, int $reminderMinutes): string
    {
        try {
            $dt = new \DateTimeImmutable($scheduledAtUtc, new \DateTimeZone('UTC'));
            return $dt->modify('-' . max(0, $reminderMinutes) . ' minutes')->format('Y-m-d H:i:s');
        } catch (\Throwable $e) {
            return '';
        }
    }

    private function log(string $message): void
    {
        $isRoutine = strpos($message, 'run started') === 0
            || strpos($message, 'run finished') === 0
            || strpos($message, 'no due meetings') === 0;

        if ($isRoutine) {
            return;
        }

        SecurityLog::log('meeting_reminder', $message, '/cron/run');
        error_log('[meeting_reminder] ' . $message);
    }
}
