File size: 6,416 Bytes
ea81969
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154

import { db } from '@/backend/services/firebase';

export const CreditService = {
    async checkEligibility(sessionId, guestId, toolKey, isOwnKey, creditCostOverride = null) {
        if (!sessionId) throw new Error("Authentication failed.");

        const now = new Date();
        const today = now.toLocaleDateString('en-CA'); 
        const usageKey = isOwnKey ? `own_${toolKey}` : `app_${toolKey}`;

        // 1. Fetch System Tier Settings
        const sysSnapshot = await db.ref('system/settings/tiers').once('value');
        const tiers = sysSnapshot.val() || {};

        const toolMapper = {
            'count_transcript': 'transcript',
            'count_translate': 'translate',
            'count_srt_translate': 'srt_translator',
            'count_tts': 'tts',
            'count_subtitle': 'subtitle_gen',
            'count_creator_text': 'content_creator',
            'count_creator_image': 'ai_image',
            'downloader': 'downloader',
            'book_recap': 'book_recap'
        };
        const tierToolKey = toolMapper[toolKey] || toolKey;

        let userKey, userData, userClass, storagePath;

        if (sessionId === 'free_access') {
            userClass = 'FREE';
            if (!guestId || guestId === 'anonymous') {
                // Return generic guest data for free mode
                userData = { Usage: {}, Credits: 0, Class: 'FREE', Last_Usage_Date: today };
                storagePath = `guests/temp_guest`;
            } else {
                storagePath = `guests/${guestId}/${today}`;
                const usageSnapshot = await db.ref(storagePath).once('value');
                const currentUsage = usageSnapshot.val() || {};
                userData = { Usage: currentUsage, Credits: 0, Class: 'FREE', Last_Usage_Date: today };
            }
        } else {
            // Find user by temporary session ID
            const snapshot = await db.ref('users').orderByChild('Active_Session_ID').equalTo(sessionId).once('value');
            if (!snapshot.exists()) throw new Error("Invalid Session. Please login again.");
            
            userKey = Object.keys(snapshot.val())[0];
            userData = snapshot.val()[userKey];
            if (userData.Status !== 'ACTIVE') throw new Error("Account suspended.");
            
            userClass = userData.Class === 'MEMBER+' ? 'MEMBER_PLUS' : (userData.Class === 'BASIC' ? 'BASIC' : 'MEMBER');
            storagePath = `users/${userKey}`;
        }

        const tierConfig = tiers[userClass] || { apiAccess: { app: true, own: true } };

        // Check if user is trying to use their own API but it's disabled for their class
        if (isOwnKey && tierConfig.apiAccess?.own === false) throw new Error("OWN_API_RESTRICTED");
        if (!isOwnKey && tierConfig.apiAccess?.app === false) throw new Error("APP_API_RESTRICTED");

        // Check Specific Tool Toggle (Mode Specific)
        const toolToggleMap = isOwnKey ? (tierConfig.ownTools || {}) : (tierConfig.tools || {});
        if (toolToggleMap[tierToolKey] === false) throw new Error("TOOL_DISABLED");

const usage = (userData.Last_Usage_Date === today) ? (userData.Usage || {}) : {};
        
        // 1. Declare the limit variable based on the tier settings
        let limit = isOwnKey 
            ? (tierConfig.ownLimits?.[tierToolKey] ?? -1) 
            : (tierConfig.limits?.[tierToolKey] ?? -1);
        
        // 2. Override: If using Own API Key, force the limit to -1 (Unlimited)
        if (isOwnKey) {
            limit = -1; 
        }
        
        // 3. Perform the check only if a limit exists
        if (limit !== -1) {
            const currentCount = parseInt(usage[usageKey] || 0);
            if (currentCount >= limit) {
                throw new Error("DAILY_LIMIT_REACHED");
            }
        }

        if (isOwnKey) {
            limit = -1; // -1 means "No Limit" or "Unlimited" in your logic (LOL kyaw Gyi)
        }        
        
        // Check Daily Frequency Limit (Mode Specific)
 //       let limit = isOwnKey ? (tierConfig.ownLimits?.[tierToolKey] ?? -1) : (tierConfig.limits?.[tierToolKey] ?? -1);
        
        
        if (limit !== -1) {
            const currentCount = parseInt(usage[usageKey] || 0);
            if (currentCount >= limit) throw new Error("DAILY_LIMIT_REACHED");
        }

        let cost = 0;
        if (userClass !== 'FREE' && !isOwnKey) {
            const costMap = {
                'count_transcript': 4, 
                'count_translate': 4, 
                'count_srt_translate': 7,
                'count_tts': 3, 
                'count_subtitle': 2, 
                'count_creator_text': 3, 
                'count_creator_image': 5,
                'downloader': 2,
                'book_recap': 8
            };
            
            cost = (creditCostOverride !== null) ? creditCostOverride : (costMap[toolKey] || 1);

            if (cost > 0 && (userData.Credits || 0) < cost) {
                throw new Error(`INSUFFICIENT_BALANCE: Needs ${cost} credits.`);
            }
        }

        return { userKey, storagePath, userData, usageKey, cost, today, isGuest: (userClass === 'FREE'), isOwnKey };
    },

    async commitDeduction(eligibilityData) {
        if (!eligibilityData) return;
        const { storagePath, userData, usageKey, cost, today, isGuest, isOwnKey } = eligibilityData;
        
        // Own API mode records usage but never deducts credits
        const finalCost = isOwnKey ? 0 : cost;

        const updates = {};
        if (isGuest) {
            if (storagePath === 'guests/temp_guest') return;
            const currentUsage = (userData.Usage?.[usageKey]) || 0;
            updates[`${storagePath}/${usageKey}`] = currentUsage + 1;
            await db.ref().update(updates);
            return;
        }

        if (finalCost > 0) {
            const newBalance = (userData.Credits || 0) - finalCost;
            updates[`${storagePath}/Credits`] = Math.max(0, newBalance);
        }

        if (userData.Last_Usage_Date !== today) {
            updates[`${storagePath}/Last_Usage_Date`] = today;
            updates[`${storagePath}/Usage`] = { [usageKey]: 1 };
        } else {
            const currentUsage = (userData.Usage?.[usageKey]) || 0;
            updates[`${storagePath}/Usage/${usageKey}`] = currentUsage + 1;
        }
        await db.ref().update(updates);
    }
};