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

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:path_provider/path_provider.dart';
import 'package:record/record.dart';

import '../../../core/storage/secure_storage.dart';
import '../../../core/network/dio_client.dart';
import '../../../core/services/voice_assistant_service.dart';
import '../../../core/utils/app_snackbar.dart';
import '../../../core/utils/logger.dart';
import '../../../app/routes/app_pages.dart';
import '../../invoices/controllers/invoices_controller.dart';
import '../../main_shell/controllers/main_shell_controller.dart';

class DashboardController extends GetxController {
  final SecureStorage _storage = SecureStorage();
  final Dio _dio = DioClient().client;
  final VoiceAssistantService _voiceAssistantService = VoiceAssistantService();
  final AudioRecorder _audioRecorder = AudioRecorder();
  Timer? _recordTimer;

  var isLoading = true.obs;
  var stats = {}.obs;
  var recentActivities = [].obs;
  var userRole = ''.obs;

  final isVoiceRecording = false.obs;
  final isVoiceUploading = false.obs;
  final voiceRemainingSeconds = 15.obs;
  final voiceStatusText = 'اضغط "ابدأ التسجيل" ثم تحدّث'.obs;

  @override
  void onInit() {
    super.onInit();
    _loadDashboardData();
  }

  @override
  void onClose() {
    _recordTimer?.cancel();
    _audioRecorder.dispose();
    super.onClose();
  }

  Future<void> _loadDashboardData() async {
    try {
      isLoading.value = true;
      final token = await _storage.getToken();

      if (token == null || token.isEmpty) {
        Get.offAllNamed(AppRoutes.PHONE_INPUT);
        return;
      }

      // Fetch Stats
      final statsResponse = await _dio.get('dashboard/stats');
      if (statsResponse.data['success'] == true) {
        stats.value = statsResponse.data['data'];
        userRole.value = statsResponse.data['data']['role'] ?? '';
        // Save role to storage for other controllers to use
        if (userRole.value.isNotEmpty) {
          await _storage.write('user_role', userRole.value);
        }
      }

      // Fetch Recent Activity
      final activityResponse = await _dio.get('dashboard/recent-activity');
      if (activityResponse.data['success'] == true) {
        recentActivities.value = activityResponse.data['data'];
      }
    } on DioException catch (e) {
      AppLogger.error('Dashboard Data Fetch Error', e);
      if (e.response?.statusCode == 401 || e.response?.statusCode == 403) {
        await logout();
      } else {
        AppSnackbar.showError(
            'خطأ', 'فشل في جلب البيانات. الرجاء التحقق من اتصالك بالإنترنت.');
      }
    } catch (e) {
      AppLogger.error('Unexpected error fetching dashboard', e);
    } finally {
      isLoading.value = false;
    }
  }

  Future<void> logout() async {
    await _storage.clearAll();
    Get.offAllNamed(AppRoutes.PHONE_INPUT);
  }

  void startVoiceAssistant() {
    _resetVoiceState();

    Get.bottomSheet(
      Obx(
        () => Container(
          padding: const EdgeInsets.all(24),
          decoration: BoxDecoration(
            color: Get.isDarkMode ? const Color(0xFF1E1E2E) : Colors.white,
            borderRadius: const BorderRadius.only(
              topLeft: Radius.circular(30),
              topRight: Radius.circular(30),
            ),
          ),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Container(
                width: 40,
                height: 4,
                margin: const EdgeInsets.only(bottom: 18),
                decoration: BoxDecoration(
                  color: Colors.grey.withValues(alpha: 0.3),
                  borderRadius: BorderRadius.circular(2),
                ),
              ),
              Row(
                children: [
                  const Icon(Icons.auto_awesome, color: Color(0xFF5EEAD4)),
                  const SizedBox(width: 12),
                  Text(
                    'المساعد الصوتي (Gemini)',
                    style: TextStyle(
                      fontSize: 18,
                      fontWeight: FontWeight.bold,
                      color: Get.isDarkMode
                          ? Colors.white
                          : const Color(0xFF0F4C81),
                    ),
                  ),
                ],
              ),
              const SizedBox(height: 18),
              Text(
                voiceStatusText.value,
                textAlign: TextAlign.center,
                style: TextStyle(
                  fontSize: 13,
                  color: Get.isDarkMode ? Colors.white70 : Colors.black87,
                ),
              ),
              const SizedBox(height: 14),
              Text(
                '${voiceRemainingSeconds.value}s',
                style: TextStyle(
                  fontFamily: 'monospace',
                  fontWeight: FontWeight.bold,
                  fontSize: 18,
                  color: isVoiceRecording.value
                      ? const Color(0xFFDC2626)
                      : const Color(0xFF0F4C81),
                ),
              ),
              const SizedBox(height: 12),
              ClipRRect(
                borderRadius: BorderRadius.circular(6),
                child: LinearProgressIndicator(
                  value: (15 - voiceRemainingSeconds.value) / 15,
                  minHeight: 8,
                  color: isVoiceRecording.value
                      ? const Color(0xFFDC2626)
                      : const Color(0xFF0F4C81),
                  backgroundColor:
                      Get.isDarkMode ? Colors.white10 : const Color(0xFFE2E8F0),
                ),
              ),
              const SizedBox(height: 20),
              Row(
                children: [
                  Expanded(
                    child: OutlinedButton.icon(
                      onPressed: isVoiceUploading.value
                          ? null
                          : () async {
                              if (isVoiceRecording.value) {
                                await _stopAndUploadVoice(autoStopped: false);
                              } else {
                                await _startVoiceRecording();
                              }
                            },
                      icon: Icon(
                        isVoiceRecording.value
                            ? Icons.stop_circle_outlined
                            : Icons.mic_none_rounded,
                      ),
                      label: Text(
                        isVoiceRecording.value
                            ? 'إيقاف وإرسال'
                            : 'ابدأ التسجيل',
                      ),
                      style: OutlinedButton.styleFrom(
                        foregroundColor: isVoiceRecording.value
                            ? const Color(0xFFDC2626)
                            : const Color(0xFF0F4C81),
                        side: BorderSide(
                          color: isVoiceRecording.value
                              ? const Color(0xFFDC2626)
                              : const Color(0xFF0F4C81),
                        ),
                        padding: const EdgeInsets.symmetric(vertical: 14),
                        shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(12),
                        ),
                      ),
                    ),
                  ),
                  const SizedBox(width: 12),
                  Expanded(
                    child: ElevatedButton.icon(
                      onPressed:
                          isVoiceRecording.value || isVoiceUploading.value
                              ? null
                              : () => Get.back(),
                      icon: const Icon(Icons.close),
                      label: const Text('إغلاق'),
                      style: ElevatedButton.styleFrom(
                        backgroundColor: const Color(0xFF0F4C81),
                        foregroundColor: Colors.white,
                        padding: const EdgeInsets.symmetric(vertical: 14),
                        shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(12),
                        ),
                      ),
                    ),
                  ),
                ],
              ),
              if (isVoiceUploading.value) ...[
                const SizedBox(height: 14),
                const SizedBox(
                  height: 20,
                  width: 20,
                  child: CircularProgressIndicator(strokeWidth: 2),
                ),
              ],
            ],
          ),
        ),
      ),
      isScrollControlled: true,
      isDismissible: false,
    );
  }

  Future<void> _startVoiceRecording() async {
    if (isVoiceUploading.value) return;

    final hasPermission = await _audioRecorder.hasPermission();
    if (!hasPermission) {
      AppSnackbar.showError('صلاحيات', 'الرجاء السماح بالوصول للميكروفون');
      return;
    }

    final tempDir = await getTemporaryDirectory();
    final wavSupported =
        await _audioRecorder.isEncoderSupported(AudioEncoder.wav);
    final flacSupported =
        await _audioRecorder.isEncoderSupported(AudioEncoder.flac);

    final AudioEncoder encoder;
    final String extension;
    if (wavSupported) {
      encoder = AudioEncoder.wav;
      extension = 'wav';
    } else if (flacSupported) {
      encoder = AudioEncoder.flac;
      extension = 'flac';
    } else {
      AppSnackbar.showError(
        'الصوت',
        'هذا الجهاز لا يدعم صيغة صوت مناسبة لـ Gemini حالياً',
      );
      return;
    }

    final path =
        '${tempDir.path}/voice_${DateTime.now().millisecondsSinceEpoch}.$extension';

    AppLogger.print(
      'Voice recorder selected encoder=$encoder, wavSupported=$wavSupported, flacSupported=$flacSupported, path=$path',
    );

    await _audioRecorder.start(
      RecordConfig(
        encoder: encoder,
        sampleRate: 16000,
        numChannels: 1,
      ),
      path: path,
    );

    isVoiceRecording.value = true;
    voiceRemainingSeconds.value = 15;
    voiceStatusText.value = 'جاري التسجيل... تكلم الآن';
    _startVoiceCountdown();
  }

  void _startVoiceCountdown() {
    _recordTimer?.cancel();
    _recordTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
      final next = voiceRemainingSeconds.value - 1;
      voiceRemainingSeconds.value = next;

      if (next <= 0) {
        timer.cancel();
        _stopAndUploadVoice(autoStopped: true);
      }
    });
  }

  Future<void> _stopAndUploadVoice({required bool autoStopped}) async {
    if (!isVoiceRecording.value) return;

    _recordTimer?.cancel();
    isVoiceRecording.value = false;
    voiceStatusText.value = autoStopped
        ? 'تم الإيقاف التلقائي، جاري الإرسال...'
        : 'جاري الإرسال...';

    final recordPath = await _audioRecorder.stop();
    if (recordPath == null || recordPath.isEmpty) {
      voiceStatusText.value = 'فشل حفظ التسجيل الصوتي';
      AppSnackbar.showError('خطأ', 'فشل حفظ التسجيل الصوتي');
      return;
    }

    await _uploadVoiceCommand(File(recordPath));
  }

  Future<void> _uploadVoiceCommand(File audioFile) async {
    isVoiceUploading.value = true;

    try {
      final result =
          await _voiceAssistantService.processVoiceCommand(audioFile);
      final intent = Map<String, dynamic>.from(
        (result['intent'] as Map?) ?? <String, dynamic>{},
      );
      final execution = Map<String, dynamic>.from(
        (result['execution'] as Map?) ?? <String, dynamic>{},
      );

      final action = (intent['action'] ?? '').toString();
      final params = _asStringMap(intent['params']);
      final confirmation = (intent['confirmation'] ??
              execution['message'] ??
              'تم تنفيذ الأمر الصوتي')
          .toString();
      final executionStatus = (execution['status'] ?? 'unknown').toString();

      AppSnackbar.showSuccess('المساعد الصوتي', confirmation);

      if (executionStatus == 'failed') {
        AppSnackbar.showError(
          'فشل التنفيذ',
          (execution['message'] ?? 'تعذر تنفيذ الأمر داخليًا').toString(),
        );
      } else {
        _executeAction(action, params, execution);
      }
    } on DioException catch (e) {
      AppLogger.error('Voice upload error', e.response?.data ?? e.message);
      String errorMsg = 'تعذر إرسال التسجيل الصوتي';
      if (e.response != null && e.response?.data != null) {
        if (e.response?.data is Map && e.response?.data['message'] != null) {
          errorMsg = e.response?.data['message'];
        }
      }
      AppSnackbar.showError('خطأ', errorMsg);
    } catch (e, stack) {
      AppLogger.error('Voice Assistant Error', e, stack);
      AppSnackbar.showError('خطأ', 'حدث خطأ غير متوقع');
    } finally {
      isVoiceUploading.value = false;
      voiceStatusText.value = 'جاهز لأمر صوتي جديد';

      // Close voice sheet if still open.
      if (Get.isBottomSheetOpen == true) {
        Get.back();
      }
    }
  }

  Map<String, dynamic> _asStringMap(dynamic value) {
    if (value is Map) {
      return Map<String, dynamic>.from(value);
    }
    return <String, dynamic>{};
  }

  void _executeAction(
    String action,
    Map<String, dynamic> params,
    Map<String, dynamic> execution,
  ) {
    switch (action) {
      case 'list_invoices':
      case 'search_invoice':
        _openInvoicesFromVoice(params, execution);
        break;
      case 'open_scanner':
        Get.toNamed(AppRoutes.SCANNER);
        break;
      case 'check_quota':
        _showQuotaResult(execution);
        break;
      case 'navigate':
        final screen = params['screen']?.toString().toLowerCase();
        if (screen == 'settings') {
          Get.toNamed(AppRoutes.MAIN);
        } else if (screen == 'scanner') {
          Get.toNamed(AppRoutes.SCANNER);
        } else {
          Get.toNamed(AppRoutes.MAIN);
        }
        break;
      case 'check_status':
      case 'get_report':
      case 'export_pdf':
        AppSnackbar.showWarning(
          'تم التنفيذ',
          'تم تنفيذ الأمر على الخادم وسيتم تحسين عرض النتائج داخل التطبيق قريباً',
        );
        break;
      default:
        AppSnackbar.showWarning(
            'تنبيه', 'الأمر مفهوم ولكن لم يتم ربط الأكشن برمجياً بعد.');
    }
  }

  void _openInvoicesFromVoice(
    Map<String, dynamic> params,
    Map<String, dynamic> execution,
  ) {
    final invoicesController = Get.isRegistered<InvoicesController>()
        ? Get.find<InvoicesController>()
        : Get.put(InvoicesController());

    invoicesController.applyVoiceFilters(params);

    if (Get.isRegistered<MainShellController>()) {
      Get.find<MainShellController>().selectTab(1);
    } else {
      Get.offAllNamed(AppRoutes.MAIN);
    }

    final data = execution['data'];
    final count = data is Map ? data['count'] : null;
    final status = params['status']?.toString();
    final suffix = count == null ? '' : ' ($count)';
    final label = status == 'approved'
        ? 'المعتمدة'
        : status == 'extracted'
            ? 'الجاهزة'
            : 'المطابقة';

    AppSnackbar.showSuccess('الفواتير', 'تم عرض الفواتير $label$suffix');
  }

  void _showQuotaResult(Map<String, dynamic> execution) {
    final data = _asStringMap(execution['data']);
    if (data.isEmpty) {
      AppSnackbar.showWarning('الاشتراك', 'لم تصل تفاصيل الاشتراك من الخادم');
      return;
    }

    final planName = (data['plan_name'] ?? 'غير معروف').toString();
    final status = _subscriptionStatusLabel(data['status']);
    final days = data['days_remaining'];

    Get.bottomSheet(
      Container(
        padding: const EdgeInsets.fromLTRB(20, 16, 20, 24),
        decoration: BoxDecoration(
          color: Get.isDarkMode ? const Color(0xFF1E1E2E) : Colors.white,
          borderRadius: const BorderRadius.vertical(top: Radius.circular(24)),
        ),
        child: SafeArea(
          top: false,
          child: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Center(
                child: Container(
                  width: 40,
                  height: 4,
                  decoration: BoxDecoration(
                    color: Colors.grey.withValues(alpha: 0.35),
                    borderRadius: BorderRadius.circular(2),
                  ),
                ),
              ),
              const SizedBox(height: 18),
              Row(
                children: [
                  const Icon(Icons.workspace_premium_rounded,
                      color: Color(0xFFD4AF37)),
                  const SizedBox(width: 10),
                  Expanded(
                    child: Text(
                      'اشتراكك الحالي',
                      style: TextStyle(
                        fontSize: 18,
                        fontWeight: FontWeight.w800,
                        color: Get.isDarkMode
                            ? Colors.white
                            : const Color(0xFF0F172A),
                      ),
                    ),
                  ),
                ],
              ),
              const SizedBox(height: 14),
              Text(
                '$planName • $status${days == null ? '' : ' • $days يوم متبقي'}',
                style: TextStyle(
                  fontSize: 14,
                  fontWeight: FontWeight.w600,
                  color:
                      Get.isDarkMode ? Colors.white70 : const Color(0xFF334155),
                ),
              ),
              const SizedBox(height: 18),
              _buildQuotaRow('الفواتير', data['invoices'], Icons.receipt_long),
              const SizedBox(height: 12),
              _buildQuotaRow('الشركات', data['companies'], Icons.business),
              const SizedBox(height: 12),
              _buildQuotaRow('المستخدمين', data['users'], Icons.people),
            ],
          ),
        ),
      ),
      isScrollControlled: true,
    );
  }

  Widget _buildQuotaRow(String label, dynamic raw, IconData icon) {
    final item = _asStringMap(raw);
    final used = item['used'] ?? 0;
    final limit = item['limit'] ?? 0;
    final percent = ((item['percent'] as num?) ?? 0).clamp(0, 100).toDouble();
    final warning = item['warning'] == true;
    final color = warning ? const Color(0xFFDC2626) : const Color(0xFF0F4C81);

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Row(
          children: [
            Icon(icon, size: 18, color: color),
            const SizedBox(width: 8),
            Expanded(
              child: Text(
                label,
                style: const TextStyle(fontWeight: FontWeight.w700),
              ),
            ),
            Text(
              '$used / $limit',
              style: TextStyle(
                fontWeight: FontWeight.w700,
                color: color,
                fontFamily: 'monospace',
              ),
            ),
          ],
        ),
        const SizedBox(height: 8),
        ClipRRect(
          borderRadius: BorderRadius.circular(4),
          child: LinearProgressIndicator(
            value: percent / 100,
            minHeight: 7,
            color: color,
            backgroundColor:
                Get.isDarkMode ? Colors.white10 : const Color(0xFFE2E8F0),
          ),
        ),
      ],
    );
  }

  String _subscriptionStatusLabel(dynamic status) {
    switch (status?.toString()) {
      case 'trial':
        return 'تجريبي';
      case 'active':
        return 'فعّال';
      case 'past_due':
        return 'متأخر الدفع';
      case 'cancelled':
        return 'ملغي';
      default:
        return 'غير معروف';
    }
  }

  void _resetVoiceState() {
    _recordTimer?.cancel();
    isVoiceRecording.value = false;
    isVoiceUploading.value = false;
    voiceRemainingSeconds.value = 15;
    voiceStatusText.value = 'اضغط "ابدأ التسجيل" ثم تحدّث';
  }

  void refreshData() {
    _loadDashboardData();
  }
}
