export enum BlogPostStatus {
  DRAFT = 'draft',
  SCHEDULED = 'scheduled',
  PUBLISHED = 'published',
  ARCHIVED = 'archived',
}

export type BlogPostCategory = 'industry' | 'technology' | 'guides' | 'news';

/** A single question/answer pair used for GEO (AI) optimisation and FAQ schema. */
export interface BlogFaqItem {
  question: string;
  answer: string;
}

interface BlogPostProps {
  id: string;
  title: string;
  slug: string;
  excerpt: string;
  content: string;
  coverImageUrl?: string | null;
  category: BlogPostCategory;
  tags: string[];
  authorName: string;
  status: BlogPostStatus;
  isFeatured: boolean;
  publishedAt?: Date;
  metaTitle?: string;
  metaDescription?: string;
  primaryKeyword?: string;
  secondaryKeywords: string[];
  // GEO (Generative Engine Optimisation) — helps AI/LLM engines cite the article.
  aiSummary?: string | null;
  faq: BlogFaqItem[];
  keyTakeaways: string[];
  aiEntities: string[];
  // Soft delete (trash). Null/undefined means the post is not trashed.
  deletedAt?: Date | null;
  createdAt: Date;
  updatedAt: Date;
}

export class BlogPost {
  private constructor(private readonly props: BlogPostProps) {}

  static create(
    props: Omit<
      BlogPostProps,
      | 'status'
      | 'isFeatured'
      | 'publishedAt'
      | 'createdAt'
      | 'updatedAt'
      | 'faq'
      | 'keyTakeaways'
      | 'aiEntities'
      | 'deletedAt'
    > &
      Partial<Pick<BlogPostProps, 'faq' | 'keyTakeaways' | 'aiEntities'>>
  ): BlogPost {
    const now = new Date();
    return new BlogPost({
      ...props,
      secondaryKeywords: props.secondaryKeywords ?? [],
      faq: props.faq ?? [],
      keyTakeaways: props.keyTakeaways ?? [],
      aiEntities: props.aiEntities ?? [],
      status: BlogPostStatus.DRAFT,
      isFeatured: false,
      createdAt: now,
      updatedAt: now,
    });
  }

  static fromPersistence(props: BlogPostProps): BlogPost {
    return new BlogPost(props);
  }

  get id(): string {
    return this.props.id;
  }
  get title(): string {
    return this.props.title;
  }
  get slug(): string {
    return this.props.slug;
  }
  get excerpt(): string {
    return this.props.excerpt;
  }
  get content(): string {
    return this.props.content;
  }
  get coverImageUrl(): string | null | undefined {
    return this.props.coverImageUrl;
  }
  get category(): BlogPostCategory {
    return this.props.category;
  }
  get tags(): string[] {
    return this.props.tags;
  }
  get authorName(): string {
    return this.props.authorName;
  }
  get status(): BlogPostStatus {
    return this.props.status;
  }
  get isFeatured(): boolean {
    return this.props.isFeatured;
  }
  get publishedAt(): Date | undefined {
    return this.props.publishedAt;
  }
  get metaTitle(): string | undefined {
    return this.props.metaTitle;
  }
  get metaDescription(): string | undefined {
    return this.props.metaDescription;
  }
  get primaryKeyword(): string | undefined {
    return this.props.primaryKeyword;
  }
  get secondaryKeywords(): string[] {
    return this.props.secondaryKeywords;
  }
  get aiSummary(): string | null | undefined {
    return this.props.aiSummary;
  }
  get faq(): BlogFaqItem[] {
    return this.props.faq;
  }
  get keyTakeaways(): string[] {
    return this.props.keyTakeaways;
  }
  get aiEntities(): string[] {
    return this.props.aiEntities;
  }
  get deletedAt(): Date | null | undefined {
    return this.props.deletedAt;
  }
  get isTrashed(): boolean {
    return !!this.props.deletedAt;
  }
  get createdAt(): Date {
    return this.props.createdAt;
  }
  get updatedAt(): Date {
    return this.props.updatedAt;
  }

  update(
    data: Partial<
      Pick<
        BlogPostProps,
        | 'title'
        | 'slug'
        | 'excerpt'
        | 'content'
        | 'coverImageUrl'
        | 'category'
        | 'tags'
        | 'authorName'
        | 'isFeatured'
        | 'metaTitle'
        | 'metaDescription'
        | 'primaryKeyword'
        | 'secondaryKeywords'
        | 'aiSummary'
        | 'faq'
        | 'keyTakeaways'
        | 'aiEntities'
      >
    >
  ): BlogPost {
    return new BlogPost({ ...this.props, ...data, updatedAt: new Date() });
  }

  /** Move the post to the trash (soft delete). */
  trash(): BlogPost {
    return new BlogPost({ ...this.props, deletedAt: new Date(), updatedAt: new Date() });
  }

  /** Restore the post from the trash. */
  restore(): BlogPost {
    return new BlogPost({ ...this.props, deletedAt: null, updatedAt: new Date() });
  }

  publish(): BlogPost {
    return new BlogPost({
      ...this.props,
      status: BlogPostStatus.PUBLISHED,
      publishedAt: this.props.publishedAt ?? new Date(),
      updatedAt: new Date(),
    });
  }

  schedule(date: Date): BlogPost {
    return new BlogPost({
      ...this.props,
      status: BlogPostStatus.SCHEDULED,
      publishedAt: date,
      updatedAt: new Date(),
    });
  }

  archive(): BlogPost {
    return new BlogPost({ ...this.props, status: BlogPostStatus.ARCHIVED, updatedAt: new Date() });
  }

  unpublish(): BlogPost {
    return new BlogPost({
      ...this.props,
      status: BlogPostStatus.DRAFT,
      publishedAt: undefined,
      updatedAt: new Date(),
    });
  }

  isPublished(): boolean {
    return this.props.status === BlogPostStatus.PUBLISHED;
  }

  isVisibleToPublic(): boolean {
    if (this.props.deletedAt) return false;
    if (this.props.status === BlogPostStatus.PUBLISHED) return true;
    if (
      this.props.status === BlogPostStatus.SCHEDULED &&
      this.props.publishedAt &&
      this.props.publishedAt <= new Date()
    )
      return true;
    return false;
  }

  toObject(): BlogPostProps {
    return { ...this.props };
  }
}
