/***********************************************
* Unified Real Backend with DUAL Result System
* Games: Use result from frontend | Matches: Pending until admin decision
* Added: Auto match result update system & Improved error handling
***********************************************/
const SHEET_ID = "1FBkBJGNY_d_PZ45VlSV7zFejRP8tfX59P0Y41rjQ4HU";
/* ---------- entry point ---------- */
function doPost(e){
try{
const payload = JSON.parse(e.postData.contents || "{}");
const action = (payload.action||"").toString();
const ss = SpreadsheetApp.openById(SHEET_ID);
ensureSheets(ss);
switch(action){
case "register": return json(registerUser(ss,payload));
case "login": return json(loginUser(ss,payload));
case "get_matches": return json(getMatches(ss));
case "get_games": return json(getGames(ss));
case "record_result": return json(recordResult(ss,payload));
case "get_bets": return json(getBets(ss,payload));
case "get_pending_bets": return json(getPendingBets(ss));
case "update_bet_status": return json(updateBetStatus(ss,payload));
case "get_balance": return json(getBalance(ss,payload));
case "add_match": return json(addMatch(ss,payload));
case "get_messages": return json(getMessages(ss,payload));
case "send_message": return json(sendMessage(ss,payload));
case "send_message_to_all": return json(sendMessageToAll(ss,payload));
case "get_notifications": return json(getNotifications(ss,payload));
case "get_profile": return json(getProfile(ss,payload));
case "save_settings": return json(saveSettings(ss,payload));
case "update_match_result": return json(updateMatchResult(ss,payload));
case "test_connection": return json(testConnection(ss, payload)); // ⬅ الجديدة
default:
return json({status:"error", message:"Action not found"});
}
}catch(err){
return json({status:"error", message: (err && err.message) ? err.message : String(err)});
}
}
function json(obj){ return ContentService.createTextOutput(JSON.stringify(obj)).setMimeType(ContentService.MimeType.JSON); }
/* ---------- ensure sheets & headers ---------- */
function ensureSheets(ss){
getOrCreateSheetWithHeaders(ss,"users",["UserId","Name","Phone","Password","Coins","Token","CreatedAt"]);
getOrCreateSheetWithHeaders(ss,"matches",["MatchId","TeamA","TeamB","StartTime","Status","Note","BetType1","Odds1","BetType2","Odds2","BetType3","Odds3"]);
getOrCreateSheetWithHeaders(ss,"games",["GameId","Title","URL","Category","Status","Note"]);
getOrCreateSheetWithHeaders(ss,"bets",["BetId","Timestamp","UserId","MatchOrGame","BetType","Stake","Odds","PotentialWin","Result","Duration","BalanceAfter","TeamA","TeamB","SellPrice","Type","AutoResult"]);
getOrCreateSheetWithHeaders(ss,"messages",["Timestamp","FromUser","ToUser","Text","Read"]);
getOrCreateSheetWithHeaders(ss,"notifications",["Timestamp","UserId","Message","Read"]);
}
function getOrCreateSheetWithHeaders(ss,name,headers){
let sh = ss.getSheetByName(name);
if(!sh){
sh = ss.insertSheet(name);
sh.getRange(1,1,1,headers.length).setValues([headers]);
return sh;
}
const existing = sh.getRange(1,1,1, Math.max(headers.length, sh.getLastColumn()||1)).getValues()[0];
const empty = existing.every(c => c === "" || c === undefined);
if(empty){
sh.getRange(1,1,1,headers.length).setValues([headers]);
}
return sh;
}
function makeId(prefix){
return (prefix||"id") + "_" + (new Date().getTime()) + "_" + Math.floor(Math.random()*9000+1000);
}
/* ---------- Users ---------- */
function registerUser(ss, data){
const users = ss.getSheetByName("users");
const rows = users.getDataRange().getValues();
const phone = (data.phone||"").toString().trim();
const name = (data.name||"").toString().trim();
const password = (data.password||"").toString();
if(!phone || !password) return {status:"error", message:"phone and password required"};
for(let i=1;i