import '../models/file_item.dart';
import '../models/viewer_session.dart';
import '../models/editor_session.dart';
import '../models/annotation.dart';
import '../models/document_capabilities.dart';
import '../models/api_error.dart';
import '../repositories/file_repository.dart';
import 'package:path/path.dart' as p;

class MockFileRepository implements FileRepository {
  final Map<String, List<FileItem>> _orgFiles = {};

  List<FileItem> _getFilesForOrg(String orgId) {
    if (!_orgFiles.containsKey(orgId)) {
      // Initialize with different files per org
      if (orgId == 'org1') {
        _orgFiles[orgId] = [
          FileItem(
            name: 'Personal Documents',
            path: '/Personal Documents',
            type: FileType.folder,
            lastModified: DateTime.now(),
          ),
          FileItem(
            name: 'Photos',
            path: '/Photos',
            type: FileType.folder,
            lastModified: DateTime.now(),
          ),
          FileItem(
            name: 'resume.pdf',
            path: '/resume.pdf',
            type: FileType.file,
            size: 1024,
            lastModified: DateTime.now(),
          ),
          FileItem(
            name: 'notes.txt',
            path: '/notes.txt',
            type: FileType.file,
            size: 256,
            lastModified: DateTime.now(),
          ),
        ];
      } else if (orgId == 'org2') {
        _orgFiles[orgId] = [
          FileItem(
            name: 'Company Reports',
            path: '/Company Reports',
            type: FileType.folder,
            lastModified: DateTime.now(),
          ),
          FileItem(
            name: 'annual_report.pdf',
            path: '/annual_report.pdf',
            type: FileType.file,
            size: 2048,
            lastModified: DateTime.now(),
          ),
          FileItem(
            name: 'presentation.pptx',
            path: '/presentation.pptx',
            type: FileType.file,
            size: 4096,
            lastModified: DateTime.now(),
          ),
        ];
      } else if (orgId == 'org3') {
        _orgFiles[orgId] = [
          FileItem(
            name: 'Project Code',
            path: '/Project Code',
            type: FileType.folder,
            lastModified: DateTime.now(),
          ),
          FileItem(
            name: 'side_project.dart',
            path: '/side_project.dart',
            type: FileType.file,
            size: 512,
            lastModified: DateTime.now(),
          ),
        ];
      } else {
        // Default for new orgs
        _orgFiles[orgId] = [];
      }
    }
    return _orgFiles[orgId]!;
  }

  @override
  Future<List<FileItem>> getFiles(String orgId, String path) async {
    await Future.delayed(const Duration(seconds: 1));
    final files = _getFilesForOrg(orgId);
    if (path == '/') {
      return files.where((f) => !f.path.substring(1).contains('/')).toList();
    } else {
      return files
          .where((f) => f.path.startsWith('$path/') && f.path != path)
          .toList();
    }
  }

  @override
  Future<FileItem?> getFile(String orgId, String path) async {
    final files = _getFilesForOrg(orgId);
    final index = files.indexWhere((f) => f.path == path);
    return index != -1 ? files[index] : null;
  }

  @override
  Future<EditorSession> requestEditorSession(
    String orgId,
    String fileId,
  ) async {
    await Future.delayed(const Duration(seconds: 1));
    // Mock: determine editability
    final isEditable =
        fileId.endsWith('.docx') ||
        fileId.endsWith('.xlsx') ||
        fileId.endsWith('.pptx');
    final editUrl = Uri.parse(
      'https://office.b0esche.cloud/editor/$orgId/$fileId?editable=$isEditable',
    );
    final expiresAt = DateTime.now().add(const Duration(minutes: 30));
    return EditorSession(
      editUrl: editUrl,
      readOnly: !isEditable,
      expiresAt: expiresAt,
    );
  }

  @override
  Future<void> deleteFile(String orgId, String path) async {
    final files = _getFilesForOrg(orgId);
    files.removeWhere((f) => f.path == path);
  }

  @override
  Future<void> createFolder(
    String orgId,
    String parentPath,
    String folderName,
  ) async {
    await Future.delayed(const Duration(seconds: 1));
    final normalizedName = folderName.startsWith('/')
        ? folderName.substring(1)
        : folderName;
    final newPath = parentPath == '/'
        ? '/$normalizedName'
        : '$parentPath/$normalizedName';
    final files = _getFilesForOrg(orgId);
    files.add(
      FileItem(
        name: normalizedName,
        path: newPath,
        type: FileType.folder,
        lastModified: DateTime.now(),
      ),
    );
  }

  @override
  Future<void> moveFile(
    String orgId,
    String sourcePath,
    String targetPath,
  ) async {
    await Future.delayed(const Duration(seconds: 1));
    final files = _getFilesForOrg(orgId);
    final fileIndex = files.indexWhere((f) => f.path == sourcePath);
    if (fileIndex != -1) {
      final file = files[fileIndex];
      final newName = file.path.split('/').last;
      final newPath = targetPath == '/' ? '/$newName' : '$targetPath/$newName';
      files[fileIndex] = FileItem(
        name: file.name,
        path: newPath,
        type: file.type,
        size: file.size,
        lastModified: DateTime.now(),
      );
    }
  }

  @override
  Future<void> renameFile(String orgId, String path, String newName) async {
    await Future.delayed(const Duration(seconds: 1));
    final files = _getFilesForOrg(orgId);
    final fileIndex = files.indexWhere((f) => f.path == path);
    if (fileIndex != -1) {
      final file = files[fileIndex];
      final parentPath = p.dirname(path);
      final newPath = parentPath == '.' ? '/$newName' : '$parentPath/$newName';
      files[fileIndex] = FileItem(
        name: newName,
        path: newPath,
        type: file.type,
        size: file.size,
        lastModified: DateTime.now(),
      );
    }
  }

  @override
  Future<List<FileItem>> searchFiles(String orgId, String query) async {
    await Future.delayed(const Duration(seconds: 1));
    final files = _getFilesForOrg(orgId);
    return files
        .where((f) => f.name.toLowerCase().contains(query.toLowerCase()))
        .toList();
  }

  @override
  Future<void> uploadFile(String orgId, FileItem file) async {
    await Future.delayed(const Duration(seconds: 1));
    final files = _getFilesForOrg(orgId);
    files.add(file);
  }

  @override
  Future<ViewerSession> requestViewerSession(
    String orgId,
    String fileId,
  ) async {
    await Future.delayed(const Duration(seconds: 1));
    if (fileId.contains('forbidden')) {
      throw ApiError(
        code: 'permission_denied',
        message: 'Access denied',
        status: 403,
      );
    }
    if (fileId.contains('notfound')) {
      throw ApiError(code: 'not_found', message: 'File not found', status: 404);
    }
    // Mock: assume fileId is path, determine if PDF
    final isPdf = fileId.endsWith('.pdf');
    final caps = DocumentCapabilities(
      canEdit: !isPdf && (fileId.endsWith('.docx') || fileId.endsWith('.xlsx')),
      canAnnotate: isPdf,
      isPdf: isPdf,
    );
    // Mock URL
    final viewUrl = Uri.parse(
      'https://office.b0esche.cloud/viewer/$orgId/$fileId',
    );
    final token = 'mock-viewer-token';
    final expiresAt = DateTime.now().add(const Duration(minutes: 30));
    return ViewerSession(
      viewUrl: viewUrl,
      capabilities: caps,
      token: token,
      expiresAt: expiresAt,
    );
  }

  @override
  Future<void> saveAnnotations(
    String orgId,
    String fileId,
    List<Annotation> annotations,
  ) async {
    await Future.delayed(const Duration(seconds: 2));
    // Mock: just delay, assume success
  }
}
