import 'dart:async';
import 'dart:io';

import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/foundation.dart';
import 'package:path_provider/path_provider.dart';
import 'package:record/record.dart';

import '../models/chat_models.dart';
import '../services/http_api_service.dart';
import 'debug_provider.dart';

class ChatProvider extends ChangeNotifier {
  ChatProvider({
    required HttpApiService httpApiService,
    required DebugProvider debugProvider,
  })  : _http = httpApiService,
        _debug = debugProvider;

  final HttpApiService _http;
  final DebugProvider _debug;
  final AudioRecorder _recorder = AudioRecorder();
  final AudioPlayer _player = AudioPlayer();

  final List<ChatBubble> _messages = <ChatBubble>[];
  String _sessionId = 'app_${DateTime.now().millisecondsSinceEpoch}';
  bool _busy = false;
  bool _recording = false;
  String? _error;
  String? _status;

  List<ChatBubble> get messages => List<ChatBubble>.unmodifiable(_messages);
  bool get isBusy => _busy;
  bool get isRecording => _recording;
  String? get error => _error;
  String? get status => _status;
  String get sessionId => _sessionId;

  void clearHistory() {
    _messages.clear();
    _sessionId = 'app_${DateTime.now().millisecondsSinceEpoch}';
    _error = null;
    _status = '已清空对话';
    notifyListeners();
  }

  Future<void> sendText(String text) async {
    final content = text.trim();
    if (content.isEmpty || _busy) return;

    _messages.add(ChatBubble(role: ChatBubbleRole.user, text: content));
    final pending = ChatBubble(
      role: ChatBubbleRole.assistant,
      text: '思考中...',
      isPending: true,
    );
    _messages.add(pending);
    _busy = true;
    _error = null;
    _status = '角色思考中...';
    notifyListeners();

    try {
      final response = await _http.chatText(
        text: content,
        sessionId: _sessionId,
      );
      await _applyResponse(pending, response);
    } catch (error) {
      pending
        ..isPending = false
        ..text = '请求失败: $error';
      _error = error.toString();
      _debug.addHttpLog('chatText failed', details: _error);
    } finally {
      _busy = false;
      if (_status == '角色思考中...') {
        _status = null;
      }
      notifyListeners();
    }
  }

  Future<bool> startRecording() async {
    if (_busy || _recording) return false;
    try {
      final hasPermission = await _recorder.hasPermission();
      if (!hasPermission) {
        _error = '需要麦克风权限才能语音对话';
        _status = _error;
        notifyListeners();
        return false;
      }
      final dir = await getTemporaryDirectory();
      final path =
          '${dir.path}/showen_rec_${DateTime.now().millisecondsSinceEpoch}.wav';
      await _recorder.start(
        const RecordConfig(
          encoder: AudioEncoder.wav,
          sampleRate: 16000,
          numChannels: 1,
        ),
        path: path,
      );
      _recording = true;
      _error = null;
      _status = '正在录音... 松开发送';
      _debug.addBleLog('Voice recording started');
      notifyListeners();
      return true;
    } catch (error) {
      _error = '无法开始录音: $error';
      _status = _error;
      _debug.addHttpLog('startRecording failed', details: _error);
      notifyListeners();
      return false;
    }
  }

  Future<void> cancelRecording() async {
    if (!_recording) return;
    try {
      final path = await _recorder.stop();
      if (path != null) {
        final file = File(path);
        if (await file.exists()) {
          await file.delete();
        }
      }
    } catch (_) {}
    _recording = false;
    _status = '已取消录音';
    notifyListeners();
  }

  Future<void> stopRecordingAndSend() async {
    if (!_recording || _busy) return;
    _recording = false;
    _status = '正在识别...';
    notifyListeners();

    String? path;
    try {
      path = await _recorder.stop();
    } catch (error) {
      _error = '停止录音失败: $error';
      _status = _error;
      notifyListeners();
      return;
    }

    if (path == null) {
      _error = '没有录到音频';
      _status = _error;
      notifyListeners();
      return;
    }

    final file = File(path);
    if (!await file.exists()) {
      _error = '录音文件不存在';
      _status = _error;
      notifyListeners();
      return;
    }

    final bytes = await file.readAsBytes();
    try {
      await file.delete();
    } catch (_) {}

    if (bytes.length < 1000) {
      _error = '录音太短，请按住再说一会儿';
      _status = _error;
      notifyListeners();
      return;
    }

    _messages.add(
      ChatBubble(role: ChatBubbleRole.user, text: '🎤 语音消息'),
    );
    final pending = ChatBubble(
      role: ChatBubbleRole.assistant,
      text: '思考中...',
      isPending: true,
    );
    _messages.add(pending);
    _busy = true;
    _status = '角色思考中...';
    notifyListeners();

    try {
      final response = await _http.chatAudio(
        bytes: bytes,
        format: 'wav',
        sessionId: _sessionId,
      );
      if (response.transcription != null &&
          response.transcription!.trim().isNotEmpty) {
        // 回填用户气泡为转写文本
        for (var i = _messages.length - 1; i >= 0; i--) {
          if (_messages[i].role == ChatBubbleRole.user) {
            _messages[i].text = response.transcription!;
            break;
          }
        }
      }
      await _applyResponse(pending, response);
    } catch (error) {
      pending
        ..isPending = false
        ..text = '语音对话失败: $error';
      _error = error.toString();
      _debug.addHttpLog('chatAudio failed', details: _error);
    } finally {
      _busy = false;
      if (_status == '角色思考中...') {
        _status = null;
      }
      notifyListeners();
    }
  }

  Future<void> _applyResponse(
    ChatBubble pending,
    ChatTurnResponse response,
  ) async {
    pending.isPending = false;
    if (!response.isOk) {
      pending.text = response.error ?? '对话失败';
      _error = pending.text;
      _status = pending.text;
      return;
    }
    if (response.sessionId.isNotEmpty) {
      _sessionId = response.sessionId;
    }
    pending.text = response.replyText.isEmpty ? '(空回复)' : response.replyText;
    pending.audioPath = response.replyAudioPath;
    _status = '已回复';
    _debug.addHttpLog(
      'chat ok',
      details: 'chars=${pending.text.length} audio=${pending.audioPath != null}',
    );
    if (pending.audioPath != null && pending.audioPath!.isNotEmpty) {
      unawaited(playReply(pending.audioPath!));
    }
  }

  Future<void> playReply(String absolutePath) async {
    try {
      final url = _http.chatAudioFileUrl(absolutePath);
      await _player.stop();
      await _player.play(UrlSource(url));
      _status = '正在播放回复...';
      notifyListeners();
    } catch (error) {
      _error = '播放失败: $error';
      _debug.addHttpLog('playReply failed', details: _error);
      notifyListeners();
    }
  }

  @override
  void dispose() {
    unawaited(_recorder.dispose());
    unawaited(_player.dispose());
    super.dispose();
  }
}
