import 'dart:convert';
import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:http/http.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/models/device/asset.dart';
import 'package:test_sa/models/device/asset_search.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/module_permissions_model.dart';
import 'package:test_sa/models/service_request/pending_service_request_model.dart';
import 'package:test_sa/models/service_request/service_report.dart';
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/models/service_request/service_request_search.dart';
import 'package:test_sa/models/service_request/spare_parts.dart';
import 'package:test_sa/models/service_request/supp_engineer_work_orders.dart';
import 'package:test_sa/models/service_request/supplier_engineer_model.dart';
import 'package:test_sa/models/timer_model.dart';
import 'package:test_sa/modules/asset_inventory_module/models/asset_inventory_model.dart';
import 'package:test_sa/modules/asset_inventory_module/models/session_model.dart';

import '../../../models/service_request/search_work_order.dart';
import '../../../models/service_request/wo_call_request.dart';
import '../../../models/user.dart';
import '../../../new_views/common_widgets/app_lazy_loading.dart';

class AssetInventoryProvider extends ChangeNotifier {
  final pageItemNumber = 10;
  final searchPageItemNumber = 10;
  int pageNo = 1;
  List<AssetInventoryModel> _devices = [];
  List<AssetInventoryModel> _searchDevices = [];

  List<AssetInventoryModel> get devices => _devices;

  List<AssetInventoryModel> get searchDevices => _searchDevices;
  SessionModel? sessionModel;

  //TODO need to check i think don't need to create this obj
  AssetInventoryResponse? assetInventoryResponse;
  AssetInventoryResponse? siteFilterAssetResponse;

  List<AssetInventoryModel> sessionAssetList = [];
  List<AssetInventoryModel> siteFilterAssetList = [];

  ModulesPermissionsModel? modelPermission;

  void reset() {
    pageNo = 1;
    modelPermission = null;
    assetInventoryResponse = null;
    sessionModel = null;
    sessionAssetList = [];
    stateCode = null;
  }

  int? stateCode;
  bool isDetailLoading = false;
  bool nextPage = false;
  bool isNextPageLoading = false;
  bool isLoading = false;
  bool isAllAssetLoading = false;

  void searchReset() {
    stateCode = null;
    _searchDevices = [];
  }

  Future<void> getSessionById({required int id}) async {
    try {
      sessionModel = SessionModel();
      isLoading = true;
      notifyListeners();
      final response = await ApiManager.instance.get(URLs.getAssetInventoryById + "?assetInventoryId=$id");
      stateCode = response.statusCode;
      if (response.statusCode >= 200 && response.statusCode < 300) {
        sessionModel = SessionModel.fromJson(json.decode(response.body)["data"]);
      } else {
        sessionModel = null;
      }

      isLoading = false;
      notifyListeners();
    } catch (e) {
      log("getSessionError [error] : $e");
      isLoading = false;
      sessionModel = null;
      notifyListeners();
      return null;
    }
  }

  Future<int> getAssetsInSession({
    required int sessionId,
    bool loadMore = false,
  }) async {
    if (isLoading || isNextPageLoading) return -2;
    if (loadMore) {
      isNextPageLoading = true;
      pageNo += 1;
    } else {
      isLoading = true;
      pageNo = 1; // reset pagination
    }
    notifyListeners();
    try {
      final payload = {
        "pageSize": pageItemNumber,
        "pageNumber": pageNo,
        "sessionId": sessionId,
      };
      final response = await ApiManager.instance.post(URLs.getAssetsInSession, body: payload);
      stateCode = response.statusCode;
      if (response.statusCode >= 200 && response.statusCode < 300) {
        final Map<String, dynamic> jsonData = json.decode(response.body);
        final newResponse = AssetInventoryResponse.fromJson(jsonData);

        if (loadMore) {
          assetInventoryResponse?.assetList?.addAll(newResponse.assetList ?? []);
          assetInventoryResponse?.totalRows = newResponse.totalRows;
        } else {
          assetInventoryResponse = newResponse;
        }
        nextPage = (assetInventoryResponse?.assetList?.length ?? 0) < (assetInventoryResponse?.totalRows ?? 0);
      } else {
        nextPage = false;
      }
      isLoading = false;
      isNextPageLoading = false;
      notifyListeners();
      return response.statusCode;
    } catch (error) {
      isLoading = false;
      isNextPageLoading = false;
      stateCode = -1;
      nextPage = false;
      notifyListeners();
      return -1;
    }
  }

  ///older code
  // Future<int> getAssetsInSession({
  //   required int sessionId,
  //   bool loadMore = false,
  // }) async {
  //   // if (isLoading || nextPage) return -2;
  //
  //   if (loadMore) {
  //     nextPage = true;
  //     pageNo += 1;
  //   } else {
  //     isLoading = true;
  //     pageNo = 1; // reset pagination
  //   }
  //
  //   notifyListeners();
  //   log('Fetching page: $pageNo');
  //
  //   try {
  //     final payload = {
  //       "pageSize": pageItemNumber,
  //       "pageNumber": pageNo,
  //       "sessionId": sessionId,
  //     };
  //
  //     final response = await ApiManager.instance.post(URLs.getAssetsInSession, body: payload);
  //     stateCode = response.statusCode;
  //
  //     if (response.statusCode >= 200 && response.statusCode < 300) {
  //       final Map<String, dynamic> jsonData = json.decode(response.body);
  //       final newResponse = AssetInventoryResponse.fromJson(jsonData);
  //
  //       if (loadMore) {
  //         assetInventoryResponse?.assetList?.addAll(newResponse.assetList ?? []);
  //         assetInventoryResponse?.totalRows = newResponse.totalRows;
  //       } else {
  //         assetInventoryResponse = newResponse;
  //       }
  //
  //       nextPage = (assetInventoryResponse?.assetList?.length ?? 0) < (assetInventoryResponse?.totalRows ?? 0);
  //     }
  //
  //     isLoading = false;
  //     nextPage = false;
  //     notifyListeners();
  //     return response.statusCode;
  //   } catch (error) {
  //     isLoading = false;
  //     nextPage = false;
  //     stateCode = -1;
  //     notifyListeners();
  //     return -1;
  //   }
  // }

  Future<int> getInventoryDetailsByFilter({
    required Map<String, dynamic> payload,
    bool loadMore = false,
  }) async {
    if (isLoading || isNextPageLoading) return -2;

    if (loadMore) {
      isNextPageLoading = true;
      pageNo += 1;
    } else {
      isLoading = true;
      pageNo = 1;
    }

    notifyListeners();
    log('Fetching inventory page: $pageNo');

    try {
      final paginatedPayload = {
        ...payload,
        "pageSize": pageItemNumber,
        "pageNumber": pageNo,
      };

      final response = await ApiManager.instance.post(URLs.getInventoryDetailsByFilter, body: paginatedPayload);
      stateCode = response.statusCode;

      if (response.statusCode >= 200 && response.statusCode < 300) {
        final Map<String, dynamic> jsonData = json.decode(response.body);
        final newResponse = AssetInventoryResponse.fromJson(jsonData);

        if (loadMore) {
          siteFilterAssetList.addAll(newResponse.assetList ?? []);
          siteFilterAssetResponse?.totalRows = newResponse.totalRows;
        } else {
          siteFilterAssetResponse = newResponse;
          siteFilterAssetList = newResponse.assetList ?? [];
        }
        nextPage = (siteFilterAssetList.length) < (siteFilterAssetResponse?.totalRows ?? 0);
      } else {
        siteFilterAssetList = [];
        nextPage = false;
      }

      isLoading = false;
      isNextPageLoading = false;
      notifyListeners();
      return response.statusCode;
    } catch (error) {
      isLoading = false;
      isNextPageLoading = false;
      nextPage = false;
      stateCode = -1;
      notifyListeners();
      return -1;
    }
  }

  Future<AssetInventoryModel?> searchAsset({
    required Map<String, dynamic> payload,
  }) async {
    isLoading = true;
    try {
      final response = await ApiManager.instance.post(URLs.searchAsset, body: payload);
      stateCode = response.statusCode;
      if (response.statusCode >= 200 && response.statusCode < 300) {
        final Map<String, dynamic> jsonData = json.decode(response.body)["data"];
        AssetInventoryModel model = AssetInventoryModel.fromJson(jsonData);
        log('model json ${model.toJson()}');
        isLoading = false;
        notifyListeners();
        return model;
      } else {
        isLoading = false;
        notifyListeners();
        return null;
      }
    } catch (error) {
      isLoading = false;
      stateCode = -1;
      notifyListeners();
      return null;
    }
  }

  Future<bool> saveAssetInSession({
    AssetInventoryModel? model,
  }) async {
    isLoading = true;
    try {
      final response = await ApiManager.instance.post(URLs.saveAssetInSession, body: model?.toJson() ?? {});
      stateCode = response.statusCode;
      if (response.statusCode >= 200 && response.statusCode < 300) {
        isLoading = false;
        notifyListeners();
        return true;
      } else {
        isLoading = false;
        notifyListeners();
        return false;
      }
    } catch (error) {
      isLoading = false;
      notifyListeners();
      return false;
    }
  }

  Future<String?> getClassification({
    required Map<String, dynamic> payload,
  }) async {
    isLoading = true;
    String? classification;
    try {
      final response = await ApiManager.instance.post(URLs.getClassification, body: payload);
      stateCode = response.statusCode;
      if (response.statusCode >= 200 && response.statusCode < 300) {
        log('classifcation on response ${json.decode(response.body)["data"]['classification']}');
        classification = json.decode(response.body)["data"]['classification'];
        isLoading = false;
        notifyListeners();
        return classification;
      } else {
        isLoading = false;
        notifyListeners();
        return classification;
      }
    } catch (error) {
      isLoading = false;
      notifyListeners();
      return classification;
    }
  }

  Future<bool> deleteAssetISession({required num id}) async {
    try {
      isLoading = true;
      notifyListeners();
      final response = await ApiManager.instance.get(URLs.deleteAssetInSession + "?id=$id");
      stateCode = response.statusCode;
      if (response.statusCode >= 200 && response.statusCode < 300) {
        isLoading = false;
        notifyListeners();
        return true;
      }
      isLoading = false;
      notifyListeners();
      return false;
    } catch (e) {
      log("Delete Asset [error] : $e");
      isLoading = false;
      notifyListeners();
      return false;
    }
  }

  Future<List<Lookup>> getAutoCompleteDetails({
    bool? isManufacturer,
    String? query,
    int type = 0,
  }) async {
    try {
      String url = '';
      switch (type) {
        //for model and manufacturer..
        case 0:
          url = URLs.getManufacturerOrModelAutoComplete;
          break;
        //for asset name..
        case 1:
          url = URLs.searchAssetName;
          break;
        //for supplier...
        case 2:
          url = URLs.getSuppliersAutoCompleteInventory;
          break;
        default:
          url = URLs.getManufacturerOrModelAutoComplete;
      }
      final queryParams = <String, String>{};
      if (isManufacturer != null && type == 0) {
        queryParams['isManufacturer'] = isManufacturer.toString();
      }
      if (query != null && query.isNotEmpty) {
        queryParams['searchText'] = query;
      }
      if (queryParams.isNotEmpty) {
        url += '?${Uri(queryParameters: queryParams).query}';
      }
      final response = await ApiManager.instance.get(url);

      List<Lookup> list = [];
      if (response.statusCode >= 200 && response.statusCode < 300) {
        final data = json.decode(response.body)["data"];
        list = (data as List).map((e) => Lookup.fromJson(e)).toList();
      }
      return list;
    } catch (error) {
      log('error $error');
      return [];
    }
  }

  Future<int> getAssets({DeviceSearch? search, bool isQr = false, bool isSearchBy = false, num? sessionId}) async {
    if (isLoading == true) return -2;
    isLoading = true;
    notifyListeners();
    late Response response;
    try {
      final Map<String, dynamic> body = {
        "pageSize": isSearchBy ? searchPageItemNumber : pageItemNumber,
        "pageNumber": isSearchBy ? (searchDevices.length / searchPageItemNumber).ceil() + 1 : devices.length ~/ pageItemNumber + 1,
        "sessionId": sessionId ?? 0,
        "assetSerialNo": search?.assetSerialNumber ?? '',
        "assetName": search?.assetName ?? '',
        "model": search?.model ?? '',
        "manufacturer": search?.manufacturer ?? '',
        "supplier": search?.supplier ?? '',
        "siteName": search?.site ?? '',
        // "buildingName":search?.??'',
        // "floorName": search?.f??'',
        "departmentName": search?.department ?? '',
        // "roomName": search?.room
      };
      // if (search != null) body.addAll(search.toJson());
      response = await ApiManager.instance.post(URLs.getAssetsTemp, body: body);
    } catch (error) {
      isLoading = false;
      stateCode = -1;
      notifyListeners();
      return -1;
    }
    stateCode = response.statusCode;
    if (response.statusCode >= 200 && response.statusCode < 300) {
      // client's request was successfully received
      List equipmentListJson = json.decode(response.body)["data"];
      var dList = equipmentListJson.map<AssetInventoryModel>((asset) => AssetInventoryModel.fromJson(asset)).toList() ?? [];
      isSearchBy ? _searchDevices.addAll(dList) : _devices.addAll(dList);
      nextPage = true;
    } else {
      nextPage = false;
    }
    isLoading = false;
    notifyListeners();
    return response.statusCode;
  }

  Future<bool> markAsComplete({
    required Map<String, dynamic> payload,
  }) async {
    isLoading = true;
    try {
      final response = await ApiManager.instance.post(URLs.convertDetailToComplete, body: payload);
      stateCode = response.statusCode;
      if (response.statusCode >= 200 && response.statusCode < 300) {
        isLoading = false;
        notifyListeners();
        return true;
      } else {
        isLoading = false;
        notifyListeners();
        return false;
      }
    } catch (error) {
      isLoading = false;
      notifyListeners();
      return false;
    }
  }
}
