import fs from 'fs';
import path from 'path';
import { IStorage } from './storage';
import {
  User, Author, Work, Translation, Tag, Bookmark, Comment,
  Like, Collection, CollectionItem, TimelineEvent, BlogPost,
  ReadingProgress, InsertUser, InsertAuthor, InsertWork,
  InsertTranslation, InsertTag, InsertBookmark, InsertComment,
  InsertLike, InsertCollection, InsertCollectionItem, InsertTimelineEvent,
  InsertBlogPost, InsertReadingProgress, AnalysisResult, InsertAnalysisResult,
  Annotation, InsertAnnotation
} from '../shared/schema';

export class JsonStorage implements IStorage {
  private data: {
    users: Map<number, User>;
    authors: Map<number, Author>;
    works: Map<number, Work>;
    translations: Map<number, Translation>;
    tags: Map<number, Tag>;
    workTagsRelations: Map<number, Set<number>>;
    blogPostTagsRelations: Map<number, Set<number>>;
    bookmarks: Map<number, Bookmark>;
    comments: Map<number, Comment>;
    likes: Map<number, Like>;
    collections: Map<number, Collection>;
    collectionItems: Map<number, CollectionItem>;
    timelineEvents: Map<number, TimelineEvent>;
    blogPosts: Map<number, BlogPost>;
    readingProgresses: Map<string, ReadingProgress>;
    analysisResults: Map<number, AnalysisResult>;
    annotations: Map<number, Annotation>;
  };

  private counters: {
    userId: number;
    authorId: number;
    workId: number;
    translationId: number;
    tagId: number;
    bookmarkId: number;
    commentId: number;
    likeId: number;
    collectionId: number;
    collectionItemId: number;
    timelineEventId: number;
    blogPostId: number;
    readingProgressId: number;
    analysisResultId: number;
    annotationId: number;
  };

  private dataFilePath: string;

  constructor(dataFilePath: string = path.join(process.cwd(), 'data', 'sampleData.json')) {
    this.dataFilePath = dataFilePath;
    this.data = {
      users: new Map<number, User>(),
      authors: new Map<number, Author>(),
      works: new Map<number, Work>(),
      translations: new Map<number, Translation>(),
      tags: new Map<number, Tag>(),
      workTagsRelations: new Map<number, Set<number>>(),
      blogPostTagsRelations: new Map<number, Set<number>>(),
      bookmarks: new Map<number, Bookmark>(),
      comments: new Map<number, Comment>(),
      likes: new Map<number, Like>(),
      collections: new Map<number, Collection>(),
      collectionItems: new Map<number, CollectionItem>(),
      timelineEvents: new Map<number, TimelineEvent>(),
      blogPosts: new Map<number, BlogPost>(),
      readingProgresses: new Map<string, ReadingProgress>(),
      analysisResults: new Map<number, AnalysisResult>(),
      annotations: new Map<number, Annotation>(),
    };
    
    this.counters = {
      userId: 1,
      authorId: 1,
      workId: 1,
      translationId: 1,
      tagId: 1,
      bookmarkId: 1,
      commentId: 1,
      likeId: 1,
      collectionId: 1,
      collectionItemId: 1,
      timelineEventId: 1,
      blogPostId: 1,
      readingProgressId: 1,
      analysisResultId: 1,
      annotationId: 1,
    };

    this.loadDataFromFile();
  }

  private loadDataFromFile() {
    try {
      console.log(`Loading data from ${this.dataFilePath}`);
      if (!fs.existsSync(this.dataFilePath)) {
        console.error(`Data file not found: ${this.dataFilePath}`);
        return;
      }

      const jsonData = JSON.parse(fs.readFileSync(this.dataFilePath, 'utf8'));
      
      // Load users
      if (jsonData.users) {
        jsonData.users.forEach((user: User) => {
          this.data.users.set(user.id, {
            ...user,
            createdAt: new Date(user.createdAt)
          });
          this.counters.userId = Math.max(this.counters.userId, user.id + 1);
        });
      }
      
      // Load authors
      if (jsonData.authors) {
        jsonData.authors.forEach((author: Author) => {
          this.data.authors.set(author.id, {
            ...author,
            createdAt: new Date(author.createdAt)
          });
          this.counters.authorId = Math.max(this.counters.authorId, author.id + 1);
        });
      }
      
      // Load works
      if (jsonData.works) {
        jsonData.works.forEach((work: Work) => {
          this.data.works.set(work.id, {
            ...work,
            createdAt: new Date(work.createdAt)
          });
          this.counters.workId = Math.max(this.counters.workId, work.id + 1);
        });
      }
      
      // Load translations
      if (jsonData.translations) {
        jsonData.translations.forEach((translation: Translation) => {
          this.data.translations.set(translation.id, {
            ...translation,
            createdAt: new Date(translation.createdAt)
          });
          this.counters.translationId = Math.max(this.counters.translationId, translation.id + 1);
        });
      }
      
      // Load tags
      if (jsonData.tags) {
        jsonData.tags.forEach((tag: Tag) => {
          this.data.tags.set(tag.id, {
            ...tag,
            createdAt: new Date(tag.createdAt)
          });
          this.counters.tagId = Math.max(this.counters.tagId, tag.id + 1);
        });
      }
      
      // Load work-tag relations
      if (jsonData.workTagsRelations) {
        for (const [workId, tagIds] of Object.entries(jsonData.workTagsRelations)) {
          this.data.workTagsRelations.set(
            parseInt(workId), 
            new Set((tagIds as number[]).map(id => id))
          );
        }
      }
      
      // Load blog post-tag relations
      if (jsonData.blogPostTagsRelations) {
        for (const [postId, tagIds] of Object.entries(jsonData.blogPostTagsRelations)) {
          this.data.blogPostTagsRelations.set(
            parseInt(postId), 
            new Set((tagIds as number[]).map(id => id))
          );
        }
      }
      
      // Load bookmarks
      if (jsonData.bookmarks) {
        jsonData.bookmarks.forEach((bookmark: Bookmark) => {
          this.data.bookmarks.set(bookmark.id, {
            ...bookmark,
            createdAt: new Date(bookmark.createdAt)
          });
          this.counters.bookmarkId = Math.max(this.counters.bookmarkId, bookmark.id + 1);
        });
      }
      
      // Load comments
      if (jsonData.comments) {
        jsonData.comments.forEach((comment: Comment) => {
          this.data.comments.set(comment.id, {
            ...comment,
            createdAt: new Date(comment.createdAt)
          });
          this.counters.commentId = Math.max(this.counters.commentId, comment.id + 1);
        });
      }
      
      // Load likes
      if (jsonData.likes) {
        jsonData.likes.forEach((like: Like) => {
          this.data.likes.set(like.id, {
            ...like,
            createdAt: new Date(like.createdAt)
          });
          this.counters.likeId = Math.max(this.counters.likeId, like.id + 1);
        });
      }
      
      // Load collections
      if (jsonData.collections) {
        jsonData.collections.forEach((collection: Collection) => {
          this.data.collections.set(collection.id, {
            ...collection,
            createdAt: new Date(collection.createdAt)
          });
          this.counters.collectionId = Math.max(this.counters.collectionId, collection.id + 1);
        });
      }
      
      // Load collection items
      if (jsonData.collectionItems) {
        jsonData.collectionItems.forEach((item: CollectionItem) => {
          this.data.collectionItems.set(item.id, {
            ...item,
            createdAt: new Date(item.createdAt)
          });
          this.counters.collectionItemId = Math.max(this.counters.collectionItemId, item.id + 1);
        });
      }
      
      // Load timeline events
      if (jsonData.timelineEvents) {
        jsonData.timelineEvents.forEach((event: TimelineEvent) => {
          this.data.timelineEvents.set(event.id, {
            ...event,
            createdAt: new Date(event.createdAt)
          });
          this.counters.timelineEventId = Math.max(this.counters.timelineEventId, event.id + 1);
        });
      }
      
      // Load blog posts
      if (jsonData.blogPosts) {
        jsonData.blogPosts.forEach((post: BlogPost) => {
          this.data.blogPosts.set(post.id, {
            ...post,
            createdAt: new Date(post.createdAt),
            publishedAt: post.publishedAt ? new Date(post.publishedAt) : null
          });
          this.counters.blogPostId = Math.max(this.counters.blogPostId, post.id + 1);
        });
      }
      
      // Load reading progresses
      if (jsonData.readingProgresses) {
        jsonData.readingProgresses.forEach((progress: ReadingProgress) => {
          const key = `${progress.userId}-${progress.workId}-${progress.translationId || 0}`;
          this.data.readingProgresses.set(key, {
            ...progress,
            lastReadAt: new Date(progress.lastReadAt)
          });
          this.counters.readingProgressId = Math.max(this.counters.readingProgressId, progress.id + 1);
        });
      }
      
      // Load analysis results
      if (jsonData.analysisResults) {
        jsonData.analysisResults.forEach((result: AnalysisResult) => {
          this.data.analysisResults.set(result.id, {
            ...result,
            createdAt: new Date(result.createdAt)
          });
          this.counters.analysisResultId = Math.max(this.counters.analysisResultId, result.id + 1);
        });
      }
      
      // Load annotations
      if (jsonData.annotations) {
        jsonData.annotations.forEach((annotation: Annotation) => {
          this.data.annotations.set(annotation.id, {
            ...annotation,
            createdAt: new Date(annotation.createdAt)
          });
          this.counters.annotationId = Math.max(this.counters.annotationId, annotation.id + 1);
        });
      }

      console.log('Data loaded successfully');
      console.log(`Users: ${this.data.users.size}`);
      console.log(`Authors: ${this.data.authors.size}`);
      console.log(`Works: ${this.data.works.size}`);
      console.log(`Translations: ${this.data.translations.size}`);
      console.log(`Analysis Results: ${this.data.analysisResults.size}`);
      console.log(`Annotations: ${this.data.annotations.size}`);
    } catch (error) {
      console.error('Error loading data from file:', error);
    }
  }

  private saveDataToFile() {
    try {
      const jsonData = {
        users: Array.from(this.data.users.values()),
        authors: Array.from(this.data.authors.values()),
        works: Array.from(this.data.works.values()),
        translations: Array.from(this.data.translations.values()),
        tags: Array.from(this.data.tags.values()),
        workTagsRelations: Object.fromEntries(
          Array.from(this.data.workTagsRelations.entries()).map(
            ([workId, tagIds]) => [workId, Array.from(tagIds)]
          )
        ),
        blogPostTagsRelations: Object.fromEntries(
          Array.from(this.data.blogPostTagsRelations.entries()).map(
            ([postId, tagIds]) => [postId, Array.from(tagIds)]
          )
        ),
        bookmarks: Array.from(this.data.bookmarks.values()),
        comments: Array.from(this.data.comments.values()),
        likes: Array.from(this.data.likes.values()),
        collections: Array.from(this.data.collections.values()),
        collectionItems: Array.from(this.data.collectionItems.values()),
        timelineEvents: Array.from(this.data.timelineEvents.values()),
        blogPosts: Array.from(this.data.blogPosts.values()),
        readingProgresses: Array.from(this.data.readingProgresses.values()),
        analysisResults: Array.from(this.data.analysisResults.values()),
        annotations: Array.from(this.data.annotations.values())
      };

      fs.writeFileSync(this.dataFilePath, JSON.stringify(jsonData, null, 2), 'utf8');
      console.log(`Data saved to ${this.dataFilePath}`);
    } catch (error) {
      console.error('Error saving data to file:', error);
    }
  }

  // User methods
  async getUser(id: number): Promise<User | undefined> {
    return this.data.users.get(id);
  }

  async getUserByUsername(username: string): Promise<User | undefined> {
    return Array.from(this.data.users.values()).find(user => user.username === username);
  }

  async createUser(insertUser: InsertUser): Promise<User> {
    const id = this.counters.userId++;
    const now = new Date();
    const user: User = {
      ...insertUser,
      id,
      role: 'user',
      createdAt: now
    };
    this.data.users.set(id, user);
    this.saveDataToFile();
    return user;
  }
  
  // Author methods
  async getAuthors(limit: number = 100, offset: number = 0): Promise<Author[]> {
    return Array.from(this.data.authors.values())
      .sort((a, b) => a.name.localeCompare(b.name))
      .slice(offset, offset + limit);
  }
  
  async getAuthorById(id: number): Promise<Author | undefined> {
    return this.data.authors.get(id);
  }
  
  async getAuthorBySlug(slug: string): Promise<Author | undefined> {
    return Array.from(this.data.authors.values()).find(author => author.slug === slug);
  }
  
  async createAuthor(insertAuthor: InsertAuthor): Promise<Author> {
    const id = this.counters.authorId++;
    const now = new Date();
    const author: Author = {
      ...insertAuthor,
      id,
      createdAt: now
    };
    this.data.authors.set(id, author);
    this.saveDataToFile();
    return author;
  }
  
  // Work methods
  async getWorks(limit: number = 100, offset: number = 0): Promise<Work[]> {
    return Array.from(this.data.works.values())
      .sort((a, b) => a.title.localeCompare(b.title))
      .slice(offset, offset + limit);
  }
  
  async getWorkById(id: number): Promise<Work | undefined> {
    return this.data.works.get(id);
  }
  
  async getWorkBySlug(slug: string): Promise<Work | undefined> {
    return Array.from(this.data.works.values()).find(work => work.slug === slug);
  }
  
  async getWorksByAuthorId(authorId: number): Promise<Work[]> {
    return Array.from(this.data.works.values()).filter(work => work.authorId === authorId);
  }
  
  async getWorksByTags(tagIds: number[]): Promise<Work[]> {
    const tagSet = new Set(tagIds);
    const workIds = new Set<number>();
    
    this.data.workTagsRelations.forEach((tags, workId) => {
      for (const tagId of tags) {
        if (tagSet.has(tagId)) {
          workIds.add(workId);
          break;
        }
      }
    });
    
    return Array.from(workIds).map(id => this.data.works.get(id)!).filter(Boolean);
  }
  
  async createWork(insertWork: InsertWork): Promise<Work> {
    const id = this.counters.workId++;
    const now = new Date();
    const work: Work = {
      ...insertWork,
      id,
      createdAt: now
    };
    this.data.works.set(id, work);
    this.saveDataToFile();
    return work;
  }
  
  // Translation methods
  async getTranslations(workId: number): Promise<Translation[]> {
    return Array.from(this.data.translations.values()).filter(
      translation => translation.workId === workId
    );
  }
  
  async getTranslationById(id: number): Promise<Translation | undefined> {
    return this.data.translations.get(id);
  }
  
  async createTranslation(insertTranslation: InsertTranslation): Promise<Translation> {
    const id = this.counters.translationId++;
    const now = new Date();
    const translation: Translation = {
      ...insertTranslation,
      id,
      createdAt: now
    };
    this.data.translations.set(id, translation);
    this.saveDataToFile();
    return translation;
  }
  
  // Tag methods
  async getTags(): Promise<Tag[]> {
    return Array.from(this.data.tags.values());
  }
  
  async getTagsByType(type: string): Promise<Tag[]> {
    return Array.from(this.data.tags.values()).filter(tag => tag.type === type);
  }
  
  async createTag(insertTag: InsertTag): Promise<Tag> {
    const id = this.counters.tagId++;
    const now = new Date();
    const tag: Tag = {
      ...insertTag,
      id,
      createdAt: now
    };
    this.data.tags.set(id, tag);
    this.saveDataToFile();
    return tag;
  }
  
  async addTagToWork(workId: number, tagId: number): Promise<void> {
    if (!this.data.workTagsRelations.has(workId)) {
      this.data.workTagsRelations.set(workId, new Set());
    }
    this.data.workTagsRelations.get(workId)!.add(tagId);
    this.saveDataToFile();
  }
  
  async getWorkTags(workId: number): Promise<Tag[]> {
    const tagIds = this.data.workTagsRelations.get(workId) || new Set<number>();
    return Array.from(tagIds).map(id => this.data.tags.get(id)!).filter(Boolean);
  }
  
  async getBlogPostTags(postId: number): Promise<Tag[]> {
    const tagIds = this.data.blogPostTagsRelations.get(postId) || new Set<number>();
    return Array.from(tagIds).map(id => this.data.tags.get(id)!).filter(Boolean);
  }
  
  async addTagToBlogPost(postId: number, tagId: number): Promise<void> {
    console.log(`Adding tag ${tagId} to blog post ${postId}`);
    if (!this.data.blogPostTagsRelations.has(postId)) {
      console.log(`Creating new tag set for blog post ${postId}`);
      this.data.blogPostTagsRelations.set(postId, new Set());
    }
    this.data.blogPostTagsRelations.get(postId)!.add(tagId);
    console.log(`After adding tag, blog post ${postId} has tags:`, 
      Array.from(this.data.blogPostTagsRelations.get(postId) || new Set()));
    this.saveDataToFile();
  }
  
  // Bookmark methods
  async getBookmarksByUserId(userId: number): Promise<Bookmark[]> {
    return Array.from(this.data.bookmarks.values()).filter(bookmark => bookmark.userId === userId);
  }
  
  async getBookmarkByUserAndWork(userId: number, workId: number): Promise<Bookmark | undefined> {
    return Array.from(this.data.bookmarks.values()).find(
      bookmark => bookmark.userId === userId && bookmark.workId === workId
    );
  }
  
  async createBookmark(insertBookmark: InsertBookmark): Promise<Bookmark> {
    const id = this.counters.bookmarkId++;
    const now = new Date();
    const bookmark: Bookmark = {
      ...insertBookmark,
      id,
      createdAt: now
    };
    this.data.bookmarks.set(id, bookmark);
    this.saveDataToFile();
    return bookmark;
  }
  
  async deleteBookmark(id: number): Promise<void> {
    this.data.bookmarks.delete(id);
    this.saveDataToFile();
  }
  
  // Comment methods
  async getCommentsByWorkId(workId: number): Promise<Comment[]> {
    return Array.from(this.data.comments.values()).filter(
      comment => comment.workId === workId
    );
  }
  
  async getCommentsByTranslationId(translationId: number): Promise<Comment[]> {
    return Array.from(this.data.comments.values()).filter(
      comment => comment.translationId === translationId
    );
  }
  
  async getCommentsByUserId(userId: number): Promise<Comment[]> {
    return Array.from(this.data.comments.values()).filter(
      comment => comment.userId === userId
    );
  }
  
  async getCommentsByEntityId(entityType: string, entityId: number): Promise<Comment[]> {
    return Array.from(this.data.comments.values()).filter(
      comment => comment.entityType === entityType && comment.entityId === entityId
    );
  }
  
  async createComment(insertComment: InsertComment): Promise<Comment> {
    const id = this.counters.commentId++;
    const now = new Date();
    const comment: Comment = {
      ...insertComment,
      id,
      createdAt: now
    };
    this.data.comments.set(id, comment);
    this.saveDataToFile();
    return comment;
  }
  
  // Like methods
  async createLike(insertLike: InsertLike): Promise<Like> {
    const id = this.counters.likeId++;
    const now = new Date();
    const like: Like = {
      ...insertLike,
      id,
      createdAt: now
    };
    this.data.likes.set(id, like);
    this.saveDataToFile();
    return like;
  }
  
  async deleteLike(id: number): Promise<void> {
    this.data.likes.delete(id);
    this.saveDataToFile();
  }
  
  async getLikesByEntity(entityType: string, entityId: number): Promise<Like[]> {
    return Array.from(this.data.likes.values()).filter(
      like => like.entityType === entityType && like.entityId === entityId
    );
  }
  
  async getLikesByUserId(userId: number): Promise<Like[]> {
    return Array.from(this.data.likes.values()).filter(
      like => like.userId === userId
    );
  }
  
  // Collection methods
  async getCollections(limit: number = 100, offset: number = 0): Promise<Collection[]> {
    return Array.from(this.data.collections.values())
      .sort((a, b) => a.title.localeCompare(b.title))
      .slice(offset, offset + limit);
  }
  
  async getCollectionsByUserId(userId: number): Promise<Collection[]> {
    return Array.from(this.data.collections.values()).filter(
      collection => collection.userId === userId
    );
  }
  
  async getCollectionById(id: number): Promise<Collection | undefined> {
    return this.data.collections.get(id);
  }
  
  async getCollectionBySlug(slug: string): Promise<Collection | undefined> {
    return Array.from(this.data.collections.values()).find(
      collection => collection.slug === slug
    );
  }
  
  async createCollection(insertCollection: InsertCollection): Promise<Collection> {
    const id = this.counters.collectionId++;
    const now = new Date();
    const collection: Collection = {
      ...insertCollection,
      id,
      createdAt: now
    };
    this.data.collections.set(id, collection);
    this.saveDataToFile();
    return collection;
  }
  
  async addWorkToCollection(insertCollectionItem: InsertCollectionItem): Promise<CollectionItem> {
    const id = this.counters.collectionItemId++;
    const now = new Date();
    const collectionItem: CollectionItem = {
      ...insertCollectionItem,
      id,
      createdAt: now
    };
    this.data.collectionItems.set(id, collectionItem);
    this.saveDataToFile();
    return collectionItem;
  }
  
  async getCollectionItems(collectionId: number): Promise<CollectionItem[]> {
    return Array.from(this.data.collectionItems.values()).filter(
      item => item.collectionId === collectionId
    );
  }
  
  // Timeline events
  async getTimelineEventsByAuthorId(authorId: number): Promise<TimelineEvent[]> {
    return Array.from(this.data.timelineEvents.values())
      .filter(event => event.authorId === authorId)
      .sort((a, b) => a.year - b.year);
  }
  
  async createTimelineEvent(insertEvent: InsertTimelineEvent): Promise<TimelineEvent> {
    const id = this.counters.timelineEventId++;
    const now = new Date();
    const event: TimelineEvent = {
      ...insertEvent,
      id,
      createdAt: now
    };
    this.data.timelineEvents.set(id, event);
    this.saveDataToFile();
    return event;
  }
  
  // Blog posts
  async getBlogPosts(limit: number = 100, offset: number = 0): Promise<BlogPost[]> {
    return Array.from(this.data.blogPosts.values())
      .sort((a, b) => {
        const dateA = a.publishedAt || a.createdAt;
        const dateB = b.publishedAt || b.createdAt;
        return dateB.getTime() - dateA.getTime(); // newest first
      })
      .slice(offset, offset + limit);
  }
  
  async getBlogPostById(id: number): Promise<BlogPost | undefined> {
    return this.data.blogPosts.get(id);
  }
  
  async getBlogPostBySlug(slug: string): Promise<BlogPost | undefined> {
    return Array.from(this.data.blogPosts.values()).find(
      post => post.slug === slug
    );
  }
  
  async createBlogPost(insertPost: InsertBlogPost): Promise<BlogPost> {
    const id = this.counters.blogPostId++;
    const now = new Date();
    const post: BlogPost = {
      ...insertPost,
      id,
      createdAt: now
    };
    this.data.blogPosts.set(id, post);
    console.log('Created blog post with ID:', id);
    this.saveDataToFile();
    return post;
  }
  
  // Reading progress
  async getReadingProgress(userId: number, workId: number, translationId?: number): Promise<ReadingProgress | undefined> {
    const key = `${userId}-${workId}-${translationId || 0}`;
    return this.data.readingProgresses.get(key);
  }
  
  async updateReadingProgress(insertProgress: InsertReadingProgress): Promise<ReadingProgress> {
    const key = `${insertProgress.userId}-${insertProgress.workId}-${insertProgress.translationId || 0}`;
    
    if (this.data.readingProgresses.has(key)) {
      const existing = this.data.readingProgresses.get(key)!;
      const updated: ReadingProgress = {
        ...existing,
        progress: insertProgress.progress ?? existing.progress,
        lastReadAt: new Date()
      };
      this.data.readingProgresses.set(key, updated);
      this.saveDataToFile();
      return updated;
    } else {
      const id = this.counters.readingProgressId++;
      const progress: ReadingProgress = {
        id,
        workId: insertProgress.workId,
        progress: insertProgress.progress ?? 0,
        userId: insertProgress.userId,
        translationId: insertProgress.translationId ?? null,
        lastReadAt: new Date()
      };
      this.data.readingProgresses.set(key, progress);
      this.saveDataToFile();
      return progress;
    }
  }
  
  // Search and filter methods
  async searchWorks(query: string, limit: number = 10): Promise<Work[]> {
    const searchTerms = query.toLowerCase().split(/\s+/);
    const works = Array.from(this.data.works.values());
    
    const scoredWorks = works.map(work => {
      let score = 0;
      const title = work.title.toLowerCase();
      const description = work.description?.toLowerCase() || '';
      
      searchTerms.forEach(term => {
        if (title.includes(term)) score += 10;
        if (description.includes(term)) score += 5;
      });
      
      return { work, score };
    });
    
    return scoredWorks
      .filter(item => item.score > 0)
      .sort((a, b) => b.score - a.score)
      .slice(0, limit)
      .map(item => item.work);
  }
  
  async searchAuthors(query: string, limit: number = 10): Promise<Author[]> {
    const searchTerms = query.toLowerCase().split(/\s+/);
    const authors = Array.from(this.data.authors.values());
    
    const scoredAuthors = authors.map(author => {
      let score = 0;
      const name = author.name.toLowerCase();
      const biography = author.biography?.toLowerCase() || '';
      const country = author.country?.toLowerCase() || '';
      
      searchTerms.forEach(term => {
        if (name.includes(term)) score += 10;
        if (country.includes(term)) score += 7;
        if (biography.includes(term)) score += 3;
      });
      
      return { author, score };
    });
    
    return scoredAuthors
      .filter(item => item.score > 0)
      .sort((a, b) => b.score - a.score)
      .slice(0, limit)
      .map(item => item.author);
  }
  
  async filterWorks(params: { 
    language?: string, 
    type?: string, 
    yearStart?: number, 
    yearEnd?: number, 
    tags?: number[] 
  }): Promise<Work[]> {
    let filteredWorks = Array.from(this.data.works.values());
    
    if (params.language) {
      filteredWorks = filteredWorks.filter(work => work.language === params.language);
    }
    
    if (params.type) {
      filteredWorks = filteredWorks.filter(work => work.type === params.type);
    }
    
    if (params.yearStart) {
      filteredWorks = filteredWorks.filter(work => work.year! >= params.yearStart!);
    }
    
    if (params.yearEnd) {
      filteredWorks = filteredWorks.filter(work => work.year! <= params.yearEnd!);
    }
    
    if (params.tags && params.tags.length > 0) {
      const taggedWorkIds = new Set<number>();
      this.data.workTagsRelations.forEach((tagIds, workId) => {
        for (const tagId of params.tags!) {
          if (tagIds.has(tagId)) {
            taggedWorkIds.add(workId);
            break;
          }
        }
      });
      
      filteredWorks = filteredWorks.filter(work => taggedWorkIds.has(work.id));
    }
    
    return filteredWorks;
  }

  // Analysis methods
  async getAnalysisResultsByWorkId(workId: number): Promise<AnalysisResult[]> {
    return Array.from(this.data.analysisResults.values()).filter(
      result => result.workId === workId
    );
  }
  
  async getAnalysisResultById(id: number): Promise<AnalysisResult | undefined> {
    return this.data.analysisResults.get(id);
  }
  
  async getAnalysisResultByWorkAndType(workId: number, type: string): Promise<AnalysisResult | undefined> {
    return Array.from(this.data.analysisResults.values()).find(
      result => result.workId === workId && result.type === type
    );
  }
  
  async createAnalysisResult(insertResult: InsertAnalysisResult): Promise<AnalysisResult> {
    const id = this.counters.analysisResultId++;
    const now = new Date();
    const result: AnalysisResult = {
      ...insertResult,
      id,
      createdAt: now
    };
    this.data.analysisResults.set(id, result);
    this.saveDataToFile();
    return result;
  }
  
  // Annotation methods
  async getAnnotationsByWorkId(workId: number): Promise<Annotation[]> {
    return Array.from(this.data.annotations.values()).filter(
      annotation => annotation.workId === workId
    );
  }
  
  async getAnnotationsByTranslationId(translationId: number): Promise<Annotation[]> {
    return Array.from(this.data.annotations.values()).filter(
      annotation => annotation.translationId === translationId
    );
  }
  
  async getAnnotationsByLine(workId: number, lineNumber: number, translationId?: number): Promise<Annotation[]> {
    return Array.from(this.data.annotations.values()).filter(
      annotation => annotation.workId === workId && 
                   annotation.lineNumber === lineNumber &&
                   (translationId === undefined || annotation.translationId === translationId)
    );
  }
  
  async getAnnotationById(id: number): Promise<Annotation | undefined> {
    return this.data.annotations.get(id);
  }
  
  async createAnnotation(insertAnnotation: InsertAnnotation): Promise<Annotation> {
    const id = this.counters.annotationId++;
    const now = new Date();
    const annotation: Annotation = {
      ...insertAnnotation,
      id,
      createdAt: now
    };
    this.data.annotations.set(id, annotation);
    this.saveDataToFile();
    return annotation;
  }
}