import { pgTable, text, serial, integer, boolean, timestamp, pgEnum, primaryKey, json, unique } from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod";
import { z } from "zod";

// Enums
export const roleEnum = pgEnum('role', ['user', 'contributor', 'reviewer', 'editor', 'admin']);
export const workTypeEnum = pgEnum('work_type', ['poem', 'story', 'novel', 'play', 'essay', 'other']);

// Users table
export const users = pgTable("users", {
  id: serial("id").primaryKey(),
  username: text("username").notNull().unique(),
  password: text("password").notNull(),
  email: text("email").notNull().unique(),
  displayName: text("display_name"),
  bio: text("bio"),
  avatar: text("avatar"),
  role: roleEnum("role").default('user').notNull(),
  createdAt: timestamp("created_at").defaultNow().notNull(),
});

// Authors table
export const authors = pgTable("authors", {
  id: serial("id").primaryKey(),
  name: text("name").notNull(),
  slug: text("slug").notNull().unique(),
  birthYear: integer("birth_year"),
  deathYear: integer("death_year"),
  country: text("country"),
  biography: text("biography"),
  portrait: text("portrait"),
  createdAt: timestamp("created_at").defaultNow().notNull(),
  createdBy: integer("created_by").references(() => users.id),
});

// Works table (original literary works)
export const works = pgTable("works", {
  id: serial("id").primaryKey(),
  title: text("title").notNull(),
  slug: text("slug").notNull().unique(),
  authorId: integer("author_id").references(() => authors.id).notNull(),
  year: integer("year"),
  type: workTypeEnum("type").default('other').notNull(),
  language: text("language").notNull(),
  content: text("content").notNull(),
  description: text("description"),
  createdAt: timestamp("created_at").defaultNow().notNull(),
  createdBy: integer("created_by").references(() => users.id),
});

// Translations table
export const translations = pgTable("translations", {
  id: serial("id").primaryKey(),
  workId: integer("work_id").references(() => works.id).notNull(),
  title: text("title").notNull(),
  language: text("language").notNull(),
  content: text("content").notNull(),
  translatorId: integer("translator_id").references(() => users.id).notNull(),
  year: integer("year"),
  notes: text("notes"),
  description: text("description"),
  createdAt: timestamp("created_at").defaultNow().notNull(),
});

// Tags table
export const tags = pgTable("tags", {
  id: serial("id").primaryKey(),
  name: text("name").notNull().unique(),
  type: text("type").notNull(), // genre, period, theme, etc.
  createdAt: timestamp("created_at").defaultNow().notNull(),
});

// Work-Tag relations (many-to-many)
export const workTags = pgTable("work_tags", {
  workId: integer("work_id").references(() => works.id).notNull(),
  tagId: integer("tag_id").references(() => tags.id).notNull(),
}, (t) => ({
  pk: primaryKey(t.workId, t.tagId),
}));

// Bookmarks
export const bookmarks = pgTable("bookmarks", {
  id: serial("id").primaryKey(),
  userId: integer("user_id").references(() => users.id).notNull(),
  workId: integer("work_id").references(() => works.id).notNull(),
  note: text("note"),
  createdAt: timestamp("created_at").defaultNow().notNull(),
}, (t) => ({
  unq: unique().on(t.userId, t.workId),
}));

// Comments
export const comments = pgTable("comments", {
  id: serial("id").primaryKey(),
  userId: integer("user_id").references(() => users.id).notNull(),
  workId: integer("work_id").references(() => works.id),  // Optional for non-work comments
  translationId: integer("translation_id").references(() => translations.id),
  lineNumber: integer("line_number"),
  content: text("content").notNull(),
  parentId: integer("parent_id").references(() => comments.id),
  // Adding support for blog posts and other content types
  entityType: text("entity_type"), // 'work', 'translation', 'blogPost', etc.
  entityId: integer("entity_id"),  // ID of the entity
  createdAt: timestamp("created_at").defaultNow().notNull(),
});

// Likes (polymorphic)
export const likes = pgTable("likes", {
  id: serial("id").primaryKey(),
  userId: integer("user_id").references(() => users.id).notNull(),
  entityType: text("entity_type").notNull(), // 'work', 'translation', 'comment'
  entityId: integer("entity_id").notNull(),
  createdAt: timestamp("created_at").defaultNow().notNull(),
}, (t) => ({
  unq: unique().on(t.userId, t.entityType, t.entityId),
}));

// Collections (curated sets of works)
export const collections = pgTable("collections", {
  id: serial("id").primaryKey(),
  name: text("name").notNull(),
  slug: text("slug").notNull().unique(),
  description: text("description"),
  userId: integer("user_id").references(() => users.id).notNull(),
  isPublic: boolean("is_public").default(true).notNull(),
  createdAt: timestamp("created_at").defaultNow().notNull(),
});

// Collection items
export const collectionItems = pgTable("collection_items", {
  id: serial("id").primaryKey(),
  collectionId: integer("collection_id").references(() => collections.id).notNull(),
  workId: integer("work_id").references(() => works.id).notNull(),
  order: integer("order").default(0).notNull(),
  addedAt: timestamp("added_at").defaultNow().notNull(),
});

// Timeline events for authors
export const timelineEvents = pgTable("timeline_events", {
  id: serial("id").primaryKey(),
  authorId: integer("author_id").references(() => authors.id).notNull(),
  year: integer("year").notNull(),
  title: text("title").notNull(),
  description: text("description"),
  createdAt: timestamp("created_at").defaultNow().notNull(),
});

// Blog posts
export const blogPosts = pgTable("blog_posts", {
  id: serial("id").primaryKey(),
  title: text("title").notNull(),
  slug: text("slug").notNull().unique(),
  content: text("content").notNull(),
  authorId: integer("author_id").references(() => users.id).notNull(),
  excerpt: text("excerpt"),
  publishedAt: timestamp("published_at"),
  createdAt: timestamp("created_at").defaultNow().notNull(),
});

// Blog post tags
export const blogPostTags = pgTable("blog_post_tags", {
  postId: integer("post_id").references(() => blogPosts.id).notNull(),
  tagId: integer("tag_id").references(() => tags.id).notNull(),
}, (t) => ({
  pk: primaryKey(t.postId, t.tagId),
}));

// Reading progress
export const readingProgress = pgTable("reading_progress", {
  id: serial("id").primaryKey(),
  userId: integer("user_id").references(() => users.id).notNull(),
  workId: integer("work_id").references(() => works.id).notNull(),
  translationId: integer("translation_id").references(() => translations.id),
  progress: integer("progress").default(0).notNull(), // percentage
  lastReadAt: timestamp("last_read_at").defaultNow().notNull(),
});

// Insert schemas
export const insertUserSchema = createInsertSchema(users).omit({
  id: true,
  createdAt: true,
  role: true
});

export const insertAuthorSchema = createInsertSchema(authors).omit({
  id: true,
  createdAt: true
});

export const insertWorkSchema = createInsertSchema(works).omit({
  id: true,
  createdAt: true
});

export const insertTranslationSchema = createInsertSchema(translations).omit({
  id: true,
  createdAt: true
});

export const insertTagSchema = createInsertSchema(tags).omit({
  id: true,
  createdAt: true
});

export const insertBookmarkSchema = createInsertSchema(bookmarks).omit({
  id: true,
  createdAt: true
});

export const insertCommentSchema = createInsertSchema(comments).omit({
  id: true,
  createdAt: true
});

export const insertLikeSchema = createInsertSchema(likes).omit({
  id: true,
  createdAt: true
});

export const insertCollectionSchema = createInsertSchema(collections).omit({
  id: true,
  createdAt: true
});

export const insertCollectionItemSchema = createInsertSchema(collectionItems).omit({
  id: true,
  addedAt: true
});

export const insertTimelineEventSchema = createInsertSchema(timelineEvents).omit({
  id: true,
  createdAt: true
});

export const insertBlogPostSchema = createInsertSchema(blogPosts).omit({
  id: true,
  createdAt: true
});

export const insertReadingProgressSchema = createInsertSchema(readingProgress).omit({
  id: true,
  lastReadAt: true
});

// Types
export type InsertUser = z.infer<typeof insertUserSchema>;
export type User = typeof users.$inferSelect;

export type InsertAuthor = z.infer<typeof insertAuthorSchema>;
export type Author = typeof authors.$inferSelect;

export type InsertWork = z.infer<typeof insertWorkSchema>;
export type Work = typeof works.$inferSelect;

export type InsertTranslation = z.infer<typeof insertTranslationSchema>;
export type Translation = typeof translations.$inferSelect;

export type InsertTag = z.infer<typeof insertTagSchema>;
export type Tag = typeof tags.$inferSelect;

export type InsertBookmark = z.infer<typeof insertBookmarkSchema>;
export type Bookmark = typeof bookmarks.$inferSelect;

export type InsertComment = z.infer<typeof insertCommentSchema>;
export type Comment = typeof comments.$inferSelect;

export type InsertLike = z.infer<typeof insertLikeSchema>;
export type Like = typeof likes.$inferSelect;

export type InsertCollection = z.infer<typeof insertCollectionSchema>;
export type Collection = typeof collections.$inferSelect;

export type InsertCollectionItem = z.infer<typeof insertCollectionItemSchema>;
export type CollectionItem = typeof collectionItems.$inferSelect;

export type InsertTimelineEvent = z.infer<typeof insertTimelineEventSchema>;
export type TimelineEvent = typeof timelineEvents.$inferSelect;

export type InsertBlogPost = z.infer<typeof insertBlogPostSchema>;
export type BlogPost = typeof blogPosts.$inferSelect;

export type InsertReadingProgress = z.infer<typeof insertReadingProgressSchema>;
export type ReadingProgress = typeof readingProgress.$inferSelect;

// Analysis results interface for linguistic/sentiment analysis and other analytics
export interface AnalysisResult {
  id: number;
  workId: number;
  type: string; // 'sentiment', 'linguistics', 'themes', 'poetic', etc.
  data: any;
  createdAt: Date;
}

export type InsertAnalysisResult = Omit<AnalysisResult, 'id' | 'createdAt'>;

// Annotations interface for line-by-line notes, context, and analysis
export interface Annotation {
  id: number;
  workId: number;
  translationId: number | null;
  lineNumber: number | null;
  content: string;
  type: string; // 'context', 'analysis', 'translation', etc.
  userId: number;
  isOfficial: boolean;
  createdAt: Date;
}

export type InsertAnnotation = Omit<Annotation, 'id' | 'createdAt'>;
