import 'package:e_commerce_training/src/model/preference/app_preference.dart';
import 'package:e_commerce_training/src/model/request/base_category_request.dart';
import 'package:e_commerce_training/src/model/request/brand_request.dart';
import 'package:e_commerce_training/src/model/request/filter_request.dart';
import 'package:e_commerce_training/src/model/request/home_category_request.dart';
import 'package:e_commerce_training/src/model/request/list_product_request.dart';
import 'package:e_commerce_training/src/model/request/login_request.dart';
import 'package:e_commerce_training/src/model/request/notification_request.dart';
import 'package:e_commerce_training/src/model/request/register_request.dart';
import 'package:e_commerce_training/src/model/request/review_request.dart';
import 'package:e_commerce_training/src/model/request/update_notification_request.dart';
import 'package:e_commerce_training/src/model/request/update_user_request.dart';
import 'package:e_commerce_training/src/model/response/base_category_response.dart';
import 'package:e_commerce_training/src/model/response/blog_response.dart';
import 'package:e_commerce_training/src/model/response/brand_response.dart';
import 'package:e_commerce_training/src/model/response/catalog_response.dart';
import 'package:e_commerce_training/src/model/response/category.dart';
import 'package:e_commerce_training/src/model/response/city_response.dart';
import 'package:e_commerce_training/src/model/response/common_response.dart';
import 'package:e_commerce_training/src/model/response/detail_category_response.dart';
import 'package:e_commerce_training/src/model/response/district_response.dart';
import 'package:e_commerce_training/src/model/response/filter_response.dart';
import 'package:e_commerce_training/src/model/response/home_category_response.dart';
import 'package:e_commerce_training/src/model/response/home_config_response.dart';
import 'package:e_commerce_training/src/model/response/list_cart.dart';
import 'package:e_commerce_training/src/model/response/list_choose_category.dart';
import 'package:e_commerce_training/src/model/response/list_community_response.dart';
import 'package:e_commerce_training/src/model/response/list_page_response.dart';
import 'package:e_commerce_training/src/model/response/list_product_response.dart';
import 'package:e_commerce_training/src/model/response/login_response.dart';
import 'package:e_commerce_training/src/model/response/news_response.dart';
import 'package:e_commerce_training/src/model/response/notification_response.dart';
import 'package:e_commerce_training/src/model/response/page_data.dart';
import 'package:e_commerce_training/src/model/response/product_detail_response.dart';

import 'package:e_commerce_training/src/model/response/review_response.dart';

import 'package:e_commerce_training/src/model/response/product_suggest.dart';
import 'package:e_commerce_training/src/model/response/tag_home.dart';

import 'package:e_commerce_training/src/model/response/user_response.dart';

import 'package:e_commerce_training/src/model/response/video_response.dart';

import 'package:e_commerce_training/src/model/response/ward_response.dart';
import 'package:e_commerce_training/src/model/service/api_result.dart';
import 'package:e_commerce_training/src/model/service/network_exceptions.dart';
import 'package:e_commerce_training/src/util/const.dart';

import '../service/app_client.dart';

class AppRepository {
  Future<ApiResult<LoginResponse>> register(RegisterRequest request) async {
    try {
      LoginResponse response = await appClient.register(request);
      return ApiResult.success(data: response);
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<UserResponse>> updateProfile(UpdateUserRequest request) async {
    try {
      UserResponse response = await appClient.updateProfile(request);
      return ApiResult.success(data: response);
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<LoginResponse>> login(LoginRequest request) async {
    try {
      LoginResponse response = await appClient.login(request);
      return ApiResult.success(data: response);
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<UserData>> getDetailUser() async {
    try {
      UserResponse response = await appClient.getDetailUser(appPreference.getData(Const.TOKEN) ?? "");
      if (response.data != null)
        return ApiResult.success(data: response.data!);
      else
        return ApiResult.failure(error: NetworkExceptions.unableToProcess());
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<CityResponse>> getListCity() async {
    try {
      CityResponse response = await appClient.getListCity();
      return ApiResult.success(data: response);
    } catch (e) {
      // TODO parse json to response data.
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<DistrictResponse>> getListDistrict(int cityId) async {
    try {
      DistrictResponse response = await appClient.getListDistrict(cityId);
      return ApiResult.success(data: response);
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<WardResponse>> getListWard(int districtId) async {
    try {
      WardResponse response = await appClient.getListWard(districtId);
      return ApiResult.success(data: response);
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<List<CatalogData>>> getCatalogBlog() async {
    try {
      CatalogResponse response = await appClient.getCatalogBlog();
      if (response.data != null) {
        return ApiResult.success(data: response.data!);
      } else {
        return ApiResult.failure(error: NetworkExceptions.unableToProcess());
      }
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<List<BlogData>>> getListBlog(int catalogId, {int pageNumber = 1}) async {
    try {
      BlogResponse response = await appClient.getListBlogByCatalog(catalogId, {"page": pageNumber, "pageSize": Const.DEFAULT_SIZE});
      if (response.data != null) {
        return ApiResult.success(data: response.data!);
      } else {
        return ApiResult.failure(error: NetworkExceptions.unableToProcess());
      }
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<List<CatalogData>>> getCatalogVideo() async {
    try {
      CatalogResponse response = await appClient.getCatalogVideo();
      if (response.data != null) {
        return ApiResult.success(data: response.data!);
      } else {
        return ApiResult.failure(error: NetworkExceptions.unableToProcess());
      }
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<List<VideoData>>> getListVideo(int catalogId, {int pageNumber = 1}) async {
    try {
      VideoResponse response = await appClient.getListVideoByCatalog(catalogId, {"page": pageNumber, "pageSize": Const.DEFAULT_SIZE});
      if (response.data != null) {
        return ApiResult.success(data: response.data!);
      } else {
        return ApiResult.failure(error: NetworkExceptions.unableToProcess());
      }
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<List<VideoData>>> getListVideoHome() async {
    try {
      VideoResponse response = await appClient.getListVideoHome({"page": 1, "pageSize": Const.DEFAULT_SIZE});
      if (response.data != null) {
        return ApiResult.success(data: response.data!);
      } else {
        return ApiResult.failure(error: NetworkExceptions.unableToProcess());
      }
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<List<CategoryData>>> getCategory() async {
    try {
      CategoryResponse response = await appClient.getCategory();
      if (response.data != null) {
        return ApiResult.success(data: response.data!);
      } else {
        return ApiResult.failure(error: NetworkExceptions.unableToProcess());
      }
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<DetailCategoryData>> getDetailCategory(int detailCategoryId) async {
    try {
      DetailCategoryResponse response = await appClient.getDetailCategory(detailCategoryId);
      if (response.detailCategoryData != null) {
        return ApiResult.success(data: response.detailCategoryData!);
      } else {
        return ApiResult.failure(error: NetworkExceptions.unableToProcess());
      }
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<dynamic>> registerDeviceToken(String deviceToken) async {
    try {
      dynamic response = await appClient.registerDevice(deviceToken);
      return ApiResult.success(data: response);
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<NotificationResponse>> getListNotification({int pageNumber = 1, bool? isReaded, String? deviceToken, String? userToken}) async {
    try {
      NotificationResponse response = await appClient
          .getListNotification(NotificationRequest(page: pageNumber, pageSize: Const.DEFAULT_SIZE, deviceToken: deviceToken, isReaded: isReaded));
      return ApiResult.success(data: response);
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<CommonResponse>> updateNotification(String notificationId, {String? deviceToken, String? userToken}) async {
    try {
      CommonResponse response =
          await appClient.updateNotification(UpdateNotificationRequest(deviceToken: deviceToken, isRead: true, notificationId: notificationId));
      return ApiResult.success(data: response);
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<List<NewsData>>> getNews() async {
    try {
      NewsResponse response = await appClient.getListNews();
      if (response.data != null) {
        return ApiResult.success(data: response.data!);
      } else {
        return ApiResult.failure(error: NetworkExceptions.unableToProcess());
      }
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<List<BrandData>>> getListBrand({int pageNumber = 1}) async {
    try {
      BrandResponse response = await appClient.getListBrand(BrandRequest(page: pageNumber, pageSize: Const.DEFAULT_SIZE));
      if (response.data != null) {
        return ApiResult.success(data: response.data!);
      } else {
        return ApiResult.failure(error: NetworkExceptions.unableToProcess());
      }
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<List<ReviewData>>> getListReview(int productId, {int pageNumber = 1}) async {
    try {
      ReviewResponse response = await appClient.getListReview(ReviewRequest(page: pageNumber, pageSize: Const.DEFAULT_SIZE, productId: productId));
      if (response.data != null) {
        return ApiResult.success(data: response.data!);
      } else {
        return ApiResult.failure(error: NetworkExceptions.unableToProcess());
      }
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<List<KeywordSuggestData>>> getListKeywordSuggest() async {
    try {
      KeywordSuggestResponse response = await appClient.getListSuggestion();

      if (response.data != null) {
        return ApiResult.success(data: response.data!);
      } else {
        return ApiResult.failure(error: NetworkExceptions.unableToProcess());
      }
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<List<ListProductData>>> getListProduct(ListProductRequest request) async {
    try {
      ListProductResponse response = await appClient.getListProduct(request);
      if (response.data != null) {
        return ApiResult.success(data: response.data!);
      } else {
        return ApiResult.failure(error: NetworkExceptions.unableToProcess());
      }
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<DetailProductData>> getProductDetail(int productId) async {
    try {
      DetailProductResponse response = await appClient.getProductDetail(productId);
      if (response.Data != null) {
        return ApiResult.success(data: response.Data!);
      } else {
        return ApiResult.failure(error: NetworkExceptions.unableToProcess());
      }
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<List<BaseCategoryData>>> getListCategory(BaseCategoryRequest request) async {
    try {
      BaseCategoryResponse response = await appClient.getListCategory(request);
      if (response.data != null) {
        return ApiResult.success(data: response.data!);
      } else {
        return ApiResult.failure(error: NetworkExceptions.unableToProcess());
      }
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<List<FilterData>>> getListFilter(FilterRequest request) async {
    try {
      FilterResponse response = await appClient.getListFilter(request);
      if (response.data != null) {
        return ApiResult.success(data: response.data!);
      } else {
        return ApiResult.failure(error: NetworkExceptions.unableToProcess());
      }
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<List<HomeCategoryData>>> getListHomeCategory({int pageNumber = 1}) async {
    try {
      HomeCategoryResponse response = await appClient.getListHomeCategory(HomeCategoryRequest(page: pageNumber, pageSize: Const.DEFAULT_SIZE));
      if (response.data != null) {
        return ApiResult.success(data: response.data!);
      } else {
        return ApiResult.failure(error: NetworkExceptions.unableToProcess());
      }
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<HomeConfigResponse>> getHomeConfig() async {
    try {
      HomeConfigResponse response = await appClient.getHomeConfig();
      return ApiResult.success(data: response);
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<List<PageData>>> getListPage() async {
    try {
      ListPageResponse response = await appClient.getListPage();
      if (response.data != null) {
        return ApiResult.success(data: response.data!);
      } else {
        return ApiResult.failure(error: NetworkExceptions.unableToProcess());
      }
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<List<ChooseCategoryData>>> getChooseCategory() async {
    try {
      ChooseCategoryResponse response = await appClient.getChooseCategory();
      if (response.Data != null) {
        return ApiResult.success(data: response.Data!);
      } else {
        return ApiResult.failure(error: NetworkExceptions.unableToProcess());
      }
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<List<TagHomeData>>> getTagHome() async {
    try {
      TagHomeResponse response = await appClient.getTagHome();
      if (response.Data != null) {
        return ApiResult.success(data: response.Data!);
      } else {
        return ApiResult.failure(error: NetworkExceptions.unableToProcess());
      }
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<List<CommunityData>>> getCommunity() async {
    try {
      ListCommunityResponse response = await appClient.getListCommunity();
      if (response.data != null) {
        return ApiResult.success(data: response.data!);
      } else {
        return ApiResult.failure(error: NetworkExceptions.unableToProcess());
      }
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }

  Future<ApiResult<List<ListCartData>>> getListCart() async {
    try {
      ListCartResponse response = await appClient.getListCart();
      if (response.Data != null) {
        return ApiResult.success(data: response.Data!);
      } else {
        return ApiResult.failure(error: NetworkExceptions.unableToProcess());
      }
    } catch (e) {
      return ApiResult.failure(error: NetworkExceptions.getDioException(e));
    }
  }
}
