import { AvatarGenerationRequest } from '@core/media/domain/entities/AvatarGenerationRequest';
import type { AvatarGenerationRepository } from '@core/media/domain/repositories/AvatarGenerationRepository';
import type { Logger } from '@core/shared/domain/Logger';

export class InMemoryAvatarGenerationRepository implements AvatarGenerationRepository {
  private requests: Map<string, AvatarGenerationRequest> = new Map(); // Key: requestId
  private userRequests: Map<string, AvatarGenerationRequest[]> = new Map(); // Key: userId

  constructor(private readonly logger: Logger, initialRequests: AvatarGenerationRequest[] = []) {
    this.logger.info('InMemoryAvatarGenerationRepository initialized.');
    for (const req of initialRequests) {
      this.requests.set(req.id, req);
      if (!this.userRequests.has(req.userId)) {
        this.userRequests.set(req.userId, []);
      }
      this.userRequests.get(req.userId)?.push(req);
      this.logger.debug(`Seeded avatar generation request: ${req.id} for user ${req.userId}.`);
    }
  }

  async save(request: AvatarGenerationRequest): Promise<void> {
    this.logger.debug(`[InMemoryAvatarGenerationRepository] Saving avatar generation request: ${request.id} for user ${request.userId}.`);
    this.requests.set(request.id, request);
    if (!this.userRequests.has(request.userId)) {
      this.userRequests.set(request.userId, []);
    }
    const existingRequests = this.userRequests.get(request.userId)!;
    // Remove old version if exists and add new version (update-like behavior)
    const index = existingRequests.findIndex(r => r.id === request.id);
    if (index > -1) {
      existingRequests[index] = request;
    } else {
      existingRequests.push(request);
    }
    this.logger.info(`Avatar generation request ${request.id} for user ${request.userId} saved successfully.`);
    return Promise.resolve();
  }

  async findById(id: string): Promise<AvatarGenerationRequest | null> {
    this.logger.debug(`[InMemoryAvatarGenerationRepository] Finding request by ID: ${id}`);
    const request = this.requests.get(id) ?? null;
    if (request) {
      this.logger.info(`Found request by ID: ${id}.`);
    } else {
      this.logger.warn(`Request with ID ${id} not found.`);
    }
    return Promise.resolve(request);
  }

  async findByUserId(userId: string): Promise<AvatarGenerationRequest[]> {
    this.logger.debug(`[InMemoryAvatarGenerationRepository] Finding requests for user: ${userId}`);
    const requests = this.userRequests.get(userId) ?? [];
    this.logger.info(`Found ${requests.length} requests for user ${userId}.`);
    return Promise.resolve(requests);
  }

  async findLatestByUserId(userId: string): Promise<AvatarGenerationRequest | null> {
    this.logger.debug(`[InMemoryAvatarGenerationRepository] Finding latest request for user: ${userId}`);
    const requests = (this.userRequests.get(userId) ?? [])
      .sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime()); // Sort by most recent
    const latest = requests.length > 0 ? requests[0]! : null; // Use non-null assertion as `requests.length > 0` is checked
    if (latest) {
      this.logger.info(`Found latest request for user ${userId}: ${latest.id}.`);
    } else {
      this.logger.warn(`No latest request found for user: ${userId}.`);
    }
    return Promise.resolve(latest);
  }

  async delete(id: string): Promise<void> {
    this.logger.debug(`[InMemoryAvatarGenerationRepository] Deleting request with ID: ${id}.`);
    const requestToDelete = this.requests.get(id);
    if (requestToDelete) {
      this.requests.delete(id);
      const userRequests = this.userRequests.get(requestToDelete.userId);
      if (userRequests) {
        this.userRequests.set(requestToDelete.userId, userRequests.filter(req => req.id !== id));
      }
      this.logger.info(`Request ${id} deleted successfully.`);
    } else {
      this.logger.warn(`Request with ID ${id} not found for deletion.`);
    }
    return Promise.resolve();
  }
}
