<?php

/**
 * 文件功能：婚姻系统消息监听器
 *
 * 监听 MarriageAccepted / WeddingCelebration / MarriageDivorced 三个事件，
 * 自动向聊天室推送并持久化系统消息（写入 Redis 缓存 + 落库 messages 表），
 * 使得用户重新登录时可在历史记录中看到这些通知。
 *
 * @author  ChatRoom Laravel
 *
 * @version 1.0.0
 */

namespace App\Listeners;

use App\Events\MarriageAccepted;
use App\Events\MarriageDivorced;
use App\Events\WeddingCelebration;
use App\Jobs\SaveMessageJob;
use App\Services\ChatStateService;
use Illuminate\Events\Dispatcher;

class SaveMarriageSystemMessage
{
    /** 固定使用房间 1（大厅）。 */
    private const ROOM_ID = 1;

    public function __construct(
        private readonly ChatStateService $chatState,
    ) {}

    /**
     * 注册所有监听的事件。
     */
    public function subscribe(Dispatcher $events): void
    {
        $events->listen(MarriageAccepted::class, [static::class, 'onMarriageAccepted']);
        $events->listen(WeddingCelebration::class, [static::class, 'onWeddingCelebration']);
        $events->listen(MarriageDivorced::class, [static::class, 'onMarriageDivorced']);
    }

    /**
     * 结婚成功 → 向全频道追加系统消息。
     */
    public function onMarriageAccepted(MarriageAccepted $event): void
    {
        $marriage = $event->marriage;
        $marriage->loadMissing(['user:id,username', 'partner:id,username', 'ringItem:id,name,icon']);

        $userName = $marriage->user?->username ?? '??';
        $partnerName = $marriage->partner?->username ?? '??';
        $ring = $marriage->ringItem?->name ?? '爱情之戒';

        $content = "💍 喜讯！【{$userName}】与【{$partnerName}】在 {$ring} 的见证下正式结为伴侣，祝新婚快乐！";

        $this->pushAndSave($content, '#ec4899');
    }

    /**
     * 婚礼庆典触发 → 向全频道追加婚礼公告消息。
     */
    public function onWeddingCelebration(WeddingCelebration $event): void
    {
        $ceremony = $event->ceremony;
        $marriage = $event->marriage;
        $marriage->loadMissing(['user:id,username', 'partner:id,username']);
        $ceremony->loadMissing('tier');

        $userName = $marriage->user?->username ?? '??';
        $partnerName = $marriage->partner?->username ?? '??';
        $tierName = $ceremony->tier?->name ?? '婚礼';
        $tierIcon = $ceremony->tier?->icon ?? '🎊';
        $amount = number_format((int) $ceremony->total_amount);

        $content = "{$tierIcon} 【{$userName}】与【{$partnerName}】举办了【{$tierName}】婚礼大典！"
            ."总计 💰{$amount} 金币红包已向全场分发，快去领取吧！";

        $this->pushAndSave($content, '#f59e0b');
    }

    /**
     * 离婚完成 → 向全频道追加离婚公告消息。
     */
    public function onMarriageDivorced(MarriageDivorced $event): void
    {
        $marriage = $event->marriage;
        $marriage->loadMissing(['user:id,username', 'partner:id,username']);

        $userName = $marriage->user?->username ?? '??';
        $partnerName = $marriage->partner?->username ?? '??';

        $typeLabel = match ($marriage->divorce_type) {
            'forced' => '强制离婚',
            'auto' => '超时自动离婚',
            'admin' => '管理员强制解除',
            default => '协议离婚',
        };

        $content = "💔 【{$userName}】与【{$partnerName}】已{$typeLabel}，缘分已尽，各奔东西。";

        $this->pushAndSave($content, '#6b7280');
    }

    /**
     * 将系统消息推入 Redis 缓存并分发 SaveMessageJob 落库。
     *
     * @param  string  $content  消息正文
     * @param  string  $fontColor  字体颜色
     */
    private function pushAndSave(string $content, string $fontColor): void
    {
        $msg = [
            'id' => $this->chatState->nextMessageId(self::ROOM_ID),
            'room_id' => self::ROOM_ID,
            'from_user' => '系统传音',
            'to_user' => '大家',
            'content' => $content,
            'is_secret' => false,
            'font_color' => $fontColor,
            'action' => '大声宣告',
            'sent_at' => now()->toDateTimeString(),
        ];

        // 推入 Redis（当前在线用户的 polling 会取到）
        $this->chatState->pushMessage(self::ROOM_ID, $msg);

        // 落库（离线用户下次登录可在历史消息中看到）
        SaveMessageJob::dispatch($msg);
    }
}
