import { builder } from "../builder";

// File type
export const FileType = builder.objectRef<{
  id: string;
  title: string | null;
  description: string | null;
  filename: string;
  mime_type: string | null;
  filesize: number | null;
  duration: number | null;
  uploaded_by: string | null;
  date_created: Date;
}>("File").implement({
  fields: (t) => ({
    id: t.exposeString("id"),
    title: t.exposeString("title", { nullable: true }),
    description: t.exposeString("description", { nullable: true }),
    filename: t.exposeString("filename"),
    mime_type: t.exposeString("mime_type", { nullable: true }),
    filesize: t.exposeFloat("filesize", { nullable: true }),
    duration: t.exposeInt("duration", { nullable: true }),
    uploaded_by: t.exposeString("uploaded_by", { nullable: true }),
    date_created: t.expose("date_created", { type: "DateTime" }),
  }),
});

// User type
export const UserType = builder.objectRef<{
  id: string;
  email: string;
  first_name: string | null;
  last_name: string | null;
  artist_name: string | null;
  slug: string | null;
  description: string | null;
  tags: string[] | null;
  role: "model" | "viewer" | "admin";
  avatar: string | null;
  banner: string | null;
  email_verified: boolean;
  date_created: Date;
}>("User").implement({
  fields: (t) => ({
    id: t.exposeString("id"),
    email: t.exposeString("email"),
    first_name: t.exposeString("first_name", { nullable: true }),
    last_name: t.exposeString("last_name", { nullable: true }),
    artist_name: t.exposeString("artist_name", { nullable: true }),
    slug: t.exposeString("slug", { nullable: true }),
    description: t.exposeString("description", { nullable: true }),
    tags: t.exposeStringList("tags", { nullable: true }),
    role: t.exposeString("role"),
    avatar: t.exposeString("avatar", { nullable: true }),
    banner: t.exposeString("banner", { nullable: true }),
    email_verified: t.exposeBoolean("email_verified"),
    date_created: t.expose("date_created", { type: "DateTime" }),
  }),
});

// CurrentUser type (same shape, used for auth context)
export const CurrentUserType = builder.objectRef<{
  id: string;
  email: string;
  first_name: string | null;
  last_name: string | null;
  artist_name: string | null;
  slug: string | null;
  description: string | null;
  tags: string[] | null;
  role: "model" | "viewer" | "admin";
  avatar: string | null;
  banner: string | null;
  email_verified: boolean;
  date_created: Date;
}>("CurrentUser").implement({
  fields: (t) => ({
    id: t.exposeString("id"),
    email: t.exposeString("email"),
    first_name: t.exposeString("first_name", { nullable: true }),
    last_name: t.exposeString("last_name", { nullable: true }),
    artist_name: t.exposeString("artist_name", { nullable: true }),
    slug: t.exposeString("slug", { nullable: true }),
    description: t.exposeString("description", { nullable: true }),
    tags: t.exposeStringList("tags", { nullable: true }),
    role: t.exposeString("role"),
    avatar: t.exposeString("avatar", { nullable: true }),
    banner: t.exposeString("banner", { nullable: true }),
    email_verified: t.exposeBoolean("email_verified"),
    date_created: t.expose("date_created", { type: "DateTime" }),
  }),
});

// Video type
export const VideoType = builder.objectRef<{
  id: string;
  slug: string;
  title: string;
  description: string | null;
  image: string | null;
  movie: string | null;
  tags: string[] | null;
  upload_date: Date;
  premium: boolean | null;
  featured: boolean | null;
  likes_count: number | null;
  plays_count: number | null;
  models?: { id: string; artist_name: string | null; slug: string | null; avatar: string | null }[];
  movie_file?: { id: string; filename: string; mime_type: string | null; duration: number | null } | null;
}>("Video").implement({
  fields: (t) => ({
    id: t.exposeString("id"),
    slug: t.exposeString("slug"),
    title: t.exposeString("title"),
    description: t.exposeString("description", { nullable: true }),
    image: t.exposeString("image", { nullable: true }),
    movie: t.exposeString("movie", { nullable: true }),
    tags: t.exposeStringList("tags", { nullable: true }),
    upload_date: t.expose("upload_date", { type: "DateTime" }),
    premium: t.exposeBoolean("premium", { nullable: true }),
    featured: t.exposeBoolean("featured", { nullable: true }),
    likes_count: t.exposeInt("likes_count", { nullable: true }),
    plays_count: t.exposeInt("plays_count", { nullable: true }),
    models: t.expose("models", { type: [VideoModelType], nullable: true }),
    movie_file: t.expose("movie_file", { type: VideoFileType, nullable: true }),
  }),
});

export const VideoModelType = builder.objectRef<{
  id: string;
  artist_name: string | null;
  slug: string | null;
  avatar: string | null;
}>("VideoModel").implement({
  fields: (t) => ({
    id: t.exposeString("id"),
    artist_name: t.exposeString("artist_name", { nullable: true }),
    slug: t.exposeString("slug", { nullable: true }),
    avatar: t.exposeString("avatar", { nullable: true }),
  }),
});

export const VideoFileType = builder.objectRef<{
  id: string;
  filename: string;
  mime_type: string | null;
  duration: number | null;
}>("VideoFile").implement({
  fields: (t) => ({
    id: t.exposeString("id"),
    filename: t.exposeString("filename"),
    mime_type: t.exposeString("mime_type", { nullable: true }),
    duration: t.exposeInt("duration", { nullable: true }),
  }),
});

// Model type (model profile, enriched user)
export const ModelType = builder.objectRef<{
  id: string;
  slug: string | null;
  artist_name: string | null;
  description: string | null;
  avatar: string | null;
  banner: string | null;
  tags: string[] | null;
  date_created: Date;
  photos?: { id: string; filename: string }[];
}>("Model").implement({
  fields: (t) => ({
    id: t.exposeString("id"),
    slug: t.exposeString("slug", { nullable: true }),
    artist_name: t.exposeString("artist_name", { nullable: true }),
    description: t.exposeString("description", { nullable: true }),
    avatar: t.exposeString("avatar", { nullable: true }),
    banner: t.exposeString("banner", { nullable: true }),
    tags: t.exposeStringList("tags", { nullable: true }),
    date_created: t.expose("date_created", { type: "DateTime" }),
    photos: t.expose("photos", { type: [ModelPhotoType], nullable: true }),
  }),
});

export const ModelPhotoType = builder.objectRef<{
  id: string;
  filename: string;
}>("ModelPhoto").implement({
  fields: (t) => ({
    id: t.exposeString("id"),
    filename: t.exposeString("filename"),
  }),
});

// Article type
export const ArticleType = builder.objectRef<{
  id: string;
  slug: string;
  title: string;
  excerpt: string | null;
  content: string | null;
  image: string | null;
  tags: string[] | null;
  publish_date: Date;
  category: string | null;
  featured: boolean | null;
  author?: { first_name: string | null; last_name: string | null; avatar: string | null; description: string | null } | null;
}>("Article").implement({
  fields: (t) => ({
    id: t.exposeString("id"),
    slug: t.exposeString("slug"),
    title: t.exposeString("title"),
    excerpt: t.exposeString("excerpt", { nullable: true }),
    content: t.exposeString("content", { nullable: true }),
    image: t.exposeString("image", { nullable: true }),
    tags: t.exposeStringList("tags", { nullable: true }),
    publish_date: t.expose("publish_date", { type: "DateTime" }),
    category: t.exposeString("category", { nullable: true }),
    featured: t.exposeBoolean("featured", { nullable: true }),
    author: t.expose("author", { type: ArticleAuthorType, nullable: true }),
  }),
});

export const ArticleAuthorType = builder.objectRef<{
  first_name: string | null;
  last_name: string | null;
  avatar: string | null;
  description: string | null;
}>("ArticleAuthor").implement({
  fields: (t) => ({
    first_name: t.exposeString("first_name", { nullable: true }),
    last_name: t.exposeString("last_name", { nullable: true }),
    avatar: t.exposeString("avatar", { nullable: true }),
    description: t.exposeString("description", { nullable: true }),
  }),
});

// Recording type
export const RecordingType = builder.objectRef<{
  id: string;
  title: string;
  description: string | null;
  slug: string;
  duration: number;
  events: object[] | null;
  device_info: object[] | null;
  user_id: string;
  status: string;
  tags: string[] | null;
  linked_video: string | null;
  featured: boolean | null;
  public: boolean | null;
  date_created: Date;
  date_updated: Date | null;
}>("Recording").implement({
  fields: (t) => ({
    id: t.exposeString("id"),
    title: t.exposeString("title"),
    description: t.exposeString("description", { nullable: true }),
    slug: t.exposeString("slug"),
    duration: t.exposeInt("duration"),
    events: t.expose("events", { type: "JSON", nullable: true }),
    device_info: t.expose("device_info", { type: "JSON", nullable: true }),
    user_id: t.exposeString("user_id"),
    status: t.exposeString("status"),
    tags: t.exposeStringList("tags", { nullable: true }),
    linked_video: t.exposeString("linked_video", { nullable: true }),
    featured: t.exposeBoolean("featured", { nullable: true }),
    public: t.exposeBoolean("public", { nullable: true }),
    date_created: t.expose("date_created", { type: "DateTime" }),
    date_updated: t.expose("date_updated", { type: "DateTime", nullable: true }),
  }),
});

// Comment type
export const CommentType = builder.objectRef<{
  id: number;
  collection: string;
  item_id: string;
  comment: string;
  user_id: string;
  date_created: Date;
  user?: { id: string; first_name: string | null; last_name: string | null; avatar: string | null } | null;
}>("Comment").implement({
  fields: (t) => ({
    id: t.exposeInt("id"),
    collection: t.exposeString("collection"),
    item_id: t.exposeString("item_id"),
    comment: t.exposeString("comment"),
    user_id: t.exposeString("user_id"),
    date_created: t.expose("date_created", { type: "DateTime" }),
    user: t.expose("user", { type: CommentUserType, nullable: true }),
  }),
});

export const CommentUserType = builder.objectRef<{
  id: string;
  first_name: string | null;
  last_name: string | null;
  avatar: string | null;
}>("CommentUser").implement({
  fields: (t) => ({
    id: t.exposeString("id"),
    first_name: t.exposeString("first_name", { nullable: true }),
    last_name: t.exposeString("last_name", { nullable: true }),
    avatar: t.exposeString("avatar", { nullable: true }),
  }),
});

// Stats type
export const StatsType = builder.objectRef<{
  videos_count: number;
  models_count: number;
  viewers_count: number;
}>("Stats").implement({
  fields: (t) => ({
    videos_count: t.exposeInt("videos_count"),
    models_count: t.exposeInt("models_count"),
    viewers_count: t.exposeInt("viewers_count"),
  }),
});

// Gamification types
export const LeaderboardEntryType = builder.objectRef<{
  user_id: string;
  display_name: string | null;
  avatar: string | null;
  total_weighted_points: number | null;
  total_raw_points: number | null;
  recordings_count: number | null;
  playbacks_count: number | null;
  achievements_count: number | null;
  rank: number;
}>("LeaderboardEntry").implement({
  fields: (t) => ({
    user_id: t.exposeString("user_id"),
    display_name: t.exposeString("display_name", { nullable: true }),
    avatar: t.exposeString("avatar", { nullable: true }),
    total_weighted_points: t.exposeFloat("total_weighted_points", { nullable: true }),
    total_raw_points: t.exposeInt("total_raw_points", { nullable: true }),
    recordings_count: t.exposeInt("recordings_count", { nullable: true }),
    playbacks_count: t.exposeInt("playbacks_count", { nullable: true }),
    achievements_count: t.exposeInt("achievements_count", { nullable: true }),
    rank: t.exposeInt("rank"),
  }),
});

export const AchievementType = builder.objectRef<{
  id: string;
  code: string;
  name: string;
  description: string | null;
  icon: string | null;
  category: string | null;
  required_count: number;
  points_reward: number;
}>("Achievement").implement({
  fields: (t) => ({
    id: t.exposeString("id"),
    code: t.exposeString("code"),
    name: t.exposeString("name"),
    description: t.exposeString("description", { nullable: true }),
    icon: t.exposeString("icon", { nullable: true }),
    category: t.exposeString("category", { nullable: true }),
    required_count: t.exposeInt("required_count"),
    points_reward: t.exposeInt("points_reward"),
  }),
});

export const UserGamificationType = builder.objectRef<{
  stats: {
    user_id: string;
    total_raw_points: number | null;
    total_weighted_points: number | null;
    recordings_count: number | null;
    playbacks_count: number | null;
    comments_count: number | null;
    achievements_count: number | null;
    rank: number;
  } | null;
  achievements: {
    id: string;
    code: string;
    name: string;
    description: string | null;
    icon: string | null;
    category: string | null;
    date_unlocked: Date;
    progress: number | null;
    required_count: number;
  }[];
  recent_points: {
    action: string;
    points: number;
    date_created: Date;
    recording_id: string | null;
  }[];
}>("UserGamification").implement({
  fields: (t) => ({
    stats: t.expose("stats", { type: UserStatsType, nullable: true }),
    achievements: t.expose("achievements", { type: [UserAchievementType] }),
    recent_points: t.expose("recent_points", { type: [RecentPointType] }),
  }),
});

export const UserStatsType = builder.objectRef<{
  user_id: string;
  total_raw_points: number | null;
  total_weighted_points: number | null;
  recordings_count: number | null;
  playbacks_count: number | null;
  comments_count: number | null;
  achievements_count: number | null;
  rank: number;
}>("UserStats").implement({
  fields: (t) => ({
    user_id: t.exposeString("user_id"),
    total_raw_points: t.exposeInt("total_raw_points", { nullable: true }),
    total_weighted_points: t.exposeFloat("total_weighted_points", { nullable: true }),
    recordings_count: t.exposeInt("recordings_count", { nullable: true }),
    playbacks_count: t.exposeInt("playbacks_count", { nullable: true }),
    comments_count: t.exposeInt("comments_count", { nullable: true }),
    achievements_count: t.exposeInt("achievements_count", { nullable: true }),
    rank: t.exposeInt("rank"),
  }),
});

export const UserAchievementType = builder.objectRef<{
  id: string;
  code: string;
  name: string;
  description: string | null;
  icon: string | null;
  category: string | null;
  date_unlocked: Date;
  progress: number | null;
  required_count: number;
}>("UserAchievement").implement({
  fields: (t) => ({
    id: t.exposeString("id"),
    code: t.exposeString("code"),
    name: t.exposeString("name"),
    description: t.exposeString("description", { nullable: true }),
    icon: t.exposeString("icon", { nullable: true }),
    category: t.exposeString("category", { nullable: true }),
    date_unlocked: t.expose("date_unlocked", { type: "DateTime" }),
    progress: t.exposeInt("progress", { nullable: true }),
    required_count: t.exposeInt("required_count"),
  }),
});

export const RecentPointType = builder.objectRef<{
  action: string;
  points: number;
  date_created: Date;
  recording_id: string | null;
}>("RecentPoint").implement({
  fields: (t) => ({
    action: t.exposeString("action"),
    points: t.exposeInt("points"),
    date_created: t.expose("date_created", { type: "DateTime" }),
    recording_id: t.exposeString("recording_id", { nullable: true }),
  }),
});

// Analytics types
export const AnalyticsType = builder.objectRef<{
  total_videos: number;
  total_likes: number;
  total_plays: number;
  plays_by_date: Record<string, number>;
  likes_by_date: Record<string, number>;
  videos: {
    id: string;
    title: string;
    slug: string;
    upload_date: Date;
    likes: number;
    plays: number;
    completed_plays: number;
    completion_rate: number;
    avg_watch_time: number;
  }[];
}>("Analytics").implement({
  fields: (t) => ({
    total_videos: t.exposeInt("total_videos"),
    total_likes: t.exposeInt("total_likes"),
    total_plays: t.exposeInt("total_plays"),
    plays_by_date: t.expose("plays_by_date", { type: "JSON" }),
    likes_by_date: t.expose("likes_by_date", { type: "JSON" }),
    videos: t.expose("videos", { type: [VideoAnalyticsType] }),
  }),
});

export const VideoAnalyticsType = builder.objectRef<{
  id: string;
  title: string;
  slug: string;
  upload_date: Date;
  likes: number;
  plays: number;
  completed_plays: number;
  completion_rate: number;
  avg_watch_time: number;
}>("VideoAnalytics").implement({
  fields: (t) => ({
    id: t.exposeString("id"),
    title: t.exposeString("title"),
    slug: t.exposeString("slug"),
    upload_date: t.expose("upload_date", { type: "DateTime" }),
    likes: t.exposeInt("likes"),
    plays: t.exposeInt("plays"),
    completed_plays: t.exposeInt("completed_plays"),
    completion_rate: t.exposeFloat("completion_rate"),
    avg_watch_time: t.exposeInt("avg_watch_time"),
  }),
});

// Response types
export const VideoLikeResponseType = builder.objectRef<{
  liked: boolean;
  likes_count: number;
}>("VideoLikeResponse").implement({
  fields: (t) => ({
    liked: t.exposeBoolean("liked"),
    likes_count: t.exposeInt("likes_count"),
  }),
});

export const VideoPlayResponseType = builder.objectRef<{
  success: boolean;
  play_id: string;
  plays_count: number;
}>("VideoPlayResponse").implement({
  fields: (t) => ({
    success: t.exposeBoolean("success"),
    play_id: t.exposeString("play_id"),
    plays_count: t.exposeInt("plays_count"),
  }),
});

export const VideoLikeStatusType = builder.objectRef<{
  liked: boolean;
}>("VideoLikeStatus").implement({
  fields: (t) => ({
    liked: t.exposeBoolean("liked"),
  }),
});
