import 'package:dio/dio.dart';
import '../../../../core/config/api_endpoints.dart';
import '../models/chat_message_model.dart';
import '../../presentation/widgets/conversation_drawer.dart';

/// Remote datasource for chat operations against the IT0 backend API.
class ChatRemoteDatasource {
  final Dio _dio;

  ChatRemoteDatasource(this._dio);

  /// Creates a new agent task within a session.
  /// Returns the response data containing sessionId and taskId.
  Future<Map<String, dynamic>> createTask({
    required String sessionId,
    required String message,
    List<Map<String, dynamic>>? attachments,
  }) async {
    final response = await _dio.post(
      ApiEndpoints.tasks,
      data: {
        'prompt': message,
        if (sessionId != 'new') 'sessionId': sessionId,
        if (attachments != null && attachments.isNotEmpty)
          'attachments': attachments,
      },
    );
    return response.data as Map<String, dynamic>;
  }

  /// Retrieves the message history for a given session.
  Future<List<ChatMessageModel>> getSessionHistory(String sessionId) async {
    final response = await _dio.get(
      '${ApiEndpoints.sessions}/$sessionId/messages',
    );

    final data = response.data;
    List<dynamic> messages;

    if (data is List) {
      messages = data;
    } else if (data is Map && data.containsKey('messages')) {
      messages = data['messages'] as List;
    } else if (data is Map && data.containsKey('items')) {
      messages = data['items'] as List;
    } else {
      messages = [];
    }

    return messages
        .map((m) => ChatMessageModel.fromJson(m as Map<String, dynamic>))
        .toList();
  }

  /// Lists all sessions for the current tenant.
  Future<List<SessionSummary>> listSessions() async {
    final response = await _dio.get(ApiEndpoints.sessions);
    final data = response.data;

    List<dynamic> sessions;
    if (data is List) {
      sessions = data;
    } else if (data is Map && data.containsKey('sessions')) {
      sessions = data['sessions'] as List;
    } else {
      sessions = [];
    }

    final list = sessions
        .map((s) => SessionSummary.fromJson(s as Map<String, dynamic>))
        .toList();

    // Sort by most recent first
    list.sort((a, b) => b.updatedAt.compareTo(a.updatedAt));
    return list;
  }

  /// Gets conversation messages for a session (from conversation_messages table).
  Future<List<ChatMessageModel>> getSessionMessages(String sessionId) async {
    final response = await _dio.get(
      '${ApiEndpoints.sessions}/$sessionId/messages',
      queryParameters: {'limit': '50'},
    );

    final data = response.data;
    List<dynamic> messages;

    if (data is Map && data.containsKey('messages')) {
      messages = data['messages'] as List;
    } else if (data is List) {
      messages = data;
    } else {
      messages = [];
    }

    return messages
        .map((m) => ChatMessageModel.fromJson(m as Map<String, dynamic>))
        .toList();
  }

  /// Deletes a session and all its messages.
  Future<void> deleteSession(String sessionId) async {
    await _dio.delete('${ApiEndpoints.sessions}/$sessionId');
  }

  /// Approves a pending command for a given task.
  Future<void> approveCommand(String taskId) async {
    await _dio.post(
      '${ApiEndpoints.tasks}/$taskId/approve',
      data: {'approved': true},
    );
  }

  /// Rejects a pending command for a given task with an optional reason.
  Future<void> rejectCommand(String taskId, {String? reason}) async {
    await _dio.post(
      '${ApiEndpoints.tasks}/$taskId/approve',
      data: {'approved': false},
    );
  }

  /// Cancels an active agent task by taskId.
  Future<void> cancelTask(String taskId) async {
    await _dio.delete('${ApiEndpoints.tasks}/$taskId');
  }

  /// Injects a message into an active task, cancelling current work and starting new task.
  Future<Map<String, dynamic>> injectMessage({
    required String taskId,
    required String message,
  }) async {
    final response = await _dio.post(
      '${ApiEndpoints.tasks}/$taskId/inject',
      data: {'message': message},
    );
    return response.data as Map<String, dynamic>;
  }

  /// Confirms a standing order draft proposed by the agent.
  Future<void> confirmStandingOrder(
    String sessionId,
    Map<String, dynamic> draft,
  ) async {
    await _dio.post(
      ApiEndpoints.standingOrders,
      data: {
        'sessionId': sessionId,
        ...draft,
      },
    );
  }

  /// Uploads an audio file to the voice-message endpoint.
  /// Backend performs STT, interrupts any running task if needed, and
  /// Transcribe audio to text (STT only, does NOT send to agent).
  /// No language hint is sent — Whisper auto-detects from audio content.
  Future<String> transcribeAudio({
    required String audioPath,
  }) async {
    final formData = FormData.fromMap({
      'audio': await MultipartFile.fromFile(
        audioPath,
        filename: audioPath.split('/').last,
      ),
    });
    final response = await _dio.post(
      '${ApiEndpoints.agent}/transcribe',
      data: formData,
    );
    final data = response.data as Map<String, dynamic>;
    return (data['text'] as String? ?? '').trim();
  }

  /// starts a new agent task with the transcript.
  /// Returns { sessionId, taskId, transcript }.
  Future<Map<String, dynamic>> sendVoiceMessage({
    required String sessionId,
    required String audioPath,
    String language = 'zh',
  }) async {
    final formData = FormData.fromMap({
      'audio': await MultipartFile.fromFile(
        audioPath,
        filename: audioPath.split('/').last,
      ),
      'language': language,
    });
    final response = await _dio.post(
      '${ApiEndpoints.sessions}/$sessionId/voice-message',
      data: formData,
    );
    return response.data as Map<String, dynamic>;
  }
}
