/**
 * Firebase Push Notification Utility
 * Initializes Firebase Admin SDK and provides FCM push sending
 */
const admin = require('firebase-admin');
const path = require('path');
const logger = require('./logger');

// Initialize Firebase Admin SDK (only once)
let initialized = false;

function initFirebase() {
    if (initialized) return;
    try {
        let serviceAccount;
        const fs = require('fs');

        if (process.env.FIREBASE_SERVICE_ACCOUNT_JSON) {
            // Load from JSON string in environment variable
            serviceAccount = JSON.parse(process.env.FIREBASE_SERVICE_ACCOUNT_JSON);
        } else if (process.env.FIREBASE_SERVICE_ACCOUNT_PATH) {
            // Load from file path specified in environment variable
            const resolvedPath = path.resolve(process.env.FIREBASE_SERVICE_ACCOUNT_PATH);
            serviceAccount = JSON.parse(fs.readFileSync(resolvedPath, 'utf8'));
        } else {
            // Auto-detect: look for firebase-adminsdk file in project root
            const projectRoot = path.join(__dirname, '..');
            const files = fs.readdirSync(projectRoot).filter(f => f.includes('firebase-adminsdk') && f.endsWith('.json'));
            if (files.length > 0) {
                const filePath = path.join(projectRoot, files[0]);
                serviceAccount = JSON.parse(fs.readFileSync(filePath, 'utf8'));
                logger.info({ file: files[0] }, 'Firebase service account auto-detected from project root');
            } else {
                logger.warn('Firebase service account not configured. Set FIREBASE_SERVICE_ACCOUNT_PATH or place firebase-adminsdk*.json in project root.');
                return;
            }
        }

        admin.initializeApp({
            credential: admin.credential.cert(serviceAccount),
            projectId: serviceAccount.project_id
        });

        initialized = true;
        logger.info('Firebase Admin SDK initialized successfully');
    } catch (error) {
        logger.error({ err: error }, 'Firebase Admin init failed');
    }
}

// Initialize on load
initFirebase();

/**
 * Send FCM Push Notification to a specific user
 * @param {string} fcmToken - User's FCM device token
 * @param {string} title - Notification title
 * @param {string} body - Notification body/message
 * @param {object} data - Optional data payload (for deep linking)
 * @returns {Promise<boolean>} success
 */
async function sendPush(fcmToken, title, body, data = {}) {
    if (!initialized || !fcmToken) return false;

    try {
        const message = {
            token: fcmToken,
            notification: {
                title,
                body,
                // 🖼️ Large image shown in notification shade (Android 13+, web)
                imageUrl: 'https://wassili.site/logo-transparent.png'
            },
            data: {
                ...Object.fromEntries(
                    Object.entries(data).map(([k, v]) => [k, String(v)])
                ),
                click_action: 'FLUTTER_NOTIFICATION_CLICK',
                // ✅ BigText: send full text in data so WassiliFCMService builds expandable notification
                notif_title: String(title),
                notif_body:  String(body)   // full text — no substring truncation
            },
            android: {
                priority: 'high',
                notification: {
                    sound: 'wassili_bell',
                    channelId: 'wassili_notifications',
                    color: '#0a8754',
                    imageUrl: 'https://wassili.site/icons/icon-192x192.png'
                }
            },
            apns: {
                payload: {
                    aps: {
                        sound: 'wassili_bell.wav',
                        badge: 1
                    }
                },
                fcmOptions: {
                    imageUrl: 'https://wassili.site/icons/icon-192x192.png'
                }
            },
            // Web push (PWA in browser)
            webpush: {
                notification: {
                    icon: 'https://wassili.site/icons/icon-192x192.png',
                    vibrate: [200, 100, 200]
                },
                fcmOptions: {
                    link: 'https://wassili.site/'
                }
            }
        };

        const response = await admin.messaging().send(message);
        logger.debug({ title, response }, 'FCM Push sent');
        return true;
    } catch (error) {
        // Token expired or invalid — clean it up
        if (error.code === 'messaging/registration-token-not-registered' ||
            error.code === 'messaging/invalid-registration-token') {
            logger.warn({ token: fcmToken.substring(0, 20) }, 'Invalid FCM token — auto-removing from DB');
            try {
                const User = require('../models/User');
                await User.findOneAndUpdate({ fcmToken }, { $unset: { fcmToken: '' } });
            } catch (cleanErr) {
                logger.warn({ err: cleanErr }, 'Failed to auto-remove invalid FCM token');
            }
        } else {
            logger.error({ err: error }, 'FCM Push error — retrying in 2s');
            // ✅ Retry once for transient network/server errors
            try {
                await new Promise(r => setTimeout(r, 2000));
                const response = await admin.messaging().send(message);
                logger.info({ title, response }, 'FCM Push sent on retry ✅');
                return true;
            } catch (retryErr) {
                logger.error({ err: retryErr }, 'FCM Push retry also failed');
            }
        }
        return false;
    }
}

/**
 * Send FCM Push to multiple users
 * @param {string[]} fcmTokens - Array of FCM tokens
 * @param {string} title
 * @param {string} body
 * @param {object} data
 * @returns {Promise<{success: number, failure: number}>}
 */
async function sendPushToMany(fcmTokens, title, body, data = {}) {
    if (!initialized || !fcmTokens || fcmTokens.length === 0) {
        return { success: 0, failure: 0 };
    }

    // Filter out empty/null tokens
    const validTokens = fcmTokens.filter(t => t && t.length > 10);
    if (validTokens.length === 0) return { success: 0, failure: 0 };

    try {
        const message = {
            notification: {
                title,
                body
            },
            data: {
                ...Object.fromEntries(
                    Object.entries(data).map(([k, v]) => [k, String(v)])
                ),
                // ✅ BigText: full text for expandable notification on Android
                notif_title: String(title),
                notif_body:  String(body)
            },
            android: {
                priority: 'high',
                notification: {
                    sound: 'wassili_bell',
                    channelId: 'wassili_notifications',
                    color: '#0a8754',
                    imageUrl: 'https://wassili.site/icons/icon-192x192.png'
                }
            },
            apns: {
                payload: { aps: { sound: 'wassili_bell.wav', badge: 1 } },
                fcmOptions: { imageUrl: 'https://wassili.site/icons/icon-192x192.png' }
            },
            webpush: {
                notification: {
                    icon: 'https://wassili.site/icons/icon-192x192.png'
                },
                fcmOptions: { link: 'https://wassili.site/' }
            }
        };

        const response = await admin.messaging().sendEachForMulticast({
            tokens: validTokens,
            ...message
        });

        logger.info(`📤 FCM Multicast: ${response.successCount} sent, ${response.failureCount} failed`);
        return { success: response.successCount, failure: response.failureCount };
    } catch (error) {
        logger.error('❌ FCM Multicast error:', error.message);
        return { success: 0, failure: validTokens.length };
    }
}

/**
 * Send FCM Chat Push Notification — Uses dedicated `chat_alerts` channel for chat sounds
 * @param {string} fcmToken
 * @param {string} title
 * @param {string} body
 * @param {object} data  Must include orderId, senderId, senderName
 */
async function sendChatPush(fcmToken, title, body, data = {}) {
    if (!initialized || !fcmToken) return false;

    try {
        const message = {
            token: fcmToken,
            notification: { title, body },
            data: {
                ...Object.fromEntries(
                    Object.entries(data).map(([k, v]) => [k, String(v)])
                ),
                click_action: 'FLUTTER_NOTIFICATION_CLICK'
            },
            android: {
                priority: 'high',
                notification: {
                    sound: 'wassili_bell',
                    // Dedicated channel so Android can apply custom sound/vibration
                    channelId: 'chat_alerts',
                    // icon: 'ic_notification',
                    color: '#6f42c1',
                    tag: data.orderId ? `chat_${data.orderId}` : undefined
                }
            },
            apns: {
                payload: { aps: { sound: 'wassili_bell.wav', badge: 1 } },
                fcmOptions: { imageUrl: 'https://wassili.site/icons/icon-192x192.png' }
            },
            webpush: {
                notification: {
                    icon: 'https://wassili.site/icons/icon-192x192.png',
                    tag: data.orderId ? `chat_${data.orderId}` : undefined, // Collapses multiple notifications
                    renotify: true
                },
                fcmOptions: {
                    link: data.orderId ? `https://wassili.site/chat.html?orderId=${data.orderId}` : 'https://wassili.site/'
                }
            }
        };

        const response = await admin.messaging().send(message);
        logger.info(`💬 Chat FCM Push sent: ${title} → ${response}`);
        return true;
    } catch (error) {
        if (error.code === 'messaging/registration-token-not-registered' ||
            error.code === 'messaging/invalid-registration-token') {
            logger.warn(`⚠️ Invalid FCM token (chat) — auto-removing: ${fcmToken.substring(0, 20)}...`);
            try {
                const User = require('../models/User');
                await User.findOneAndUpdate({ fcmToken }, { $unset: { fcmToken: '' } });
            } catch (cleanErr) {
                logger.warn({ err: cleanErr }, 'Failed to auto-remove invalid chat FCM token');
            }
        } else {
            logger.error('❌ Chat FCM Push error:', error.message);
        }
        return false;
    }
}

/**
 * Send FCM Push to Admins (with distinct channel, sound, and color)
 */
async function sendAdminPushToMany(fcmTokens, title, body, data = {}) {
    if (!initialized || !fcmTokens || fcmTokens.length === 0) {
        return { success: 0, failure: 0 };
    }

    const validTokens = fcmTokens.filter(t => t && t.length > 10);
    if (validTokens.length === 0) return { success: 0, failure: 0 };

    try {
        const message = {
            notification: {
                title,
                body
            },
            data: {
                ...Object.fromEntries(
                    Object.entries(data).map(([k, v]) => [k, String(v)])
                ),
                // ✅ BigText: full text for expandable notification on Android
                notif_title: String(title),
                notif_body:  String(body)
            },
            android: {
                priority: 'high',
                notification: {
                    sound: 'wassili_bell',
                    channelId: 'admin_alerts',
                    color: '#dc3545',
                    imageUrl: 'https://wassili.site/icons/icon-192x192.png'
                }
            },
            apns: {
                payload: { aps: { sound: 'wassili_bell.wav', badge: 1 } },
                fcmOptions: { imageUrl: 'https://wassili.site/icons/icon-192x192.png' }
            },
            webpush: {
                notification: {
                    icon: 'https://wassili.site/icons/icon-192x192.png'
                },
                fcmOptions: { link: 'https://wassili.site/' }
            }
        };

        const response = await admin.messaging().sendEachForMulticast({
            tokens: validTokens,
            ...message
        });

        logger.info(`📤 FCM Admin Multicast: ${response.successCount} sent, ${response.failureCount} failed`);
        return { success: response.successCount, failure: response.failureCount };
    } catch (error) {
        logger.error('❌ FCM Admin Multicast error:', error.message);
        return { success: 0, failure: validTokens.length };
    }
}

module.exports = { sendPush, sendPushToMany, sendChatPush, sendAdminPushToMany, initFirebase };
