import 'dart:convert'; import 'dart:io'; import 'dart:math' show Random; import 'package:get/get.dart'; import 'package:http/http.dart' as http; import 'package:image_picker/image_picker.dart'; import 'package:minio/io.dart'; import 'package:minio/minio.dart'; import 'package:nearle/Models/supportticket/support_ticket.dart'; // Minimal local stub for DigitalOcean Spaces client to avoid undefined name errors. // Replace this with a real package or implementation for production uploads. class dospace { static DOSpaceClient DOSpace({ required String region, required String accessKey, required String secretKey, }) => DOSpaceClient(region: region, accessKey: accessKey, secretKey: secretKey); static final ACL = _ACL(); } class _ACL { final String publicRead = 'public-read'; } class DOSpaceClient { final String region; final String accessKey; final String secretKey; DOSpaceClient({ required this.region, required this.accessKey, required this.secretKey, }); Future putObject({ required String bucketName, required String objectName, required File file, required String acl, required String contentType, }) async { // No-op stub: implement actual upload logic here or use a proper package. await Future.value(); } } class SupportTicketController extends GetxController { final RxList tickets = [].obs; final RxBool isLoading = true.obs; final RxString errorMessage = ''.obs; final RxBool isSubmitting = false.obs; @override void onInit() { super.onInit(); fetchTickets(); } // ---------- FETCH TICKETS ---------- Future fetchTickets() async { try { isLoading(true); errorMessage(''); const userId = 1242; final url = Uri.parse( 'https://jupiter.nearle.app/live/api/v1/partners/getridersupport/?userid=$userId'); final response = await http.get(url, headers: { 'Accept': 'application/json', }); if (response.statusCode != 200) { throw Exception('Server error: ${response.statusCode}'); } final Map jsonResponse = json.decode(response.body); if (jsonResponse['status'] != true) { throw Exception(jsonResponse['message'] ?? 'Unknown error'); } final List data = jsonResponse['data']; tickets.assignAll(data.map((e) => SupportTicketModel.fromJson(e)).toList()); } catch (e) { errorMessage(e.toString()); } finally { isLoading(false); } } // ---------- UPLOAD IMAGE TO DO SPACES ---------- Future uploadImageToDOSpaces(File imageFile, int userId) async { try { final rng = Random(); const String region = "sgp1"; const String accessKey = "DO00NQER7N2FRYZAB2HR"; const String secretKey = "nMDewX25IBEu1FM5dakK+v28/WbW3TzBAwq913+dxP0"; const String bucketName = "nearle"; const String folderName = "support"; // File name final String fileName = 'ticket-${rng.nextInt(10000)}-$userId.jpg'; // Object path inside the bucket final String objectPath = "$folderName/$fileName"; // CDN URL you want final String cdnUrl = "https://images.nearle.app/$objectPath"; // Initialize Minio final minio = Minio( endPoint: "$region.digitaloceanspaces.com", accessKey: accessKey, secretKey: secretKey, region: region, useSSL: true, ); print("Uploading: $objectPath"); // Upload to DO Spaces await minio.fPutObject( bucketName, objectPath, imageFile.path, metadata: { "Content-Type": "image/jpeg", "x-amz-acl": "public-read", }, ); print("Uploaded Successfully: $cdnUrl"); return cdnUrl; } catch (e) { print("Upload error: $e"); Get.snackbar("Error", "Image upload failed."); return null; } } // ---------- CREATE TICKET ---------- // ---------- CREATE TICKET ---------- Future createTicket({ required int userid, required String category, required String priority, required String subject, required String issue, List? attachments, }) async { try { isSubmitting(true); String imageUrl = ""; // Upload first image if attached if (attachments != null && attachments.isNotEmpty) { final XFile xFile = attachments.first; final File file = File(xFile.path); final uploadedUrl = await uploadImageToDOSpaces(file, userid); // Only assign if a valid URL (short length) if (uploadedUrl != null && uploadedUrl.length < 200) { imageUrl = uploadedUrl; } else { print("⚠️ Skipping image URL because it’s too long or invalid."); } } // Create ticket request body final Map payload = { 'userid': userid, 'category': category, 'priority': priority, 'subject': subject, 'issue': issue, 'image': imageUrl, // ✅ Always short string or empty }; final response = await http.post( Uri.parse('https://jupiter.nearle.app/live/api/v1/partners/createridersupport/'), headers: {'Accept': 'application/json', 'Content-Type': 'application/json'}, body: jsonEncode(payload), ); if (response.statusCode != 200) { throw Exception('Ticket creation failed: ${response.statusCode}'); } final jsonResponse = jsonDecode(response.body); if (jsonResponse['status'] != true) { throw Exception(jsonResponse['message'] ?? 'Unknown error'); } await fetchTickets(); // Refresh list after success return true; } catch (e) { errorMessage(e.toString()); return false; } finally { isSubmitting(false); } } }