import "reflect-metadata";
import { injectable } from "inversify";
import {
  NoopTracer,
  NoopLogger,
  type ITracer,
  type ILogger,
} from "@repo/core-shared/instrumentation";

import type { IMediaRepository } from "../../application/repositories/media.repository.interface";
import type { Media } from "../../entities/models/media";

@injectable()
export class MockMediaRepository implements IMediaRepository {
  private _media: Media[] = [];
  private tracer: ITracer;
  private logger: ILogger;

  constructor(
    tracer: ITracer = new NoopTracer(),
    logger: ILogger = new NoopLogger(),
  ) {
    this.tracer = tracer;
    this.logger = logger;
    void this.logger; // currently unused; reserved for future mock-thrown captures
  }

  /** Test helper — seeds the in-memory store directly. */
  async _store(media: Media): Promise<void> {
    this._media.push(media);
  }

  async getMedia(id: string): Promise<Media | undefined> {
    return this.tracer.startSpan(
      { name: "media.getMedia", op: "repository", attributes: { id } },
      async (span) => {
        const found = this._media.find((m) => m.id === id);
        span.setAttribute("found", Boolean(found));
        return found;
      },
    );
  }

  async listMedia(opts?: { limit?: number; offset?: number }): Promise<Media[]> {
    return this.tracer.startSpan(
      {
        name: "media.listMedia",
        op: "repository",
        attributes: {
          limit: opts?.limit ?? null,
          offset: opts?.offset ?? null,
        },
      },
      async (span) => {
        const offset = opts?.offset ?? 0;
        const limit = opts?.limit ?? 50;
        const result = this._media.slice(offset, offset + limit);
        span.setAttribute("count", result.length);
        return result;
      },
    );
  }

  async deleteMedia(id: string): Promise<void> {
    return this.tracer.startSpan(
      { name: "media.deleteMedia", op: "repository", attributes: { id } },
      async (span) => {
        const before = this._media.length;
        this._media = this._media.filter((m) => m.id !== id);
        span.setAttribute("deleted", this._media.length < before);
      },
    );
  }
}
