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

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

interface BlogPostProps {
  id: string;
  title: string;
  slug: string;
  excerpt: string;
  content: string;
  coverImageUrl?: string;
  category: BlogPostCategory;
  tags: string[];
  authorName: string;
  status: BlogPostStatus;
  isFeatured: boolean;
  publishedAt?: Date;
  createdAt: Date;
  updatedAt: Date;
}

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

  static create(
    props: Omit<BlogPostProps, 'status' | 'isFeatured' | 'publishedAt' | 'createdAt' | 'updatedAt'>
  ): BlogPost {
    const now = new Date();
    return new BlogPost({
      ...props,
      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 | 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 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'
      >
    >
  ): BlogPost {
    return new BlogPost({ ...this.props, ...data, updatedAt: new Date() });
  }

  publish(): BlogPost {
    return new BlogPost({
      ...this.props,
      status: BlogPostStatus.PUBLISHED,
      publishedAt: this.props.publishedAt ?? new 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, updatedAt: new Date() });
  }

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

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