<?php

namespace App\Notifications;

use App\Models\User;
use App\Notifications\Channels\FcmChannel;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Log;

abstract class HrmsNotification extends Notification
{
    /**
     * Category key from config/hrms_notifications.php (email preference group).
     */
    abstract public function notificationCategory(): string;

    /**
     * @return list<string>
     */
    abstract public function notificationSubject(): string;

    /**
     * @return list<string>
     */
    abstract public function notificationLines(): array;

    abstract public function actionUrl(): ?string;

    abstract public function actionLabel(): string;

    public function via(object $notifiable): array
    {
        $channels = ['database'];

        $wantsEmail = method_exists($notifiable, 'wantsEmailNotification')
            ? $notifiable->wantsEmailNotification($this->notificationCategory())
            : true;

        if (
            $wantsEmail
            && ! empty($notifiable->email)
            && filter_var($notifiable->email, FILTER_VALIDATE_EMAIL)
        ) {
            $channels[] = 'mail';
        }

        if ($this->notifiableHasFcmTokens($notifiable)) {
            $channels[] = FcmChannel::class;
        } elseif ($notifiable instanceof User) {
            Log::info('FCM channel omitted: user has no device_tokens.', [
                'user_id' => $notifiable->id,
                'notification' => static::class,
                'category' => $this->notificationCategory(),
            ]);
        }

        return $channels;
    }

    public function toMail(object $notifiable): MailMessage
    {
        $mail = (new MailMessage)->subject($this->notificationSubject());

        foreach ($this->notificationLines() as $line) {
            $mail->line($line);
        }

        if ($url = $this->actionUrl()) {
            $mail->action($this->actionLabel(), $url);
        }

        return $mail;
    }

    /**
     * Default FCM payload for TimeX; subclasses should override for typed deep links.
     *
     * @return array{title: string, body: string, data: array<string, string>}
     */
    public function toFcm(object $notifiable): array
    {
        $lines = $this->notificationLines();
        $body = $lines[0] ?? $this->notificationSubject();

        return [
            'title' => $this->notificationSubject(),
            'body' => $body,
            'data' => array_merge([
                'type' => $this->fcmType(),
                'route' => $this->fcmRoute(),
                'category' => $this->notificationCategory(),
            ], $this->fcmData()),
        ];
    }

    /**
     * Extra string data for the mobile client (ids, outcomes, etc.).
     *
     * @return array<string, string>
     */
    protected function fcmData(): array
    {
        return [];
    }

    protected function fcmType(): string
    {
        return 'hrms_notification';
    }

    protected function fcmRoute(): string
    {
        return '/dashboard';
    }

    protected function notifiableHasFcmTokens(object $notifiable): bool
    {
        if ($notifiable instanceof User) {
            return $notifiable->deviceTokens()->exists();
        }

        if (method_exists($notifiable, 'routeNotificationForFcm')) {
            $tokens = $notifiable->routeNotificationForFcm();

            return is_array($tokens) ? $tokens !== [] : (is_string($tokens) && $tokens !== '');
        }

        return false;
    }
}
