import 'dart:async';
import 'package:bloc/bloc.dart';
import 'document_viewer_event.dart';
import 'document_viewer_state.dart';
import '../../services/file_service.dart';
import '../../models/api_error.dart';

class DocumentViewerBloc
    extends Bloc<DocumentViewerEvent, DocumentViewerState> {
  final FileService _fileService;
  Timer? _expiryTimer;

  DocumentViewerBloc(this._fileService) : super(DocumentViewerInitial()) {
    on<DocumentOpened>(_onDocumentOpened);
    on<DocumentReloaded>(_onDocumentReloaded);
    on<DocumentClosed>(_onDocumentClosed);
  }

  void _onDocumentOpened(
    DocumentOpened event,
    Emitter<DocumentViewerState> emit,
  ) async {
    emit(DocumentViewerLoading());
    try {
      final session = await _fileService.requestViewerSession(
        event.orgId,
        event.fileId,
      );
      if (session.expiresAt.isBefore(DateTime.now())) {
        emit(DocumentViewerSessionExpired());
        return;
      }
      emit(
        DocumentViewerReady(
          viewUrl: session.viewUrl,
          caps: session.capabilities,
          token: session.token,
          fileInfo: session.fileInfo,
        ),
      );
      _expiryTimer = Timer(
        session.expiresAt.difference(DateTime.now()),
        () => emit(DocumentViewerSessionExpired()),
      );
    } catch (e) {
      if (e is ApiError) {
        switch (e.code) {
          case 'UNAUTHENTICATED':
            // Already handled by ApiClient
            break;
          case 'PERMISSION_DENIED':
            emit(
              DocumentViewerError(
                message: 'You don\'t have access to this document.',
              ),
            );
            break;
          case 'NOT_FOUND':
            emit(
              DocumentViewerError(
                message: 'This document no longer exists or was moved.',
              ),
            );
            break;
          default:
            emit(
              DocumentViewerError(
                message: 'Failed to open document: ${e.message}',
              ),
            );
        }
      } else {
        emit(DocumentViewerError(message: 'Unexpected error: ${e.toString()}'));
      }
    }
  }

  void _onDocumentReloaded(
    DocumentReloaded event,
    Emitter<DocumentViewerState> emit,
  ) async {
    final currentState = state;
    if (currentState is DocumentViewerReady) {
      _expiryTimer?.cancel();
      emit(DocumentViewerLoading());
      try {
        // Re-fetch session
        // For simplicity, re-emit (in real, re-call the service)
        emit(currentState);
        // Restart timer if needed
      } catch (e) {
        emit(DocumentViewerError(message: 'Unexpected error: ${e.toString()}'));
      }
    }
  }

  void _onDocumentClosed(
    DocumentClosed event,
    Emitter<DocumentViewerState> emit,
  ) {
    _expiryTimer?.cancel();
    emit(DocumentViewerInitial());
  }
}
