Files
Siro/siro_admin/lib/controller/admin/marketing_controller.dart
2026-06-26 17:29:23 +03:00

337 lines
9.3 KiB
Dart

import 'package:get/get.dart';
import '../../constant/links.dart';
import '../../views/widgets/snackbar.dart';
import '../functions/crud.dart';
class MarketingController extends GetxController {
bool isLoading = false;
List priceAnomalies = [];
List campaignsLog = [];
// --- Dynamic Dashboard Configurations ---
String selectedCountry = 'All'; // 'All', 'SY', 'JO', 'EG', 'IQ'
bool isAutopilotEnabled = true;
String systemPrompt = "أنت المحلل الذكي لتطبيق Siro لخدمات نقل الركاب. قمنا برصد قراءات أسعار المنافسين لتقديم عروض وحملات تسويقية ملائمة ومخصصة.";
// --- AI API Token & Cost Telemetry ---
int apiRequestsCount = 0;
int totalTokensUsed = 0;
double estimatedCostUSD = 0.0;
// --- Price Comparison Data ---
List hourlyPriceData = [];
List pciRegions = [];
Map siroBasePrices = {};
// --- Country Selection Handler ---
void changeCountry(String countryCode) {
selectedCountry = countryCode;
fetchAnomalies();
fetchCampaignsLog();
fetchPriceComparison();
fetchPriceGapHeatmap();
fetchMarketShareAnalytics();
fetchAiPricePrediction();
fetchWinbackTargets();
}
// --- Autopilot Status Toggle ---
void toggleAutopilot(bool value) {
isAutopilotEnabled = value;
update();
mySnackbarInfo(value ? "Full Autopilot mode enabled".tr : "Approval Mode enabled".tr);
}
// --- System Prompt Configuration Saver ---
void savePrompt(String newPrompt) {
systemPrompt = newPrompt;
update();
mySnackbarSuccess("Gemini system instructions updated successfully".tr);
}
Future<void> fetchAnomalies() async {
isLoading = true;
update();
try {
Map<String, dynamic> params = {};
if (selectedCountry != 'All') {
params['country_code'] = selectedCountry;
}
var res = await CRUD().post(
link: AppLink.getMarketAnomalies,
payload: params,
);
if (res is Map && res['status'] == 'success') {
priceAnomalies = res['message'] ?? [];
} else {
mySnackbarError("Failed to fetch price anomalies");
}
} catch (e) {
mySnackbarError("Network error while loading anomalies");
} finally {
isLoading = false;
update();
}
}
Future<void> fetchTelemetry() async {
try {
Map<String, dynamic> params = {};
if (selectedCountry != 'All') {
params['country_code'] = selectedCountry;
}
var res = await CRUD().post(
link: AppLink.getTelemetry,
payload: params,
);
if (res is Map && res['status'] == 'success') {
final data = res['message'];
if (data is Map) {
apiRequestsCount = data['api_requests_count'] ?? 0;
totalTokensUsed = data['total_tokens_used'] ?? 0;
estimatedCostUSD = (data['estimated_cost_usd'] ?? 0.0).toDouble();
update();
}
}
} catch (e) {
// Silently fail — telemetry is non-critical
}
}
Future<void> fetchCampaignsLog() async {
isLoading = true;
update();
try {
Map<String, dynamic> params = {};
if (selectedCountry != 'All') {
params['country_code'] = selectedCountry;
}
var res = await CRUD().post(
link: AppLink.getCampaignsLog,
payload: params,
);
if (res is Map && res['status'] == 'success') {
campaignsLog = res['message'] ?? [];
} else {
mySnackbarError("Failed to fetch campaign logs");
}
} catch (e) {
mySnackbarError("Network error while loading campaign logs");
} finally {
isLoading = false;
update();
}
}
Future<void> fetchPriceComparison() async {
try {
Map<String, dynamic> params = {};
if (selectedCountry != 'All') {
params['country_code'] = selectedCountry;
}
var res = await CRUD().post(
link: AppLink.getPriceComparison,
payload: params,
);
if (res is Map && res['status'] == 'success') {
final data = res['message'];
if (data is Map) {
hourlyPriceData = data['hourly_competitor_prices'] ?? [];
pciRegions = data['pci_regions'] ?? [];
siroBasePrices = data['siro_base_prices'] is Map
? data['siro_base_prices'] as Map
: {};
update();
}
}
} catch (e) {
// Silently fail
}
}
Future<void> triggerAICampaign() async {
isLoading = true;
update();
try {
Map<String, dynamic> params = {};
if (selectedCountry != 'All') {
params['country_code'] = selectedCountry;
}
var res = await CRUD().post(
link: AppLink.triggerCampaign,
payload: params,
);
if (res is Map) {
if (res['status'] == 'success') {
mySnackbarSuccess("AI campaign triggered successfully! Promos sent.");
fetchCampaignsLog();
fetchTelemetry();
} else {
mySnackbarWarning(res['message'] ?? "Campaign rate limited.");
}
} else {
mySnackbarError("Failed to trigger AI campaign");
}
} catch (e) {
mySnackbarError("Network error while triggering campaign");
} finally {
isLoading = false;
update();
}
}
// --- What-If Simulator State ---
double? simulatedPci;
double? simulatedMarketShare;
String? simulatorRecommendationStatus;
String? simulatorRecommendationMessage;
Future<void> runWhatIfSimulation(String proposedSpeedPrice) async {
isLoading = true;
update();
try {
Map<String, dynamic> params = {
'speed_price': proposedSpeedPrice
};
if (selectedCountry != 'All') {
params['country_code'] = selectedCountry;
} else {
params['country_code'] = 'SY'; // Fallback
}
var res = await CRUD().post(
link: AppLink.whatIfSimulator,
payload: params,
);
if (res is Map && res['status'] == 'success') {
final data = res['message'];
if (data is Map) {
simulatedPci = (data['simulated_pci'] ?? 0.0).toDouble();
simulatedMarketShare = (data['simulated_market_share_percent'] ?? 0.0).toDouble();
simulatorRecommendationStatus = data['recommendation_status'];
simulatorRecommendationMessage = data['recommendation_message'];
}
} else {
mySnackbarError(res['message'] ?? "Failed to run simulation");
}
} catch (e) {
mySnackbarError("Network error during simulation");
} finally {
isLoading = false;
update();
}
}
// --- Heatmap State ---
List heatmapData = [];
double currentSiroPriceHeatmap = 0.0;
Future<void> fetchPriceGapHeatmap() async {
try {
Map<String, dynamic> params = {};
if (selectedCountry != 'All') {
params['country_code'] = selectedCountry;
} else {
params['country_code'] = 'SY'; // Fallback
}
var res = await CRUD().post(
link: AppLink.getPriceGapHeatmap,
payload: params,
);
if (res is Map && res['status'] == 'success') {
final data = res['message'];
if (data is Map) {
heatmapData = data['heatmap_data'] ?? [];
currentSiroPriceHeatmap = (data['current_siro_price_per_km'] ?? 0.0).toDouble();
update();
}
}
} catch (e) {
// Silently fail
}
}
// --- Market Share Analytics ---
List marketShareData = [];
Future<void> fetchMarketShareAnalytics() async {
try {
Map<String, dynamic> params = {};
if (selectedCountry != 'All') {
params['country_code'] = selectedCountry;
} else {
params['country_code'] = 'SY';
}
var res = await CRUD().post(
link: AppLink.getMarketShareAnalytics,
payload: params,
);
if (res is Map && res['status'] == 'success') {
marketShareData = res['historical_data'] ?? [];
update();
}
} catch (e) {
// Ignore
}
}
// --- AI Price Prediction ---
String? aiPredictionMessage;
List predictedSurgeHours = [];
Future<void> fetchAiPricePrediction() async {
try {
Map<String, dynamic> params = {};
if (selectedCountry != 'All') {
params['country_code'] = selectedCountry;
} else {
params['country_code'] = 'SY';
}
var res = await CRUD().post(
link: AppLink.aiPricePrediction,
payload: params,
);
if (res is Map && res['status'] == 'success') {
aiPredictionMessage = res['ai_analysis_message'];
predictedSurgeHours = res['predicted_surge_hours'] ?? [];
update();
}
} catch (e) {
// Ignore
}
}
// --- Win-Back Targets ---
List winbackTargets = [];
int winbackTotalCount = 0;
Future<void> fetchWinbackTargets() async {
try {
Map<String, dynamic> params = {};
if (selectedCountry != 'All') {
params['country_code'] = selectedCountry;
} else {
params['country_code'] = 'SY';
}
var res = await CRUD().post(
link: AppLink.winbackHotspotTargets,
payload: params,
);
if (res is Map && res['status'] == 'success') {
winbackTargets = res['targets'] ?? [];
winbackTotalCount = res['total_targets'] ?? 0;
update();
}
} catch (e) {
// Ignore
}
}
}