<?php

namespace App\Services;

use App\Laravue\Models\User;
use Illuminate\Support\Facades\Log;
use Minishlink\WebPush\WebPush;
use Minishlink\WebPush\Subscription;

/**
 * PWA Push Notification Service using minishlink/web-push
 * Pure PWA implementation without FCM dependency
 */
class PWAPushService
{
	private $publicKey;
	private $privateKey;
	private $subject;
	
	public function __construct()
	{
		$this->publicKey = config('services.pwa.public_key');
		$this->privateKey = config('services.pwa.private_key');
		$this->subject = config('services.pwa.subject', 'mailto:duyliemapt@gmail.com');
	}
	
	/**
	 * Send notification to a specific user
	 */
	public function sendNotificationToUser($userId, $title, $body, $data = [])
	{
		$user = User::find($userId);
		if (!$user || !$this->hasValidPWASubscription($user)) {
			Log::warning("User {$userId} has no valid PWA subscription");
			return false;
		}
		
		return $this->sendNotification($user, $title, $body, $data);
	}
	
	/**
	 * Send notification to multiple users
	 */
	public function sendNotificationToUsers($userIds, $title, $body, $data = [])
	{
		$users = User::whereIn('id', $userIds)
			->whereNotNull('pwa_endpoint')
			->whereNotNull('pwa_p256dh')
			->whereNotNull('pwa_auth')
			->where('push_notifications_enabled', true)
			->get();
		
		$results = [];
		foreach ($users as $user) {
			// Check if user should receive notification based on app state
			if ($this->shouldSendNotificationToUser($user, $data)) {
				$results[] = $this->sendNotification($user, $title, $body, $data);
			} else {
				Log::info("Skipping notification for user {$user->id} - app is active in chat");
			}
		}
		
		return $results;
	}
	
	/**
	 * Send notification using minishlink/web-push library
	 */
	private function sendNotification($user, $title, $body, $data = [])
	{
		try {
			if (!$this->hasValidPWASubscription($user)) {
				Log::warning("User {$user->id} has no valid PWA subscription");
				return false;
			}
			
			// Prepare notification payload
			$payload = json_encode([
				'title'              => $title,
				'body'               => $body,
				'icon'               => '/images/logo.png',
				'badge'              => '/images/logo.png',
				'tag'                => 'nakai-message-' . ($data['conversation_id'] ?? 'general'),
				'data'               => array_merge($data, [
					'timestamp' => time(),
					'url'       => $data['url'] ?? '/'
				]),
				'actions'            => [
					['action' => 'open', 'title' => '開く'],
					['action' => 'close', 'title' => '閉じる']
				],
				'requireInteraction' => false,
				'silent'             => false,
				'vibrate'            => [200, 100, 200]
			]);
			
			// Create WebPush instance with VAPID credentials
			$auth = [
				'VAPID' => [
					'subject' => $this->subject,
					'publicKey' => $this->publicKey,
					'privateKey' => $this->privateKey,
				]
			];
			
			$webPush = new WebPush($auth);
			
			// Create subscription object
			$subscription = Subscription::create([
				'endpoint' => $user->pwa_endpoint,
				'keys' => [
					'p256dh' => $user->pwa_p256dh,
					'auth' => $user->pwa_auth
				]
			]);
			
			// Send notification
			$report = $webPush->sendOneNotification($subscription, $payload);
			
			// Check result
			if ($report->isSuccess()) {
				Log::info("PWA notification sent successfully to user {$user->id}: {$title}");
				return true;
			} else {
				Log::error("Failed to send PWA notification to user {$user->id}: " . $report->getReason());
				
				// If subscription is invalid, remove it from database
				if ($report->isSubscriptionExpired()) {
					$this->removeExpiredSubscription($user);
				}
				
				return false;
			}
			
		} catch (\Exception $e) {
			Log::error("PWA notification error for user {$user->id}: " . $e->getMessage());
			return false;
		}
	}
	
	/**
	 * Remove expired subscription from user
	 */
	private function removeExpiredSubscription($user)
	{
		try {
			$user->pwa_endpoint = null;
			$user->pwa_p256dh = null;
			$user->pwa_auth = null;
			$user->push_notifications_enabled = false;
			$user->save();
			
			Log::info("Removed expired PWA subscription for user {$user->id}");
		} catch (\Exception $e) {
			Log::error("Failed to remove expired subscription for user {$user->id}: " . $e->getMessage());
		}
	}
	
	/**
	 * Check if user has valid PWA subscription
	 */
	private function hasValidPWASubscription($user)
	{
		return !empty($user->pwa_endpoint) &&
			!empty($user->pwa_p256dh) &&
			!empty($user->pwa_auth) &&
			$user->push_notifications_enabled;
	}
	
	/**
	 * Generate VAPID keys using web-push library
	 */
	public static function generateVAPIDKeys()
	{
		$keys = \Minishlink\WebPush\VAPID::createVapidKeys();
		
		return [
			'public_key'  => $keys['publicKey'],
			'private_key' => $keys['privateKey']
		];
	}
	
	/**
	 * Check if user should receive notification (not in active chat)
	 */
	private function shouldSendNotificationToUser($user, $data)
	{
		$conversationId = $data['conversation_id'] ?? null;
		
		if (!$conversationId) {
			return true; // Send notification if no conversation context
		}
		
		// Check if user is currently active in this conversation
		$cacheKey = "user_chat_active_{$user->id}";
		$userChatData = cache()->get($cacheKey);
		
		if ($userChatData) {
			$activeConversationId = $userChatData['conversation_id'] ?? null;
			$lastActivity = $userChatData['last_activity'] ?? 0;
			$isPageVisible = $userChatData['page_visible'] ?? false;
			
			// Check if activity is within last 2 minutes and page is visible
			$isRecentActivity = (time() - $lastActivity) < 120;
			$isSameConversation = $activeConversationId == $conversationId;
			
			if ($isRecentActivity && $isPageVisible && $isSameConversation) {
				Log::info("Skipping notification for user {$user->id} - actively chatting in conversation {$conversationId}");
				return false;
			}
		}
		
		return true;
	}
	
	/**
	 * Test PWA notification functionality
	 */
	public function testNotification($userId)
	{
		return $this->sendNotificationToUser(
			$userId,
			'NAKAI Chat - テスト通知',
			'PWA通知システムが正常に動作しています。',
			[
				'test' => true,
				'url' => '/',
				'timestamp' => time()
			]
		);
	}
}