import {
  createInList, readInList, updateInList, deleteInList,
  createById, readById, updateById, deleteById
} from "../utils/articles";
import { AuthUser } from "../../../auth/src";


export interface AuthorModel extends AuthUser {
  // meta fields
  _id?: string | null;
  created_at: string;
  updated_at: string;

  // model fields
  name: string;
  avatar: string;
}

export interface ArticleModel {
  // meta fields
  _id?: string | null;
  created_at: string;
  updated_at: string;

  // model fields
  img: string;
  tag: string;
  title: string;
  description: string;
  content: string;

  // ref fields
  authors: AuthorModel[];
}

export interface ArticlesModel {
  articlesList: ArticleModel[];
  articlesById: Record<string, ArticleModel>;
  // articlesByTag: Record<string, ArticleModel[]>;
  // articlesByAuthor: Record<string, ArticleModel[]>;

  length: number;
  slice(start: number, end?: number): ArticleModel[];

  refresh(list: ArticleModel[]): ArticlesModel;
  create(a: ArticleModel): ArticlesModel;
  readByIndex(index: number): ArticleModel | undefined;
  readById(id: string): ArticleModel | undefined;
  update(a: ArticleModel): ArticlesModel;
  delete(id: string): ArticlesModel;
}

// ---------- FACTORY ----------
export function createArticlesModelObject(
  articles: ArticleModel[] = []
): ArticlesModel {
  const initialMap: Record<string, ArticleModel> = {};
  for (const a of articles) {
    if (a._id) initialMap[a._id] = a;
  }

  return {
    articlesList: articles,
    articlesById: initialMap,

    // --- computed property ---
    get length() {
      return this.articlesList.length;
    },

    // --- array-like slice ---
    slice(start: number, end?: number) {
      return this.articlesList.slice(start, end);
    },

    refresh(list) {
      this.articlesList = list;

      const map: Record<string, ArticleModel> = {};
      for (const a of list) {
        if (a._id) map[a._id] = a;
      }
      this.articlesById = map;
      return this;
    },

    create(a) {
      this.articlesList = createInList(this.articlesList, a);
      this.articlesById = createById(this.articlesById, a);
      return this;
    },

    readByIndex(index) {
      return readInList(this.articlesList, index);
    },

    readById(id) {
      return readById(this.articlesById, id);
    },

    update(a) {
      this.articlesList = updateInList(this.articlesList, a);
      this.articlesById = updateById(this.articlesById, a);
      return this;
    },

    delete(id) {
      this.articlesList = deleteInList(this.articlesList, id);
      this.articlesById = deleteById(this.articlesById, id);
      return this;
    }
  };
}
