import { beforeEach, describe, expect, it, vi } from "vitest"
import { PushAppState, PushPlatform } from "@prisma/client"

const { pushServiceMock, pushFcmServiceMock } = vi.hoisted(() => ({
    pushServiceMock: {
        listEligibleInstallations: vi.fn(),
        markPushDelivered: vi.fn(),
        markPushFailure: vi.fn(),
    },
    pushFcmServiceMock: {
        sendDataMessage: vi.fn(),
    },
}))

const { shopEventServiceMock } = vi.hoisted(() => ({
    shopEventServiceMock: {
        createEvent: vi.fn(),
    },
}))

vi.mock("./push.service", () => ({
    pushService: pushServiceMock,
}))

vi.mock("./push-fcm.service", () => ({
    pushFcmService: pushFcmServiceMock,
}))

vi.mock("@/modules/shop/shop-event.service", () => ({
    shopEventService: shopEventServiceMock,
}))

import { posPushDispatchService } from "./push-dispatch.service"

describe("posPushDispatchService", () => {
    beforeEach(() => {
        vi.clearAllMocks()
    })

    it("n'envoie aucun push si une installation du user est en foreground", async () => {
        pushServiceMock.listEligibleInstallations.mockResolvedValue([
            {
                id: "install-1",
                shopId: "shop-1",
                shopUserId: "user-1",
                terminalId: "terminal-1",
                fcmToken: "token-1",
                platform: PushPlatform.ANDROID,
                appVersion: "1.0.0",
                isActive: true,
                appState: PushAppState.FOREGROUND,
                lastSeenAt: new Date(),
                createdAt: new Date(),
                updatedAt: new Date(),
            },
        ])

        const result = await posPushDispatchService.dispatchOrderItemReady({
            shopId: "shop-1",
            orderId: "order-1",
            orderItemId: "item-1",
            targetShopUserId: "user-1",
        })

        expect(pushFcmServiceMock.sendDataMessage).not.toHaveBeenCalled()
        expect(result.decision).toBe("SKIP_FOREGROUND_PRESENT")
    })

    it("envoie aux installations background et désactive les tokens invalides", async () => {
        pushServiceMock.listEligibleInstallations.mockResolvedValue([
            {
                id: "install-1",
                shopId: "shop-1",
                shopUserId: "user-1",
                terminalId: "terminal-1",
                fcmToken: "token-1",
                platform: PushPlatform.ANDROID,
                appVersion: "1.0.0",
                isActive: true,
                appState: PushAppState.BACKGROUND,
                lastSeenAt: new Date(),
                createdAt: new Date(),
                updatedAt: new Date(),
            },
            {
                id: "install-2",
                shopId: "shop-1",
                shopUserId: "user-1",
                terminalId: "terminal-2",
                fcmToken: "token-2",
                platform: PushPlatform.ANDROID,
                appVersion: "1.0.0",
                isActive: true,
                appState: PushAppState.UNKNOWN,
                lastSeenAt: new Date(),
                createdAt: new Date(),
                updatedAt: new Date(),
            },
        ])
        pushFcmServiceMock.sendDataMessage.mockResolvedValue({
            mode: "sent",
            reason: null,
            successCount: 1,
            failureCount: 1,
            results: [
                { token: "token-1", success: true, invalidToken: false, errorCode: null },
                { token: "token-2", success: false, invalidToken: true, errorCode: "messaging/registration-token-not-registered" },
            ],
        })

        const result = await posPushDispatchService.dispatchOrderItemReady({
            shopId: "shop-1",
            orderId: "order-1",
            orderItemId: "item-1",
            targetShopUserId: "user-1",
            productLabel: "Burger Classic",
            orderShortId: "#42",
            readyStationId: "station-prod-1",
            readyStationName: "Grill",
            cashStationId: "station-cash-1",
        })

        expect(pushFcmServiceMock.sendDataMessage).toHaveBeenCalledWith({
            tokens: ["token-1", "token-2"],
            data: {
                event: "order_item_ready",
                pushSchemaVersion: "2",
                shopId: "shop-1",
                orderId: "order-1",
                orderItemId: "item-1",
                targetShopUserId: "user-1",
                productLabel: "Burger Classic",
                orderShortId: "#42",
                readyStationId: "station-prod-1",
                readyStationName: "Grill",
                cashierStationId: "station-cash-1",
                notificationTitle: "Produit prêt · #42",
                notificationBody: "Burger Classic prêt à Grill",
                clickAction: "open_cashier_order_detail",
                targetRouteName: "cashier-order-detail",
                targetRoutePath: "/pos/stations/cashier/orders/order-1?stationId=station-cash-1",
                targetPhase: "order-detail",
                targetOrderId: "order-1",
                targetStationId: "station-cash-1",
            },
        })
        expect(pushServiceMock.markPushDelivered).toHaveBeenCalledWith("install-1", "order_item_ready")
        expect(pushServiceMock.markPushFailure).toHaveBeenCalledWith(
            "install-2",
            "messaging/registration-token-not-registered",
            true,
        )
        expect(result.decision).toBe("SEND")
    })
})


