import 'dart:io';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import 'package:intl/intl.dart';
import 'package:gifunavi/model/rog.dart';
import 'package:gifunavi/pages/destination/destination_controller.dart';
import 'package:gifunavi/pages/index/index_controller.dart';
import 'package:gifunavi/utils/database_gps.dart';
import 'package:gifunavi/utils/database_helper.dart';
import 'dart:convert';

import '../model/gps_data.dart';
import '../utils/const.dart';

//
// Rog type 0- start 1- checkin 2- goal
//

class ExternalService {
  static final ExternalService _instance = ExternalService._internal();

  factory ExternalService() {
    return _instance;
  }

  ExternalService._internal();

  String getFormatedTime(DateTime datetime) {
    return DateFormat('yyyy-MM-dd HH:mm:ss').format(datetime);
  }

  Future<Map<String, dynamic>> startRogaining() async {
    final IndexController indexController = Get.find<IndexController>();
    //final TeamController teamController = Get.find<TeamController>();

    debugPrint("== startRogaining ==");

    Map<String, dynamic> res = {};

    //final teamController = TeamController();

    //Team team0 = teamController.teams[0];
    //print("team={team0}");

    //int teamId = indexController.currentUser[0]["user"]["team"]["id"];

    int userId = indexController.currentUser[0]["user"]["id"];
    //print("--- Pressed -----");
    String team = indexController.currentUser[0]["user"]['team_name'];
    //print("--- _team : ${_team}-----");
    String eventCode = indexController.currentUser[0]["user"]["event_code"];

    if (indexController.connectionStatusName.value.toLowerCase() != "wifi" &&
        indexController.connectionStatusName.value.toLowerCase() != "mobile") {
      debugPrint("== No network ==");
      DatabaseHelper db = DatabaseHelper.instance;
      Rog rog = Rog(
          id: 1,
          team_name: team,
          event_code: eventCode,
          user_id: userId,
          cp_number: -1,
          checkintime: DateTime.now().toUtc().microsecondsSinceEpoch,
          image: null,
          rog_action_type: 0);
      db.insertRogaining(rog);
    } else {
      debugPrint("== startRogaining processing==");

      String serverUrl = ConstValues.currentServer();
      String url = '$serverUrl/gifuroge/start_from_rogapp';
      print('++++++++$url');
      final http.Response response = await http.post(
        Uri.parse(url),
        headers: <String, String>{
          'Content-Type': 'application/json; charset=UTF-8',
        },
        body: jsonEncode(
            <String, String>{'team_name': team, 'event_code': eventCode}),
      );

      print("---- start rogianing api status ---- ${response.statusCode}");

      if (response.statusCode == 200) {
        res = json.decode(utf8.decode(response.bodyBytes));
        //print('----_res : $res ----');
      }
    }
    return res;
  }

  Future<Map<String, dynamic>> makeCheckpoint(
      int userId,  // 中身はteamId
      String token,
      String checkinTime,
      String teamname,
      int cp,
      String eventcode,
      String imageurl) async {
    // print("~~~~ in API call function ~~~~");
    // print("~~~~ cp is $cp ~~~~");
    //print("--cpcp-- ${cp}");
    Map<String, dynamic> res = {};
    String serverUrl = ConstValues.currentServer();
    String url = '$serverUrl/gifuroge/checkin_from_rogapp';
    //print('++++++++$url');
    final IndexController indexController = Get.find<IndexController>();
    //final TeamController teamController = Get.find<TeamController>();


//    Team team0 = indexController.teamController.teams[0];
//    print("team={team0}");

    //int teamId = indexController.teamController.teams[0];

    if (indexController.connectionStatusName.value.toLowerCase() != "wifi" &&
        indexController.connectionStatusName.value.toLowerCase() != "mobile") {
      debugPrint("== checkin without network ==");

      DatabaseHelper db = DatabaseHelper.instance;
      Rog rog = Rog(
        id: 1,
        team_name: teamname,
        event_code: eventcode,
        user_id: userId,
        cp_number: cp,
        checkintime: DateTime.now().toUtc().microsecondsSinceEpoch,
        image: imageurl,
        rog_action_type: 1,
      );
      db.insertRogaining(rog);
    } else {
      debugPrint("== Normal Check in ===");
      String serverUrl = ConstValues.currentServer();
      String url1 = "$serverUrl/api/checkinimage/";
      final im1Bytes = File(imageurl).readAsBytesSync();
      String im1_64 = base64Encode(im1Bytes);

      //print("~~~~ before calling api 1 ~~~~");

      try {
        final http.Response response = await http.post(
          Uri.parse(url1),
          headers: <String, String>{
            'Content-Type': 'application/json; charset=UTF-8',
            'Authorization': 'Token $token'
          },
          // 'id', 'user', 'goalimage', 'goaltime', 'team_name', 'event_code','cp_number'
          body: jsonEncode(<String, String>{
            'user': userId.toString(),
            'team_name': teamname,
            'event_code': eventcode,
            'checkinimage': im1_64,
            'checkintime': checkinTime,
            'cp_number': cp.toString()
          }),
        );

        res = json.decode(utf8.decode(response.bodyBytes));
        //print("~~~~ api1 result $res ~~~~");
        //print("-----@@@@@ checkin $_res -----");

        if (response.statusCode == 201) {
          //print("~~~~ image from api1 ${res["checkinimage"].toString()} ~~~~");
          //print('---- toekn is ${token} -----');
          //print("~~~~ token is $token ~~~~");
          //print("~~~~ before callling api2 ~~~~");
          final http.Response response2 = await http.post(
            Uri.parse(url),
            headers: <String, String>{
              'Content-Type': 'application/json; charset=UTF-8',
            },
            body: jsonEncode(<String, String>{
              'team_name': teamname,
              'cp_number': cp.toString(),
              'event_code': eventcode,
              'image': res["checkinimage"].toString().replaceAll(
                  'http://localhost:8100', serverUrl)  //'http://rogaining.sumasen.net')
            }),
          );
          var vv = jsonEncode(<String, String>{
            'team_name': teamname,
            'cp_number': cp.toString(),
            'event_code': eventcode,
            'image': res["checkinimage"].toString().replaceAll(
                'http://localhost:8100', serverUrl)  //'http://rogaining.sumasen.net')
          });
          //print("~~~~ api 2 values $vv ~~~~");
          //print("--json-- $vv");
          //print("--- checnin response ${response2.statusCode}----");
          if (response2.statusCode == 200) {
            res = json.decode(utf8.decode(response2.bodyBytes));
            //print('----checkin res _res : $res ----');
            if (res["status"] == "ERROR" && cp>0 ) {
              // スタート・ゴールはエラー除外。
              Get.snackbar("エラーがおきました", res["detail"],
                backgroundColor: Colors.red,
                colorText: Colors.white
              );
            }

          }
        } else {
          Get.snackbar("サーバーエラーがおきました", "サーバーと通信できませんでした",
              backgroundColor: Colors.red,
              colorText: Colors.white
          );
        }
      } catch( e ) {
        print('Error in makeCheckpoint: $e');
        Get.snackbar("通信エラーがおきました", "サーバーと通信できませんでした",
            backgroundColor: Colors.red,
            colorText: Colors.white
        );
      }
    }
      //print("~~~~ done checkin ~~~~");
    return res;
  }

  Future<Map<String, dynamic>> makeGoal(int userId, String token,
      String teamname, String image, String goalTime, String eventcode) async {
    Map<String, dynamic> res2 = {};

    final IndexController indexController = Get.find<IndexController>();
    final DestinationController destinationController =
        Get.find<DestinationController>();

    // チームIDを取得

    //int teamId = indexController.currentUser[0]["user"]["team"]["id"];

    debugPrint("== goal Rogaining ==");

    //if(indexController.connectionStatusName != "wifi" && indexController.connectionStatusName != "mobile"){
    DatabaseHelper db = DatabaseHelper.instance;
    Rog rog = Rog(
      id: 1,
      team_name: teamname,
      event_code: eventcode,
      user_id: userId,  // 中身はteamid
      cp_number: -1,
      checkintime: DateTime.now().toUtc().microsecondsSinceEpoch,
      image: image,
      rog_action_type: 1,
    );
    db.insertRogaining(rog);
    // }
    // else{
    String serverUrl = ConstValues.currentServer();
    String url1 = "$serverUrl/api/goalimage/";
    final im1Bytes = File(image).readAsBytesSync();
    String im1_64 = base64Encode(im1Bytes);

    final http.Response response = await http.post(
      Uri.parse(url1),
      headers: <String, String>{
        'Content-Type': 'application/json; charset=UTF-8',
        'Authorization': 'Token $token'
      },
      // 'id', 'user', 'goalimage', 'goaltime', 'team_name', 'event_code','cp_number'
      body: jsonEncode(<String, String>{
        'user': userId.toString(),  //userId.toString(),
        'team_name': teamname,
        'event_code': eventcode,
        'goaltime': goalTime,
        'goalimage': im1_64,
        'cp_number': "-1"
      }),
    );

    //String serverUrl = ConstValues.currentServer();
    String url = '$serverUrl/gifuroge/goal_from_rogapp';
    //print('++++++++$url');
    if (response.statusCode == 201) {
      try {
        Map<String, dynamic> res = json.decode(utf8.decode(response.bodyBytes));
        // print('----_res : $res ----');
        // print('---- image url ${res["goalimage"]} ----');
        final http.Response response2 = await http.post(
          Uri.parse(url),
          headers: <String, String>{
            'Content-Type': 'application/json; charset=UTF-8',
          },
          body: jsonEncode(<String, String>{
            'team_name': teamname,
            'event_code': eventcode,
            'goal_time': goalTime,
            'image': res["goalimage"].toString().replaceAll(
                'http://localhost:8100', serverUrl)
            //'http://rogaining.sumasen.net')
          }),
        );
        String rec = jsonEncode(<String, String>{
          'team_name': teamname,
          'event_code': eventcode,
          'goal_time': goalTime,
          'image': res["goalimage"]
              .toString()
              .replaceAll('http://localhost:8100', serverUrl)
          //'http://rogaining.sumasen.net')
        });
        //print("-- json -- $rec");
        //print('----- response2 is $response2 --------');
        if (response2.statusCode == 200) {
          res2 = json.decode(utf8.decode(response2.bodyBytes));
        } else {
          res2 = json.decode(utf8.decode(response2.bodyBytes));
        }
      } catch(e){
        print( "Error {$e}" );
      }
    }
    //}
    destinationController.resetRogaining(isgoal: true);
    return res2;
  }

  Future<bool> removeCheckin(int cp) async {
    final IndexController indexController = Get.find<IndexController>();

    //int userId = indexController.currentUser[0]["user"]["id"];
    //print("--- Pressed -----");
    String team = indexController.currentUser[0]["user"]['team_name'];
    //print("--- _team : ${_team}-----");
    String eventCode = indexController.currentUser[0]["user"]["event_code"];

    if (indexController.connectionStatusName.value.toLowerCase() != "wifi" &&
        indexController.connectionStatusName.value.toLowerCase() != "mobile") {
      return Future.value(false);
    } else {
      String serverUrl = ConstValues.currentServer();
      String url = '$serverUrl/gifuroge/remove_checkin_from_rogapp';
      //print('++++++++$url');
      final http.Response response = await http.post(
        Uri.parse(url),
        headers: <String, String>{
          'Content-Type': 'application/json; charset=UTF-8',
        },
        body: jsonEncode(<String, String>{
          'event_code': eventCode,
          'team_name': team,
          'cp_number': cp.toString()
        }),
      );

      //print("---- remove checkin ---- ${response.statusCode}");

      if (response.statusCode == 200) {
        return Future.value(true);
        //print('----_res : $res ----');
      }
    }
    return Future.value(false);
  }

  String timestampToTimeString(int timestamp) {
    // Convert timestamp to DateTime and format it as needed
    var dateTime = DateTime.fromMillisecondsSinceEpoch(timestamp);
    //print("^^^^ time ${dateTime}");
    // Format dateTime to a time string (e.g., '12:00:00')
    // Adjust the format as needed
    return "${dateTime.hour}:${dateTime.minute}:${dateTime.second}";
  }

  Future<bool> pushGPS() async {
    //print("^^^^ pushed ^^^");
    final IndexController indexController = Get.find<IndexController>();

    //int userId = indexController.currentUser[0]["user"]["id"];
    //print("--- Pressed -----");
    if( indexController.currentUser[0]["user"]==null ){
      return Future.value(false);
    }
    if( indexController.currentUser[0]["user"]['team_name']==null ){
      return Future.value(false);
    }
    if( indexController.currentUser[0]["user"]["event_code"]==null ){
      return Future.value(false);
    }
    String team = indexController.currentUser[0]["user"]['team_name'];
    //print("--- _team : ${_team}-----");
    String eventCode = indexController.currentUser[0]["user"]["event_code"];

    List<GpsData> gpsDataList = [];

    if (indexController.connectionStatusName.value.toLowerCase() != "wifi" &&
        indexController.connectionStatusName.value.toLowerCase() != "mobile") {
      return Future.value(false);
    } else {
      // Step 1: Fetch data from the local database
      gpsDataList =
          await GpsDatabaseHelper.instance.getUnsyncedGPSData(team, eventCode);

      // Step 2: Transform data into the required format
      var payload = {
        'team_name': team,
        'event_code': eventCode,
        'waypoints': gpsDataList.map((gpsData) {
          return {
            'latitude': gpsData.lat.toString(),
            'longitude': gpsData.lon.toString(),
            // Convert the timestamp to a formatted time string
            'time': timestampToTimeString(gpsData.created_at),
          };
        }).toList(),
      };

      //print("calling push gps step 2 ${payload}");

      String serverUrl = ConstValues.currentServer();
      String urlS = '$serverUrl/gifuroge/get_waypoint_datas_from_rogapp';
      //print('++++++++$url');
      var url = Uri.parse(urlS); // Replace with your server URL
      var response = await http.post(
        url,
        headers: {"Content-Type": "application/json"},
        body: json.encode(payload),
      );

      //print("GPS Data res ${response.statusCode}");
      if (response.statusCode == 200) {
        // Handle success
        // make local data as synced
        await GpsDatabaseHelper.instance.setSyncData(gpsDataList);
        //print("GPS Data sent successfully");
      } else {
        // Handle error
        //print("Failed to send data");
      }
    }
    return Future.value(false);
  }

  static Future<Map<String, dynamic>> usersEventCode(
      String teamcode, String password) async {
    Map<String, dynamic> res = {};
    String serverUrl = ConstValues.currentServer();
    String url = "$serverUrl/gifuroge/check_event_code?zekken_number=$teamcode&password=$password";
    //print('++++++++$url');
    final http.Response response =
        await http.get(Uri.parse(url), headers: <String, String>{
      'Content-Type': 'application/json; charset=UTF-8',
    });

    if (response.statusCode == 200) {
      res = json.decode(utf8.decode(response.bodyBytes));
    }
    return res;
  }
}
