import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:tm_app/core/theme/colors.dart';
import 'package:tm_app/core/utils/result.dart';
import 'package:tm_app/data/repositories/your_tenders_repository.dart';
import 'package:tm_app/data/services/model/liked_tenders_response/liked_tenders_response.dart';
import 'package:tm_app/data/services/model/tender_approvals_response/tender_approvals_response.dart';
import 'package:tm_app/views/your_tenders/strings/your_tenders_strings.dart';

import '../core/constants/assets.dart';
import '../core/constants/tender_approval_status.dart';
import '../core/constants/tender_feedback.dart';
import '../data/services/model/request_models/get_tenders_request_model/get_tenders_request_model.dart';
import '../data/services/model/request_models/tender_feedback_request_model/tender_feedback_request_model.dart';

class YourTendersViewModel with ChangeNotifier {
  final YourTendersRepository yourTendersRepository;
  YourTendersViewModel({required this.yourTendersRepository});

  bool isLoading = false;
  String? errorMessage;
  TenderApprovalsResponse? data;
  LikedTendersResponse? likedTendersData;

  // Pagination state for feedback lists
  bool isLoadingMore = false;
  bool hasMore = true;
  int _offset = 0;
  final int _limit = 10;
  String? _currentFeedbackType;

  // Pagination state for tenders
  bool isLoadingMoreTenders = false;
  bool hasMoreTenders = true;
  int _tendersOffset = 0;
  final int _tendersLimit = 10;

  // Filter States
  DateTimeRange? selectedDateRange;
  String selectedStatus = 'All';
  final _fmt = DateFormat('yyyy/MM/dd');

  String get startDateFormatted =>
      selectedDateRange?.start != null
          ? _fmt.format(selectedDateRange!.start)
          : 'YYYY/MM/DD';

  String get endDateFormatted =>
      selectedDateRange?.end != null
          ? _fmt.format(selectedDateRange!.end)
          : 'YYYY/MM/DD';

  String get startDateUnix =>
      selectedDateRange?.start != null
          ? (selectedDateRange!.start.millisecondsSinceEpoch ~/ 1000).toString()
          : '';

  String get endDateUnix =>
      selectedDateRange?.end != null
          ? (selectedDateRange!.end.millisecondsSinceEpoch ~/ 1000).toString()
          : '';

  Future<void> getTenders({
    required GetTendersRequestModel requestModel,
    bool reset = false,
  }) async {
    if (!reset && (isLoadingMoreTenders || !hasMoreTenders)) {
      return;
    }

    if (reset) {
      _tendersOffset = 0;
      hasMoreTenders = true;
      data = null;
    }

    if (_tendersOffset == 0) {
      isLoading = true;
    } else {
      isLoadingMoreTenders = true;
    }
    notifyListeners();

    final result = await yourTendersRepository.getTenders(
      requestModel: requestModel,
    );

    switch (result) {
      case Ok<TenderApprovalsResponse>():
        final incoming = result.value;
        final incomingList = incoming.data?.tenders ?? [];

        if (reset || data == null) {
          data = incoming;
        } else {
          final existingList = data!.data?.tenders ?? [];
          final combined = List.of(existingList)..addAll(incomingList);
          final newMetadata = incoming.data?.metadata ?? data!.data?.metadata;
          data = data!.copyWith(
            data: data!.data!.copyWith(
              tenders: combined,
              metadata: newMetadata,
            ),
          );
        }

        hasMoreTenders = incomingList.length == _tendersLimit;
        _tendersOffset += _tendersLimit;
        errorMessage = null;
        break;
      case Error<TenderApprovalsResponse>():
        errorMessage = result.error.toString();
        break;
    }

    isLoading = false;
    isLoadingMoreTenders = false;
    notifyListeners();
  }

  Future<void> getTendersFeedback({
    required String feedbackType,
    bool reset = false,
  }) async {
    if (reset) {
      _offset = (currentPage - 1) * _limit;
      hasMore = true;
      _currentFeedbackType = feedbackType;
    }

    if (!reset && (isLoadingMore || !hasMore)) {
      return;
    }

    if (_offset == 0) {
      isLoading = true;
    } else {
      isLoadingMore = true;
    }
    notifyListeners();

    final requestModel = TenderFeedbackRequestModel(
      offset: _offset,
      limit: _limit,
      feedbackType: _currentFeedbackType ?? feedbackType,
      dateFrom: startDateUnix,
      dateTo: endDateUnix,
    );

    final result = await yourTendersRepository.getTendersFeedback(
      requestModel: requestModel,
    );

    switch (result) {
      case Ok<LikedTendersResponse>():
        final incoming = result.value;
        final incomingList = incoming.data?.feedback ?? [];

        if (reset || likedTendersData == null) {
          likedTendersData = incoming;
        } else {
          final existingList = likedTendersData!.data?.feedback ?? [];
          final combined = List.of(existingList)..addAll(incomingList);
          final newMeta = incoming.data?.meta ?? likedTendersData!.data?.meta;
          likedTendersData = likedTendersData!.copyWith(
            data: likedTendersData!.data!.copyWith(
              feedback: combined,
              meta: newMeta,
            ),
          );
        }

        hasMore = incomingList.length == _limit;
        _offset += _limit;
        errorMessage = null;
        break;
      case Error<LikedTendersResponse>():
        errorMessage = result.error.toString();
        break;
    }

    isLoading = false;
    isLoadingMore = false;
    notifyListeners();
  }

  Future<void> loadMoreFeedback() async {
    if (_currentFeedbackType == null) {
      return;
    }
    await getTendersFeedback(feedbackType: _currentFeedbackType!, reset: false);
  }

  Future<void> loadMoreTenders() async {
    if (isLoadingMoreTenders || !hasMoreTenders) {
      return;
    }

    if (selectedStatus == YourTendersStrings.all) {
      final requestModel = GetTendersRequestModel(
        status: '',
        createdFrom: startDateUnix,
        createdTo: endDateUnix,
        limit: _tendersLimit,
        offset: _tendersOffset,
      );
      await getTenders(requestModel: requestModel);
    } else if (selectedStatus == YourTendersStrings.tendersSubmitted) {
      final requestModel = GetTendersRequestModel(
        status: TenderApprovalStatus.submitted.value,
        createdFrom: startDateUnix,
        createdTo: endDateUnix,
        limit: _tendersLimit,
        offset: _tendersOffset,
      );
      await getTenders(requestModel: requestModel);
    }
  }

  // --- Filter Actions ---
  void setDateRange(DateTimeRange? range) {
    selectedDateRange = range;
    notifyListeners();
  }

  void setStatus(String status) {
    // Clear data when status changes
    _clearAllData();
    selectedStatus = status;
    currentPage = 1;
    notifyListeners();
  }

  void clearFilter() {
    // Clear data when clearing filter
    _clearAllData();
    selectedDateRange = null;
    selectedStatus = YourTendersStrings.all;
    notifyListeners();
  }

  // Clear all data and reset states
  void _clearAllData() {
    // Clear main data
    data = null;
    likedTendersData = null;

    // Clear loading states
    isLoading = false;
    isLoadingMore = false;
    isLoadingMoreTenders = false;

    // Clear error messages
    errorMessage = null;

    // Reset pagination states
    _offset = 0;
    _tendersOffset = 0;
    hasMore = true;
    hasMoreTenders = true;
    _currentFeedbackType = null;

    notifyListeners();
  }

  Future<void> callWithFilter() async {
    likedTendersData = null;
    data = null;
    isLoading = true;
    notifyListeners();

    if (selectedStatus == YourTendersStrings.all) {
      final requestModel = GetTendersRequestModel(
        status: '',
        createdFrom: startDateUnix,
        createdTo: endDateUnix,
        limit: _tendersLimit,
        offset: _tendersOffset,
      );
      await getTenders(requestModel: requestModel, reset: true);
    } else if (selectedStatus == YourTendersStrings.tendersSubmitted) {
      final requestModel = GetTendersRequestModel(
        status: TenderApprovalStatus.submitted.value,
        createdFrom: startDateUnix,
        createdTo: endDateUnix,
        limit: _tendersLimit,
        offset: _tendersOffset,
      );
      await getTenders(requestModel: requestModel, reset: true);
    } else if (selectedStatus == YourTendersStrings.likeTenders) {
      await getTendersFeedback(
        feedbackType: TenderFeedback.liked.value,
        reset: true,
      );
    } else if (selectedStatus == YourTendersStrings.dislikeTenders) {
      await getTendersFeedback(
        feedbackType: TenderFeedback.disliked.value,
        reset: true,
      );
    }
  }

  int currentPage = 1;

  int get totalPages {
    if (likedTendersData?.data?.meta?.pages != null) {
      return likedTendersData!.data!.meta!.pages!;
    }
    if (data?.data?.metadata?.pages != null) {
      return data!.data!.metadata!.pages!;
    }
    return 1;
  }

  Future<void> jumpToPage(int page) async {
    currentPage = page;
    _offset = (page - 1) * _limit;
    _tendersOffset = (page - 1) * _tendersLimit;

    likedTendersData = null;
    data = null;
    hasMore = true;
    hasMoreTenders = true;

    await callWithFilter();
  }

  Color getBackGroundColorByStatus(String status) {
    if (status == TenderFeedback.liked.value ||
        status == TenderApprovalStatus.submitted.value) {
      return AppColors.green0;
    } else if (status == TenderFeedback.disliked.value ||
        status == TenderApprovalStatus.rejected.value) {
      return AppColors.red0;
    }
    return AppColors.grey0;
  }

  Color getBorderColorByStatus(String status) {
    if (status == TenderFeedback.liked.value ||
        status == TenderApprovalStatus.submitted.value) {
      return AppColors.green10;
    } else if (status == TenderFeedback.disliked.value ||
        status == TenderApprovalStatus.rejected.value) {
      return AppColors.red10;
    }
    return AppColors.grey30;
  }

  Color getStatusCardColorByStatus(String status) {
    if (status == TenderFeedback.liked.value ||
        status == TenderApprovalStatus.submitted.value) {
      return AppColors.green20;
    } else if (status == TenderFeedback.disliked.value ||
        status == TenderApprovalStatus.rejected.value) {
      return AppColors.red10;
    }
    return AppColors.grey0;
  }

  Color getStatusTextColorByStatus(String status) {
    if (status == TenderFeedback.liked.value ||
        status == TenderApprovalStatus.submitted.value) {
      return AppColors.green30;
    } else if (status == TenderFeedback.disliked.value ||
        status == TenderApprovalStatus.rejected.value) {
      return AppColors.red20;
    }
    return AppColors.grey60;
  }

  String? getStatusIconByStatus(String status) {
    if (status == TenderFeedback.liked.value ||
        status == TenderApprovalStatus.submitted.value) {
      return AssetsManager.tickCircle;
    } else if (status == TenderFeedback.disliked.value ||
        status == TenderApprovalStatus.rejected.value) {
      return AssetsManager.closeCircle;
    }
    return null;
  }
}
