import { z } from "zod";

// Enums for GraphQL/API
export const roleEnum = z.enum([
	"user",
	"contributor",
	"reviewer",
	"editor",
	"admin",
]);

export const workTypeEnum = z.enum([
	"poem",
	"story",
	"novel",
	"play",
	"essay",
	"other",
]);

export const contributionStatusEnum = z.enum([
	"draft",
	"submitted",
	"under_review",
	"approved",
	"rejected",
]);

// Core entity schemas for GraphQL/API
export const userSchema = z.object({
	id: z.string(),
	username: z.string(),
	email: z.string(),
	displayName: z.string().optional(),
	firstName: z.string().optional(),
	lastName: z.string().optional(),
	bio: z.string().optional(),
	avatar: z.string().optional(),
	role: roleEnum,
	verified: z.boolean().optional(),
	active: z.boolean().optional(),
	lastLoginAt: z.string().optional(),
	createdAt: z.string(), // ISO date string
	updatedAt: z.string().optional(),
	countryId: z.string().optional(),
	cityId: z.string().optional(),
});

export const authorSchema = z.object({
	id: z.string(),
	name: z.string(),
	slug: z.string(),
	birthYear: z.number().optional(),
	deathYear: z.number().optional(),
	country: z.string().optional(),
	biography: z.string().optional(),
	portrait: z.string().optional(),
	createdAt: z.string(),
	createdBy: z.string().optional(),
	updatedAt: z.string().optional(),
	countryId: z.string().optional(),
	cityId: z.string().optional(),
	copyrightId: z.string().optional(),
});

export const workSchema = z.object({
	id: z.string(),
	title: z.string(),
	slug: z.string(),
	authorId: z.string(),
	year: z.number().optional(),
	type: workTypeEnum,
	language: z.string(),
	content: z.string(),
	description: z.string().optional(),
	createdAt: z.string(),
	createdBy: z.string().optional(),
	updatedAt: z.string().optional(),
	tags: z.array(z.string()).optional(), // Array of tag IDs
	likes: z.number().optional(),
	views: z.number().optional(),
	author: authorSchema.optional(), // For denormalized author info
	readabilityScore: z.number().optional(),
	copyrightId: z.string().optional(),
});

export const translationSchema = z.object({
	id: z.string(),
	workId: z.string(),
	title: z.string(),
	language: z.string(),
	content: z.string(),
	translatorId: z.string(),
	year: z.number().optional(),
	notes: z.string().optional(),
	description: z.string().optional(),
	createdAt: z.string(),
});

export const tagSchema = z.object({
	id: z.string(),
	name: z.string(),
	type: z.string(), // genre, period, theme, etc.
	createdAt: z.string(),
});

export const bookmarkSchema = z.object({
	id: z.string(),
	userId: z.string(),
	workId: z.string(),
	note: z.string().optional(),
	createdAt: z.string(),
});

export const commentSchema = z.object({
	id: z.string(),
	userId: z.string(),
	workId: z.string().optional(),
	translationId: z.string().optional(),
	lineNumber: z.number().optional(),
	content: z.string(),
	parentId: z.string().optional(),
	entityType: z.string().optional(), // 'work', 'translation', 'blogPost', etc.
	entityId: z.string().optional(),
	createdAt: z.string(),
});

export const likeSchema = z.object({
	id: z.string(),
	userId: z.string(),
	entityType: z.string(), // 'work', 'translation', 'comment'
	entityId: z.string(),
	createdAt: z.string(),
});

export const collectionSchema = z.object({
	id: z.string(),
	name: z.string(),
	slug: z.string(),
	description: z.string().optional(),
	userId: z.string(),
	isPublic: z.boolean(),
	createdAt: z.string(),
});

export const collectionItemSchema = z.object({
	id: z.string(),
	collectionId: z.string(),
	workId: z.string(),
	order: z.number(),
	addedAt: z.string(),
});

export const timelineEventSchema = z.object({
	id: z.string(),
	authorId: z.string(),
	year: z.number(),
	title: z.string(),
	description: z.string().optional(),
	createdAt: z.string(),
});

export const blogPostSchema = z.object({
	id: z.string(),
	title: z.string(),
	slug: z.string(),
	content: z.string(),
	authorId: z.string(),
	excerpt: z.string().optional(),
	publishedAt: z.string().optional(),
	createdAt: z.string(),
});

export const readingProgressSchema = z.object({
	id: z.string(),
	userId: z.string(),
	workId: z.string(),
	translationId: z.string().optional(),
	progress: z.number().min(0).max(100), // percentage
	lastReadAt: z.string(),
});

export const annotationSchema = z.object({
	id: z.string(),
	workId: z.string(),
	translationId: z.string().optional(),
	lineNumber: z.number().optional(),
	content: z.string(),
	type: z.string(), // 'context', 'analysis', 'translation', etc.
	userId: z.string(),
	isOfficial: z.boolean(),
	createdAt: z.string(),
});

export const analysisResultSchema = z.object({
	id: z.string(),
	workId: z.string(),
	type: z.string(), // 'sentiment', 'linguistics', 'themes', 'poetic', etc.
	data: z.record(z.string(), z.unknown()), // flexible data structure
	createdAt: z.string(),
});

// New schemas for GraphQL alignment
export const countrySchema = z.object({
	id: z.string(),
	name: z.string(),
	code: z.string(),
	language: z.string(),
	createdAt: z.string(),
	updatedAt: z.string().optional(),
});

export const citySchema = z.object({
	id: z.string(),
	name: z.string(),
	countryId: z.string(),
	language: z.string(),
	createdAt: z.string(),
	updatedAt: z.string().optional(),
});

export const bookSchema = z.object({
	id: z.string(),
	title: z.string(),
	slug: z.string(),
	language: z.string(),
	authorId: z.string(),
	copyrightId: z.string().optional(),
	createdAt: z.string(),
	updatedAt: z.string().optional(),
});

export const copyrightSchema = z.object({
	id: z.string(),
	name: z.string(),
	language: z.string(),
	details: z.string().optional(),
	createdAt: z.string(),
	updatedAt: z.string().optional(),
});

export const contributionSchema = z.object({
	id: z.string(),
	name: z.string(),
	status: contributionStatusEnum,
	userId: z.string(),
	workId: z.string().optional(),
	translationId: z.string().optional(),
	createdAt: z.string(),
	updatedAt: z.string().optional(),
});

export const userProfileSchema = z.object({
	id: z.string(),
	userId: z.string(),
	phoneNumber: z.string().optional(),
	website: z.string().optional(),
	twitter: z.string().optional(),
	facebook: z.string().optional(),
	linkedIn: z.string().optional(),
	github: z.string().optional(),
	preferences: z.record(z.string(), z.unknown()).optional(),
	settings: z.record(z.string(), z.unknown()).optional(),
	createdAt: z.string(),
	updatedAt: z.string().optional(),
});

export const readabilityScoreSchema = z.object({
	id: z.string(),
	workId: z.string(),
	score: z.number(),
	language: z.string(),
	createdAt: z.string(),
	updatedAt: z.string().optional(),
});

export const writingStyleSchema = z.object({
	id: z.string(),
	workId: z.string(),
	name: z.string(),
	language: z.string(),
	characteristics: z.record(z.string(), z.unknown()).optional(),
	createdAt: z.string(),
	updatedAt: z.string().optional(),
});

export const emotionSchema = z.object({
	id: z.string(),
	name: z.string(),
	workId: z.string().optional(),
	userId: z.string().optional(),
	collectionId: z.string().optional(),
	language: z.string(),
	intensity: z.number().optional(),
	createdAt: z.string(),
	updatedAt: z.string().optional(),
});

export const conceptSchema = z.object({
	id: z.string(),
	name: z.string(),
	description: z.string().optional(),
	createdAt: z.string(),
	updatedAt: z.string().optional(),
});

export const topicClusterSchema = z.object({
	id: z.string(),
	name: z.string(),
	description: z.string().optional(),
	createdAt: z.string(),
	updatedAt: z.string().optional(),
});

export const workStatsSchema = z.object({
	id: z.string(),
	workId: z.string(),
	views: z.number(),
	likes: z.number(),
	bookmarks: z.number(),
	comments: z.number(),
	createdAt: z.string(),
	updatedAt: z.string().optional(),
});

export const userStatsSchema = z.object({
	id: z.string(),
	userId: z.string(),
	activity: z.number(),
	contributions: z.number(),
	likes: z.number(),
	comments: z.number(),
	createdAt: z.string(),
	updatedAt: z.string().optional(),
});

// Input schemas for GraphQL mutations/API endpoints
export const createUserSchema = userSchema.omit({
	id: true,
	createdAt: true,
	role: true, // Role assigned by system
});

export const createAuthorSchema = authorSchema.omit({
	id: true,
	createdAt: true,
});

export const createWorkSchema = workSchema.omit({
	id: true,
	createdAt: true,
	author: true, // Not included in creation
});

export const createTranslationSchema = translationSchema.omit({
	id: true,
	createdAt: true,
});

export const createTagSchema = tagSchema.omit({
	id: true,
	createdAt: true,
});

export const createBookmarkSchema = bookmarkSchema.omit({
	id: true,
	createdAt: true,
});

export const createCommentSchema = commentSchema.omit({
	id: true,
	createdAt: true,
});

export const createLikeSchema = likeSchema.omit({
	id: true,
	createdAt: true,
});

export const createCollectionSchema = collectionSchema.omit({
	id: true,
	createdAt: true,
});

export const createCollectionItemSchema = collectionItemSchema.omit({
	id: true,
	addedAt: true,
});

export const createTimelineEventSchema = timelineEventSchema.omit({
	id: true,
	createdAt: true,
});

export const createBlogPostSchema = blogPostSchema.omit({
	id: true,
	createdAt: true,
});

export const createReadingProgressSchema = readingProgressSchema.omit({
	id: true,
	lastReadAt: true,
});

export const createAnnotationSchema = annotationSchema.omit({
	id: true,
	createdAt: true,
});

export const createAnalysisResultSchema = analysisResultSchema.omit({
	id: true,
	createdAt: true,
});

// New create schemas for GraphQL alignment
export const createCountrySchema = countrySchema.omit({
	id: true,
	createdAt: true,
	updatedAt: true,
});

export const createCitySchema = citySchema.omit({
	id: true,
	createdAt: true,
	updatedAt: true,
});

export const createBookSchema = bookSchema.omit({
	id: true,
	createdAt: true,
	updatedAt: true,
});

export const createCopyrightSchema = copyrightSchema.omit({
	id: true,
	createdAt: true,
	updatedAt: true,
});

export const createContributionSchema = contributionSchema.omit({
	id: true,
	createdAt: true,
	updatedAt: true,
});

export const createUserProfileSchema = userProfileSchema.omit({
	id: true,
	createdAt: true,
	updatedAt: true,
});

export const createReadabilityScoreSchema = readabilityScoreSchema.omit({
	id: true,
	createdAt: true,
	updatedAt: true,
});

export const createWritingStyleSchema = writingStyleSchema.omit({
	id: true,
	createdAt: true,
	updatedAt: true,
});

export const createEmotionSchema = emotionSchema.omit({
	id: true,
	createdAt: true,
	updatedAt: true,
});

export const createConceptSchema = conceptSchema.omit({
	id: true,
	createdAt: true,
	updatedAt: true,
});

export const createTopicClusterSchema = topicClusterSchema.omit({
	id: true,
	createdAt: true,
	updatedAt: true,
});

export const createWorkStatsSchema = workStatsSchema.omit({
	id: true,
	createdAt: true,
	updatedAt: true,
});

export const createUserStatsSchema = userStatsSchema.omit({
	id: true,
	createdAt: true,
	updatedAt: true,
});

// Update schemas for partial updates
export const updateUserSchema = createUserSchema.partial();
export const updateAuthorSchema = createAuthorSchema.partial();
export const updateWorkSchema = createWorkSchema.partial();
export const updateTranslationSchema = createTranslationSchema.partial();
export const updateTagSchema = createTagSchema.partial();
export const updateBookmarkSchema = createBookmarkSchema.partial();
export const updateCommentSchema = createCommentSchema.partial();
export const updateCollectionSchema = createCollectionSchema.partial();
export const updateTimelineEventSchema = createTimelineEventSchema.partial();
export const updateBlogPostSchema = createBlogPostSchema.partial();
export const updateReadingProgressSchema =
	createReadingProgressSchema.partial();
export const updateAnnotationSchema = createAnnotationSchema.partial();

// New update schemas for GraphQL alignment
export const updateCountrySchema = createCountrySchema.partial();
export const updateCitySchema = createCitySchema.partial();
export const updateBookSchema = createBookSchema.partial();
export const updateCopyrightSchema = createCopyrightSchema.partial();
export const updateContributionSchema = createContributionSchema.partial();
export const updateUserProfileSchema = createUserProfileSchema.partial();
export const updateReadabilityScoreSchema =
	createReadabilityScoreSchema.partial();
export const updateWritingStyleSchema = createWritingStyleSchema.partial();
export const updateEmotionSchema = createEmotionSchema.partial();
export const updateConceptSchema = createConceptSchema.partial();
export const updateTopicClusterSchema = createTopicClusterSchema.partial();
export const updateWorkStatsSchema = createWorkStatsSchema.partial();
export const updateUserStatsSchema = createUserStatsSchema.partial();

// TypeScript types inferred from Zod schemas
export type User = z.infer<typeof userSchema>;
export type Author = z.infer<typeof authorSchema>;
export type Work = z.infer<typeof workSchema>;
export type Translation = z.infer<typeof translationSchema>;
export type Tag = z.infer<typeof tagSchema>;
export type Bookmark = z.infer<typeof bookmarkSchema>;
export type Comment = z.infer<typeof commentSchema>;
export type Like = z.infer<typeof likeSchema>;
export type Collection = z.infer<typeof collectionSchema>;
export type CollectionItem = z.infer<typeof collectionItemSchema>;
export type TimelineEvent = z.infer<typeof timelineEventSchema>;
export type BlogPost = z.infer<typeof blogPostSchema>;
export type ReadingProgress = z.infer<typeof readingProgressSchema>;
export type Annotation = z.infer<typeof annotationSchema>;
export type AnalysisResult = z.infer<typeof analysisResultSchema>;

// New types for GraphQL alignment
export type Country = z.infer<typeof countrySchema>;
export type City = z.infer<typeof citySchema>;
export type Book = z.infer<typeof bookSchema>;
export type Copyright = z.infer<typeof copyrightSchema>;
export type Contribution = z.infer<typeof contributionSchema>;
export type UserProfile = z.infer<typeof userProfileSchema>;
export type ReadabilityScore = z.infer<typeof readabilityScoreSchema>;
export type WritingStyle = z.infer<typeof writingStyleSchema>;
export type Emotion = z.infer<typeof emotionSchema>;
export type Concept = z.infer<typeof conceptSchema>;
export type TopicCluster = z.infer<typeof topicClusterSchema>;
export type WorkStats = z.infer<typeof workStatsSchema>;
export type UserStats = z.infer<typeof userStatsSchema>;

// Input types
export type CreateUser = z.infer<typeof createUserSchema>;
export type CreateAuthor = z.infer<typeof createAuthorSchema>;
export type CreateWork = z.infer<typeof createWorkSchema>;
export type CreateTranslation = z.infer<typeof createTranslationSchema>;
export type CreateTag = z.infer<typeof createTagSchema>;
export type CreateBookmark = z.infer<typeof createBookmarkSchema>;
export type CreateComment = z.infer<typeof createCommentSchema>;
export type CreateLike = z.infer<typeof createLikeSchema>;
export type CreateCollection = z.infer<typeof createCollectionSchema>;
export type CreateCollectionItem = z.infer<typeof createCollectionItemSchema>;
export type CreateTimelineEvent = z.infer<typeof createTimelineEventSchema>;
export type CreateBlogPost = z.infer<typeof createBlogPostSchema>;
export type CreateReadingProgress = z.infer<typeof createReadingProgressSchema>;
export type CreateAnnotation = z.infer<typeof createAnnotationSchema>;
export type CreateAnalysisResult = z.infer<typeof createAnalysisResultSchema>;

// New create types for GraphQL alignment
export type CreateCountry = z.infer<typeof createCountrySchema>;
export type CreateCity = z.infer<typeof createCitySchema>;
export type CreateBook = z.infer<typeof createBookSchema>;
export type CreateCopyright = z.infer<typeof createCopyrightSchema>;
export type CreateContribution = z.infer<typeof createContributionSchema>;
export type CreateUserProfile = z.infer<typeof createUserProfileSchema>;
export type CreateReadabilityScore = z.infer<
	typeof createReadabilityScoreSchema
>;
export type CreateWritingStyle = z.infer<typeof createWritingStyleSchema>;
export type CreateEmotion = z.infer<typeof createEmotionSchema>;
export type CreateConcept = z.infer<typeof createConceptSchema>;
export type CreateTopicCluster = z.infer<typeof createTopicClusterSchema>;
export type CreateWorkStats = z.infer<typeof createWorkStatsSchema>;
export type CreateUserStats = z.infer<typeof createUserStatsSchema>;

// Update types
export type UpdateUser = z.infer<typeof updateUserSchema>;
export type UpdateAuthor = z.infer<typeof updateAuthorSchema>;
export type UpdateWork = z.infer<typeof updateWorkSchema>;
export type UpdateTranslation = z.infer<typeof updateTranslationSchema>;
export type UpdateTag = z.infer<typeof updateTagSchema>;
export type UpdateBookmark = z.infer<typeof updateBookmarkSchema>;
export type UpdateComment = z.infer<typeof updateCommentSchema>;
export type UpdateCollection = z.infer<typeof updateCollectionSchema>;
export type UpdateTimelineEvent = z.infer<typeof updateTimelineEventSchema>;
export type UpdateBlogPost = z.infer<typeof updateBlogPostSchema>;
export type UpdateReadingProgress = z.infer<typeof updateReadingProgressSchema>;
export type UpdateAnnotation = z.infer<typeof updateAnnotationSchema>;

// New update types for GraphQL alignment
export type UpdateCountry = z.infer<typeof updateCountrySchema>;
export type UpdateCity = z.infer<typeof updateCitySchema>;
export type UpdateBook = z.infer<typeof updateBookSchema>;
export type UpdateCopyright = z.infer<typeof updateCopyrightSchema>;
export type UpdateContribution = z.infer<typeof updateContributionSchema>;
export type UpdateUserProfile = z.infer<typeof updateUserProfileSchema>;
export type UpdateReadabilityScore = z.infer<
	typeof updateReadabilityScoreSchema
>;
export type UpdateWritingStyle = z.infer<typeof updateWritingStyleSchema>;
export type UpdateEmotion = z.infer<typeof updateEmotionSchema>;
export type UpdateConcept = z.infer<typeof updateConceptSchema>;
export type UpdateTopicCluster = z.infer<typeof updateTopicClusterSchema>;
export type UpdateWorkStats = z.infer<typeof updateWorkStatsSchema>;
export type UpdateUserStats = z.infer<typeof updateUserStatsSchema>;

// API Response schemas
export const apiResponseSchema = z.object({
	success: z.boolean(),
	data: z.unknown().optional(),
	error: z.string().optional(),
	message: z.string().optional(),
});

export const paginatedResponseSchema = z.object({
	data: z.array(z.unknown()),
	pagination: z.object({
		page: z.number(),
		limit: z.number(),
		total: z.number(),
		totalPages: z.number(),
	}),
});

export type ApiResponse = z.infer<typeof apiResponseSchema>;
export type PaginatedResponse = z.infer<typeof paginatedResponseSchema>;
