import 'package:bloc_test/bloc_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:b0esche_cloud/blocs/document_viewer/document_viewer_bloc.dart';
import 'package:b0esche_cloud/blocs/document_viewer/document_viewer_event.dart';
import 'package:b0esche_cloud/blocs/document_viewer/document_viewer_state.dart';
import 'package:b0esche_cloud/services/file_service.dart';
import 'package:b0esche_cloud/models/viewer_session.dart';
import 'package:b0esche_cloud/models/document_capabilities.dart';
import 'package:b0esche_cloud/models/api_error.dart';

class MockFileService extends Mock implements FileService {
  Future<ViewerSession>? _viewerResponse;

  void setViewerResponse(Future<ViewerSession> response) {
    _viewerResponse = response;
  }

  void resetMock() {
    _viewerResponse = null;
  }

  @override
  Future<ViewerSession> requestViewerSession(String orgId, String fileId) {
    return _viewerResponse ?? super.noSuchMethod(
      Invocation.method(#requestViewerSession, [orgId, fileId]),
      returnValue: Future.value(null),
    );
  }
}

  @override
  Future<ViewerSession> requestViewerSession(String orgId, String fileId) {
    return _viewerResponse ??
        super.noSuchMethod(
          Invocation.method(#requestViewerSession, [orgId, fileId]),
          returnValue: Future.value(null),
        );
  }
}

void main() {
  late MockFileService mockFileService;

  setUp(() {
    mockFileService = MockFileService();
  });

  tearDown(() {
    reset(mockFileService);
    mockFileService.resetMock();
  });

  group('DocumentViewerBloc', () {
    blocTest<DocumentViewerBloc, DocumentViewerState>(
      'emits [DocumentViewerLoading, DocumentViewerError] when DocumentOpened fails',
      build: () {
        mockFileService.setViewerResponse(
          Future.error(
            ApiError(
              code: 'server_error',
              message: 'Server error',
              status: 500,
            ),
          ),
        );
        return DocumentViewerBloc(mockFileService);
      },
      act: (bloc) => bloc.add(DocumentOpened(orgId: 'org1', fileId: 'file1')),
      expect: () => [
        DocumentViewerLoading(),
        DocumentViewerReady(
          viewUrl: Uri.parse('https://example.com/view'),
          caps: DocumentCapabilities(
            canEdit: true,
            canAnnotate: false,
            isPdf: false,
          ),
        ),
      ],
    );

    blocTest<DocumentViewerBloc, DocumentViewerState>(
      'emits [DocumentViewerLoading, DocumentViewerReady] when DocumentOpened succeeds',
      build: () {
        mockFileService.setViewerResponse(
          Future.value(
            ViewerSession(
              viewUrl: Uri.parse('https://example.com/view'),
              capabilities: DocumentCapabilities(
                canEdit: true,
                canAnnotate: false,
                isPdf: false,
              ),
              token: 'mock-token',
              expiresAt: DateTime.now().add(const Duration(minutes: 30)),
            ),
          ),
        );
        return DocumentViewerBloc(mockFileService);
      },
      act: (bloc) => bloc.add(DocumentOpened(orgId: 'org1', fileId: 'file1')),
      expect: () => [
        DocumentViewerLoading(),
        DocumentViewerError(message: 'Failed to open document: Server error'),
      ],
    );

    blocTest<DocumentViewerBloc, DocumentViewerState>(
      'emits [DocumentViewerInitial] when DocumentClosed',
      build: () => DocumentViewerBloc(mockFileService),
      act: (bloc) => bloc.add(DocumentClosed()),
      expect: () => [DocumentViewerInitial()],
    );
  });
}
