import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/api/etqan_ovr_api_client.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/models/etqan_ovr/etqan_get_employee_incident_report.dart';
import 'package:mohem_flutter_app/models/etqan_ovr/etqan_get_requests_model.dart';
import 'package:mohem_flutter_app/models/etqan_ovr/etqan_getprojects_model.dart';
import 'package:speech_to_text/speech_recognition_result.dart';
import 'package:speech_to_text/speech_to_text.dart';

class EtqanOvrProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
  // Home screen state
  List<EtqanGetProjectsResponse>? getEtqanProjectsList;
  List<EtqanGetEmployeeOvrRequestsResponse>? getEtqanEmployeeRequestsList;
  List<EtqanGetIncidentRequestResponse>? getEtqanEmployeeIncidnetRequest;
  bool isLoading = false;
  String? _ticketId;
  String? _currentStatus;
  String? _currentStatusAr;
  bool? _currentIsAnonymous;

  // Speech to text state
  final SpeechToText _speechToText = SpeechToText();
  bool _speechEnabled = false;
  bool _isListening = false;
  String _currentLocaleId = '';
  TextEditingController? _currentController;
  String _baseText = ''; // Text that was there when we started listening
  String _currentSessionText = ''; // Text captured in current listening session

  // Getters for speech state
  bool get speechEnabled => _speechEnabled;

  bool get isListening => _isListening;

  // Getter for ticketId
  String get getTicketId => _ticketId ?? '';
  String get getCurrentStatus => _currentStatus ?? '';
  String get getCurrentStatusAr => _currentStatusAr ?? '';
  bool get getCurrentIsAnonymous => _currentIsAnonymous ?? false;

  // Setter for ticketId with status and isAnonymous
  void setTicketId(String ticketId, {String? status, String? statusAr, bool? isAnonymous}) {
    _ticketId = ticketId;
    _currentStatus = status;
    _currentStatusAr = statusAr;
    _currentIsAnonymous = isAnonymous;
    notifyListeners();
  }

  // Create request screen state
  EtqanGetProjectsResponse? selectedProject;
  String? selectedEmployeeNumber;
  File? attachment;
  String? attachmentBase64;
  String description = '';
  bool isAnonymous = false;

  /// Initialize speech recognition - call this once when screen loads
  Future<void> initSpeech() async {
    _speechEnabled = await _speechToText.initialize(
      onStatus: (String status) {
        print('Speech status: $status, isListening: $_isListening');
        // If user wants to keep listening but speech stopped, restart it
        if ((status == 'done' || status == 'notListening') && _isListening && _currentController != null) {
          // Save the finalized text before restarting
          if (_currentSessionText.isNotEmpty) {
            _baseText = _currentController!.text.trim();
            _currentSessionText = '';
          }

          // Automatically restart listening after a brief pause
          Future.delayed(const Duration(milliseconds: 300), () {
            if (_isListening && _currentController != null) {
              _startListeningInternal(_currentLocaleId, _currentController!);
            }
          });
        }
      },
    );
    notifyListeners();
  }

  /// Internal method to start listening
  Future<void> _startListeningInternal(String localeId, TextEditingController controller) async {
    if (!_speechEnabled) return;

    await _speechToText.listen(
      onResult: (SpeechRecognitionResult result) {
        _currentSessionText = result.recognizedWords;

        // Combine base text with current session text
        String combinedText = _baseText.isEmpty
            ? _currentSessionText
            : _baseText + (_baseText.endsWith(' ') ? '' : ' ') + _currentSessionText;

        description = combinedText;
        controller.text = combinedText;
        controller.selection = TextSelection.fromPosition(TextPosition(offset: controller.text.length));
        notifyListeners();
      },
      localeId: localeId,
      listenFor: const Duration(seconds: 60),
      pauseFor: const Duration(seconds: 10),
      listenOptions: SpeechListenOptions(
        partialResults: true,
        listenMode: ListenMode.confirmation,
        cancelOnError: false,
      ),
    );
  }

  /// Start listening for speech input
  Future<void> startListening(String localeId, TextEditingController controller) async {
    _isListening = true;
    _currentLocaleId = localeId;
    _currentController = controller;
    _baseText = controller.text.trim(); // Save existing text
    _currentSessionText = '';
    notifyListeners();
    await _startListeningInternal(localeId, controller);
  }

  /// Stop listening for speech input
  Future<void> stopListening() async {
    _isListening = false;
    _currentLocaleId = '';
    _currentController = null;
    _baseText = '';
    _currentSessionText = '';
    await _speechToText.stop();
    notifyListeners();
  }

  /// Toggle listening state
  Future<void> toggleListening(String localeId, TextEditingController controller) async {
    if (_isListening) {
      await stopListening();
    } else {
      await startListening(localeId, controller);
    }
  }

  // Fetch Etqan Projects
  Future<void> fetchEtqanProjects(BuildContext context) async {
    isLoading = true;
    notifyListeners();
    Utils.showLoading(context);
    getEtqanProjectsList?.clear();
    getEtqanProjectsList = await EtqanApiClient().getEtqanProjects();
    Utils.hideLoading(context);
    isLoading = false;
    notifyListeners();
  }

  // Fetch Etqan Employee Requests
  Future<void> fetchEtqanEmployeeRequests(BuildContext context) async {
    isLoading = true;
    notifyListeners();
    Utils.showLoading(context);
    getEtqanEmployeeRequestsList?.clear();
    getEtqanEmployeeRequestsList = await EtqanApiClient().getEmployeeEtqanRequests();
    Utils.hideLoading(context);
    isLoading = false;
    notifyListeners();
  }

  // Fetch Etqan Employee Incident Report
  Future<void> fetchEtqanEmployeeIncidentRequests(BuildContext context, String ticketNo) async {
    isLoading = true;
    notifyListeners();
    Utils.showLoading(context);
    getEtqanEmployeeIncidnetRequest?.clear();
    getEtqanEmployeeIncidnetRequest = await EtqanApiClient().getEtqanIncidentRequests(ticketNo);
    Utils.hideLoading(context);
    isLoading = false;
    notifyListeners();
  }

  // Set selected project
  void setSelectedProject(EtqanGetProjectsResponse? project) {
    selectedProject = project;
    notifyListeners();
  }

  // Set selected employee number
  void setSelectedEmployeeNumber(String? employeeNumber) {
    selectedEmployeeNumber = employeeNumber;
    notifyListeners();
  }

  // Set attachment with base64
  void setAttachment(File file, String base64) {
    attachment = file;
    attachmentBase64 = base64;
    notifyListeners();
  }

  // Remove attachment
  void removeAttachment() {
    attachment = null;
    attachmentBase64 = null;
    notifyListeners();
  }

  // Set description
  void setDescription(String value) {
    description = value;
    notifyListeners();
  }

  // Validate description
  bool isDescriptionValid() {
    return description.trim().isNotEmpty;
  }

  // Set isAnonymous
  void setIsAnonymous(bool value) {
    isAnonymous = value;
    notifyListeners();
  }

  // Clear create request form
  void clearCreateRequestForm() {
    selectedProject = null;
    selectedEmployeeNumber = null;
    attachment = null;
    attachmentBase64 = null;
    description = '';
    isAnonymous = false;
    notifyListeners();
  }

  // Submit request
  Future<Map<String, dynamic>?> submitRequest(BuildContext context) async {
    try {
      Utils.showLoading(context);
      Map<String, dynamic>? response = await EtqanApiClient().createRequest(description, selectedProject?.projectId, attachmentBase64, isAnonymous);
      Utils.hideLoading(context);
      if (response != null) {
        getEtqanEmployeeRequestsList = await EtqanApiClient().getEmployeeEtqanRequests();
        notifyListeners();
        return response;
      }
      return null;
    } catch (ex) {
      Utils.hideLoading(context);
      Utils.handleException(ex, context, null);
      return null;
    }
  }

  @override
  void dispose() {
    if (_isListening) {
      _speechToText.stop();
    }
    super.dispose();
  }
}
