<?php

namespace Kylin\Sms\Channels;

use Illuminate\Notifications\Notification;
use Kylin\Sms\Contracts\GatewayInterface;
use Kylin\Sms\Messages\SmsMessage;
use Kylin\Sms\SmsManager;

/**
 * 短信通知渠道
 * 
 * 扩展 Laravel 通知系统，支持通过短信发送通知
 * 使用方式：在通知类中定义 toSms 方法返回 SmsMessage 实例
 * 
 * 示例：
 * ```php
 * class VerificationCodeNotification extends Notification
 * {
 *     public function via($notifiable)
 *     {
 *         return ['sms'];
 *     }
 * 
 *     public function toSms($notifiable)
 *     {
 *         return SmsMessage::create()
 *             ->template('SMS_123456')
 *             ->withTemplateParams(['code' => '123456']);
 *     }
 * }
 * ```
 * 
 * @package Kylin\Sms\Channels
 */
class SmsChannel
{
    /**
     * 构造函数
     * 
     * @param SmsManager $smsManager 短信管理器实例
     */
    public function __construct(
        protected SmsManager $smsManager
    ) {}

    /**
     * 发送短信通知
     * 
     * 将通知转换为短信消息并发送
     * 
     * @param object $notifiable 可通知实体，通常是用户模型
     * @param Notification $notification 通知实例
     * @return array 发送结果
     * @throws \InvalidArgumentException 当通知未返回 SmsMessage 实例时抛出
     */
    public function send(object $notifiable, Notification $notification): array
    {
        $message = $notification->toSms($notifiable);

        if (!$message instanceof SmsMessage) {
            throw new \InvalidArgumentException('通知必须返回 SmsMessage 实例。');
        }

        $phone = $this->getPhone($notifiable, $notification);

        if (empty($phone)) {
            return [
                'success' => false,
                'error' => '未找到可通知实体的手机号码。',
            ];
        }

        if ($message->hasTemplate()) {
            return $this->smsManager->sendTemplate(
                $phone,
                $message->getTemplateId(),
                $message->getTemplateParams(),
                $message->getGateway()
            );
        }

        return $this->smsManager->send(
            $phone,
            $message->getContent(),
            $message->getData(),
            $message->getGateway()
        );
    }

    /**
     * 获取可通知实体的手机号
     * 
     * 按以下优先级获取手机号：
     * 1. 调用 notifiable 的 routeNotificationFor 方法
     * 2. 使用 notifiable 的 phone 属性
     * 3. 使用 notifiable 的 mobile 属性
     * 4. 使用 notifiable 的 phone_number 属性
     * 
     * @param object $notifiable 可通知实体
     * @param Notification $notification 通知实例
     * @return string|null 手机号，未找到时返回 null
     */
    protected function getPhone(object $notifiable, Notification $notification): ?string
    {
        if (method_exists($notifiable, 'routeNotificationFor')) {
            return $notifiable->routeNotificationFor('sms', $notification);
        }

        if (isset($notifiable->phone)) {
            return $notifiable->phone;
        }

        if (isset($notifiable->mobile)) {
            return $notifiable->mobile;
        }

        if (isset($notifiable->phone_number)) {
            return $notifiable->phone_number;
        }

        return null;
    }
}
