import 'dart:io';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import '../utils/logger.dart';

/// Service for managing educational content from teachers
class ContentService {
  static final FirebaseAuth _auth = FirebaseAuth.instance;
  static final FirebaseFirestore _firestore = FirebaseFirestore.instance;
  static final FirebaseStorage _storage = FirebaseStorage.instanceFor(
    bucket: 'teachit-app.firebasestorage.app',
  );

  /// Upload and process content file
  static Future<String> uploadContent({
    required File file,
    required String title,
    required String subject,
    required String concept,
    required double difficulty,
    required int grade,
    Map<String, dynamic>? additionalMetadata,
  }) async {
    try {
      final user = _auth.currentUser;
      if (user == null) throw Exception('User not authenticated');

      Logger.info('Starting content upload: $title');

      // 1. Upload file to Firebase Storage
      final fileName =
          '${DateTime.now().millisecondsSinceEpoch}_${file.path.split('/').last}';
      final storageRef = _storage.ref().child('content/${user.uid}/$fileName');

      final uploadTask = await storageRef.putFile(file);
      final downloadUrl = await uploadTask.ref.getDownloadURL();

      Logger.info('File uploaded to storage: $downloadUrl');

      // 2. Create content document in Firestore
      final contentDoc = {
        'title': title,
        'subject': subject,
        'concept': concept,
        'difficulty': difficulty,
        'grade': grade,
        'teacherId': user.uid,
        'teacherEmail': user.email,
        'fileName': fileName,
        'downloadUrl': downloadUrl,
        'fileSize': await file.length(),
        'uploadedAt': FieldValue.serverTimestamp(),
        'status': 'processing',
        'metadata': additionalMetadata ?? {},
        'chunkCount': 0,
        'totalChunks': 0,
      };

      final docRef = await _firestore.collection('content').add(contentDoc);
      final contentId = docRef.id;

      Logger.info('Content document created: $contentId');

      // 3. Trigger content processing (this would be handled by a Cloud Function)
      await _triggerContentProcessing(contentId, file.path, downloadUrl);

      return contentId;
    } catch (e) {
      Logger.error('Error uploading content: $e');
      throw Exception('Failed to upload content: $e');
    }
  }

  /// Get content list for a teacher
  static Future<List<Map<String, dynamic>>> getTeacherContent({
    int limit = 20,
    DocumentSnapshot? lastDocument,
  }) async {
    try {
      final user = _auth.currentUser;
      if (user == null) throw Exception('User not authenticated');

      Query query = _firestore
          .collection('content')
          .where('teacherId', isEqualTo: user.uid)
          .orderBy('uploadedAt', descending: true)
          .limit(limit);

      if (lastDocument != null) {
        query = query.startAfterDocument(lastDocument);
      }

      final querySnapshot = await query.get();

      return querySnapshot.docs
          .map((doc) => {'id': doc.id, ...doc.data() as Map<String, dynamic>})
          .toList();
    } catch (e) {
      Logger.error('Error getting teacher content: $e');
      throw Exception('Failed to get content: $e');
    }
  }

  /// Get content details
  static Future<Map<String, dynamic>?> getContentDetails(
    String contentId,
  ) async {
    try {
      final doc = await _firestore.collection('content').doc(contentId).get();

      if (!doc.exists) return null;

      return {'id': doc.id, ...doc.data() as Map<String, dynamic>};
    } catch (e) {
      Logger.error('Error getting content details: $e');
      throw Exception('Failed to get content details: $e');
    }
  }

  /// Get available content for students (filtered by school/grade)
  static Future<List<Map<String, dynamic>>> getAvailableContent({
    String? subject,
    String? concept,
    double? minDifficulty,
    double? maxDifficulty,
    int? grade,
    int limit = 50,
  }) async {
    try {
      final user = _auth.currentUser;
      if (user == null) throw Exception('User not authenticated');

      // Get user's grade from their profile
      final userDoc = await _firestore.collection('users').doc(user.uid).get();
      final userData = userDoc.data();
      final userGrade = userData?['profile']?['gradeLevel'] ?? grade;

      Query query = _firestore
          .collection('content')
          .where('status', isEqualTo: 'processed')
          .where('grade', isEqualTo: userGrade)
          .orderBy('uploadedAt', descending: true)
          .limit(limit);

      // Apply filters
      if (subject != null) {
        query = query.where('subject', isEqualTo: subject);
      }
      if (concept != null) {
        query = query.where('concept', isEqualTo: concept);
      }
      if (minDifficulty != null) {
        query = query.where(
          'difficulty',
          isGreaterThanOrEqualTo: minDifficulty,
        );
      }
      if (maxDifficulty != null) {
        query = query.where('difficulty', isLessThanOrEqualTo: maxDifficulty);
      }

      final querySnapshot = await query.get();

      return querySnapshot.docs
          .map((doc) => {'id': doc.id, ...doc.data() as Map<String, dynamic>})
          .toList();
    } catch (e) {
      Logger.error('Error getting available content: $e');
      throw Exception('Failed to get available content: $e');
    }
  }

  /// Delete content
  static Future<void> deleteContent(String contentId) async {
    try {
      final user = _auth.currentUser;
      if (user == null) throw Exception('User not authenticated');

      // Get content details
      final content = await getContentDetails(contentId);
      if (content == null) throw Exception('Content not found');

      // Check ownership
      if (content['teacherId'] != user.uid) {
        throw Exception('Permission denied');
      }

      // Delete from Firestore
      await _firestore.collection('content').doc(contentId).delete();

      // Delete from Storage
      if (content['fileName'] != null) {
        final storageRef = _storage.ref().child(
          'content/${user.uid}/${content['fileName']}',
        );
        await storageRef.delete();
      }

      // Delete associated chunks
      final chunksSnapshot = await _firestore
          .collection('contentChunks')
          .where('contentId', isEqualTo: contentId)
          .get();

      final batch = _firestore.batch();
      for (final doc in chunksSnapshot.docs) {
        batch.delete(doc.reference);
      }
      await batch.commit();

      Logger.info('Content deleted successfully: $contentId');
    } catch (e) {
      Logger.error('Error deleting content: $e');
      throw Exception('Failed to delete content: $e');
    }
  }

  /// Update content metadata
  static Future<void> updateContentMetadata(
    String contentId,
    Map<String, dynamic> metadata,
  ) async {
    try {
      final user = _auth.currentUser;
      if (user == null) throw Exception('User not authenticated');

      // Check ownership
      final content = await getContentDetails(contentId);
      if (content == null) throw Exception('Content not found');
      if (content['teacherId'] != user.uid) {
        throw Exception('Permission denied');
      }

      await _firestore.collection('content').doc(contentId).update({
        'metadata': metadata,
        'updatedAt': FieldValue.serverTimestamp(),
      });

      Logger.info('Content metadata updated: $contentId');
    } catch (e) {
      Logger.error('Error updating content metadata: $e');
      throw Exception('Failed to update content metadata: $e');
    }
  }

  /// Get content statistics for a teacher
  static Future<Map<String, dynamic>> getTeacherStats() async {
    try {
      final user = _auth.currentUser;
      if (user == null) throw Exception('User not authenticated');

      final contentSnapshot = await _firestore
          .collection('content')
          .where('teacherId', isEqualTo: user.uid)
          .get();

      final totalContent = contentSnapshot.docs.length;
      final processedContent = contentSnapshot.docs
          .where((doc) => doc['status'] == 'processed')
          .length;

      final totalChunks = contentSnapshot.docs.fold<int>(
        0,
        (sum, doc) => sum + (doc['chunkCount'] as int? ?? 0),
      );

      final subjects = <String, int>{};
      for (final doc in contentSnapshot.docs) {
        final subject = doc['subject'] as String? ?? 'Unknown';
        subjects[subject] = (subjects[subject] ?? 0) + 1;
      }

      return {
        'totalContent': totalContent,
        'processedContent': processedContent,
        'totalChunks': totalChunks,
        'subjects': subjects,
        'processingContent': totalContent - processedContent,
      };
    } catch (e) {
      Logger.error('Error getting teacher stats: $e');
      throw Exception('Failed to get teacher stats: $e');
    }
  }

  /// Trigger content processing (would be handled by Cloud Function)
  static Future<void> _triggerContentProcessing(
    String contentId,
    String filePath,
    String downloadUrl,
  ) async {
    try {
      // This would typically trigger a Cloud Function
      // For now, we'll update the status to indicate processing should start
      await _firestore.collection('content').doc(contentId).update({
        'status': 'processing_started',
        'processingStartedAt': FieldValue.serverTimestamp(),
      });

      Logger.info('Content processing triggered: $contentId');
    } catch (e) {
      Logger.error('Error triggering content processing: $e');
      throw Exception('Failed to trigger content processing: $e');
    }
  }

  /// Search content by text
  static Future<List<Map<String, dynamic>>> searchContent({
    required String searchQuery,
    String? subject,
    int? grade,
    int limit = 20,
  }) async {
    try {
      final user = _auth.currentUser;
      if (user == null) throw Exception('User not authenticated');

      // Get user's grade if not specified
      final userDoc = await _firestore.collection('users').doc(user.uid).get();
      final userData = userDoc.data();
      final userGrade = grade ?? userData?['profile']?['gradeLevel'];

      // For now, we'll do a simple text search on title and concept
      // In a full implementation, this would use the vector search
      Query query = _firestore
          .collection('content')
          .where('status', isEqualTo: 'processed')
          .where('grade', isEqualTo: userGrade)
          .orderBy('uploadedAt', descending: true)
          .limit(limit);

      if (subject != null) {
        query = query.where('subject', isEqualTo: subject);
      }

      final querySnapshot = await query.get();

      final searchQueryLower = searchQuery.toLowerCase();
      final results = querySnapshot.docs
          .where((doc) {
            final data = doc.data() as Map<String, dynamic>;
            final title = (data['title'] as String? ?? '').toLowerCase();
            final concept = (data['concept'] as String? ?? '').toLowerCase();

            return title.contains(searchQueryLower) ||
                concept.contains(searchQueryLower);
          })
          .map((doc) => {'id': doc.id, ...doc.data() as Map<String, dynamic>})
          .toList();

      return results;
    } catch (e) {
      Logger.error('Error searching content: $e');
      throw Exception('Failed to search content: $e');
    }
  }
}
