import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import {
  IsString,
  IsNotEmpty,
  IsOptional,
  IsArray,
  IsBoolean,
  IsEnum,
  IsDateString,
  MaxLength,
  MinLength,
  Matches,
  ValidateIf,
  ValidateNested,
} from 'class-validator';
import { Type } from 'class-transformer';
import {
  BlogPostStatus,
  type BlogPostCategory,
  type BlogFaqItem,
} from '@domain/entities/blog-post.entity';

const CATEGORIES: BlogPostCategory[] = ['industry', 'technology', 'guides', 'news'];

export class BlogFaqItemDto implements BlogFaqItem {
  @ApiProperty()
  @IsString()
  @IsNotEmpty()
  @MaxLength(500)
  question: string;

  @ApiProperty()
  @IsString()
  @IsNotEmpty()
  @MaxLength(4000)
  answer: string;
}

/**
 * GEO (Generative Engine Optimisation) fields, shared by create/update DTOs.
 */
export class BlogGeoFields {
  @ApiPropertyOptional({ description: 'AI summary / TL;DR of the article' })
  @IsOptional()
  @ValidateIf((_, value) => value !== null)
  @IsString()
  @MaxLength(2000)
  aiSummary?: string | null;

  @ApiPropertyOptional({ type: [BlogFaqItemDto], description: 'FAQ (question/answer pairs)' })
  @IsOptional()
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => BlogFaqItemDto)
  faq?: BlogFaqItemDto[];

  @ApiPropertyOptional({ type: [String], description: 'Key takeaways' })
  @IsOptional()
  @IsArray()
  @IsString({ each: true })
  keyTakeaways?: string[];

  @ApiPropertyOptional({ type: [String], description: 'Related entities / topics' })
  @IsOptional()
  @IsArray()
  @IsString({ each: true })
  aiEntities?: string[];
}

export class CreateBlogPostDto extends BlogGeoFields {
  @ApiProperty()
  @IsString()
  @IsNotEmpty()
  @MaxLength(255)
  title: string;

  @ApiProperty({ description: 'URL-friendly slug, e.g. "my-article"' })
  @IsString()
  @IsNotEmpty()
  @MaxLength(255)
  @Matches(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, {
    message: 'Slug must be lowercase alphanumeric with hyphens',
  })
  slug: string;

  @ApiProperty()
  @IsString()
  @IsNotEmpty()
  @MinLength(10)
  excerpt: string;

  @ApiProperty()
  @IsString()
  @IsNotEmpty()
  content: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  @MaxLength(500)
  coverImageUrl?: string;

  @ApiProperty({ enum: CATEGORIES })
  @IsEnum(CATEGORIES)
  category: BlogPostCategory;

  @ApiPropertyOptional({ type: [String] })
  @IsOptional()
  @IsArray()
  @IsString({ each: true })
  tags?: string[];

  @ApiProperty()
  @IsString()
  @IsNotEmpty()
  @MaxLength(255)
  authorName: string;

  @ApiPropertyOptional({ description: 'ISO date string for scheduled publication' })
  @IsOptional()
  @IsDateString()
  scheduledAt?: string;

  @ApiPropertyOptional({ description: 'SEO meta title (50-60 chars recommended)' })
  @IsOptional()
  @IsString()
  @MaxLength(255)
  metaTitle?: string;

  @ApiPropertyOptional({ description: 'SEO meta description (150-160 chars recommended)' })
  @IsOptional()
  @IsString()
  @MaxLength(500)
  metaDescription?: string;

  @ApiPropertyOptional({ description: 'Primary SEO keyword' })
  @IsOptional()
  @IsString()
  @MaxLength(255)
  primaryKeyword?: string;

  @ApiPropertyOptional({ type: [String], description: 'Secondary SEO keywords' })
  @IsOptional()
  @IsArray()
  @IsString({ each: true })
  secondaryKeywords?: string[];
}

export class UpdateBlogPostDto extends BlogGeoFields {
  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  @IsNotEmpty()
  @MaxLength(255)
  title?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  @MaxLength(255)
  @Matches(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, {
    message: 'Slug must be lowercase alphanumeric with hyphens',
  })
  slug?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  excerpt?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  content?: string;

  @ApiPropertyOptional({
    nullable: true,
    description: 'Cover image URL. Pass null to remove the current cover image.',
  })
  @IsOptional()
  @ValidateIf((_, value) => value !== null)
  @IsString()
  @MaxLength(500)
  coverImageUrl?: string | null;

  @ApiPropertyOptional({ enum: CATEGORIES })
  @IsOptional()
  @IsEnum(CATEGORIES)
  category?: BlogPostCategory;

  @ApiPropertyOptional({ type: [String] })
  @IsOptional()
  @IsArray()
  @IsString({ each: true })
  tags?: string[];

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  @MaxLength(255)
  authorName?: string;

  @ApiPropertyOptional({ enum: BlogPostStatus })
  @IsOptional()
  @IsEnum(BlogPostStatus)
  status?: BlogPostStatus;

  @ApiPropertyOptional()
  @IsOptional()
  @IsBoolean()
  isFeatured?: boolean;

  @ApiPropertyOptional({ description: 'ISO date string for scheduled publication' })
  @IsOptional()
  @IsDateString()
  scheduledAt?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  @MaxLength(255)
  metaTitle?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  @MaxLength(500)
  metaDescription?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  @MaxLength(255)
  primaryKeyword?: string;

  @ApiPropertyOptional({ type: [String] })
  @IsOptional()
  @IsArray()
  @IsString({ each: true })
  secondaryKeywords?: string[];
}

export class BlogPostResponseDto {
  @ApiProperty() id: string;
  @ApiProperty() title: string;
  @ApiProperty() slug: string;
  @ApiProperty() excerpt: string;
  @ApiProperty() content: string;
  @ApiPropertyOptional() coverImageUrl?: string;
  @ApiProperty() category: string;
  @ApiProperty({ type: [String] }) tags: string[];
  @ApiProperty() authorName: string;
  @ApiProperty({ enum: BlogPostStatus }) status: BlogPostStatus;
  @ApiProperty() isFeatured: boolean;
  @ApiPropertyOptional() publishedAt?: Date;
  @ApiPropertyOptional() metaTitle?: string;
  @ApiPropertyOptional() metaDescription?: string;
  @ApiPropertyOptional() primaryKeyword?: string;
  @ApiProperty({ type: [String] }) secondaryKeywords: string[];
  @ApiPropertyOptional() aiSummary?: string | null;
  @ApiProperty({ type: [BlogFaqItemDto] }) faq: BlogFaqItemDto[];
  @ApiProperty({ type: [String] }) keyTakeaways: string[];
  @ApiProperty({ type: [String] }) aiEntities: string[];
  @ApiProperty() createdAt: Date;
  @ApiProperty() updatedAt: Date;
}

export class BlogPostListResponseDto {
  @ApiProperty({ type: [BlogPostResponseDto] }) posts: BlogPostResponseDto[];
  @ApiProperty() total: number;
  @ApiProperty() limit: number;
  @ApiProperty() offset: number;
}
