import type {
  MediaFile,
  User,
  VideoModel,
  VideoFile,
  Video,
  ModelPhoto,
  Model,
  Article,
  CommentUser,
  Comment,
  Stats,
  Recording,
  VideoLikeStatus,
  VideoLikeResponse,
  VideoPlayResponse,
  VideoAnalytics,
  Analytics,
  LeaderboardEntry,
  UserStats,
  UserAchievement,
  RecentPoint,
  UserGamification,
  Achievement,
} from "@sexy/types";

type AdminUserDetail = User & { photos: ModelPhoto[] };
import { builder } from "../builder";

export const FileType = builder.objectRef<MediaFile>("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" }),
  }),
});

export const UserType = builder.objectRef<User>("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"),
    is_admin: t.exposeBoolean("is_admin"),
    avatar: t.exposeString("avatar", { nullable: true }),
    banner: t.exposeString("banner", { nullable: true }),
    photo: t.exposeString("photo", { nullable: true }),
    email_verified: t.exposeBoolean("email_verified"),
    date_created: t.expose("date_created", { type: "DateTime" }),
  }),
});

// CurrentUser is the same shape as User
export const CurrentUserType = builder.objectRef<User>("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"),
    is_admin: t.exposeBoolean("is_admin"),
    avatar: t.exposeString("avatar", { nullable: true }),
    banner: t.exposeString("banner", { nullable: true }),
    photo: t.exposeString("photo", { nullable: true }),
    email_verified: t.exposeBoolean("email_verified"),
    date_created: t.expose("date_created", { type: "DateTime" }),
  }),
});

export const VideoModelType = builder.objectRef<VideoModel>("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 }),
    description: t.exposeString("description", { nullable: true }),
  }),
});

export const VideoFileType = builder.objectRef<VideoFile>("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 }),
  }),
});

export const VideoType = builder.objectRef<Video>("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 ModelPhotoType = builder.objectRef<ModelPhoto>("ModelPhoto").implement({
  fields: (t) => ({
    id: t.exposeString("id"),
    filename: t.exposeString("filename"),
  }),
});

export const ModelType = builder.objectRef<Model>("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 }),
    photo: t.exposeString("photo", { 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 ArticleType = builder.objectRef<Article>("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: VideoModelType, nullable: true }),
  }),
});

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

export const CommentType = builder.objectRef<Comment>("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 StatsType = builder.objectRef<Stats>("Stats").implement({
  fields: (t) => ({
    videos_count: t.exposeInt("videos_count"),
    models_count: t.exposeInt("models_count"),
    viewers_count: t.exposeInt("viewers_count"),
  }),
});

export const RecordingType = builder.objectRef<Recording>("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 }),
  }),
});

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

export const VideoPlayResponseType = builder
  .objectRef<VideoPlayResponse>("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<VideoLikeStatus>("VideoLikeStatus").implement({
  fields: (t) => ({
    liked: t.exposeBoolean("liked"),
  }),
});

export const VideoAnalyticsType = builder.objectRef<VideoAnalytics>("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"),
  }),
});

export const AnalyticsType = builder.objectRef<Analytics>("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 LeaderboardEntryType = builder
  .objectRef<LeaderboardEntry>("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 UserStatsType = builder.objectRef<UserStats>("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<UserAchievement>("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<RecentPoint>("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 }),
  }),
});

export const UserGamificationType = builder
  .objectRef<UserGamification>("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 AchievementType = builder.objectRef<Achievement>("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"),
  }),
});

// --- Queue / Job types (admin only, not in shared types package) ---

type JobCounts = {
  waiting: number;
  active: number;
  completed: number;
  failed: number;
  delayed: number;
  paused: number;
};

type JobData = {
  id: string;
  name: string;
  queue: string;
  status: string;
  data: unknown;
  result: unknown;
  failedReason: string | null;
  attemptsMade: number;
  createdAt: Date;
  processedAt: Date | null;
  finishedAt: Date | null;
  progress: number | null;
};

type QueueInfoData = {
  name: string;
  counts: JobCounts;
  isPaused: boolean;
};

export const JobCountsType = builder.objectRef<JobCounts>("JobCounts").implement({
  fields: (t) => ({
    waiting: t.exposeInt("waiting"),
    active: t.exposeInt("active"),
    completed: t.exposeInt("completed"),
    failed: t.exposeInt("failed"),
    delayed: t.exposeInt("delayed"),
    paused: t.exposeInt("paused"),
  }),
});

export const JobType = builder.objectRef<JobData>("Job").implement({
  fields: (t) => ({
    id: t.exposeString("id"),
    name: t.exposeString("name"),
    queue: t.exposeString("queue"),
    status: t.exposeString("status"),
    data: t.expose("data", { type: "JSON" }),
    result: t.expose("result", { type: "JSON", nullable: true }),
    failedReason: t.exposeString("failedReason", { nullable: true }),
    attemptsMade: t.exposeInt("attemptsMade"),
    createdAt: t.expose("createdAt", { type: "DateTime" }),
    processedAt: t.expose("processedAt", { type: "DateTime", nullable: true }),
    finishedAt: t.expose("finishedAt", { type: "DateTime", nullable: true }),
    progress: t.exposeFloat("progress", { nullable: true }),
  }),
});

export const QueueInfoType = builder.objectRef<QueueInfoData>("QueueInfo").implement({
  fields: (t) => ({
    name: t.exposeString("name"),
    counts: t.expose("counts", { type: JobCountsType }),
    isPaused: t.exposeBoolean("isPaused"),
  }),
});

export const VideoListType = builder
  .objectRef<{ items: Video[]; total: number }>("VideoList")
  .implement({
    fields: (t) => ({
      items: t.expose("items", { type: [VideoType] }),
      total: t.exposeInt("total"),
    }),
  });

export const ArticleListType = builder
  .objectRef<{ items: Article[]; total: number }>("ArticleList")
  .implement({
    fields: (t) => ({
      items: t.expose("items", { type: [ArticleType] }),
      total: t.exposeInt("total"),
    }),
  });

export const ModelListType = builder
  .objectRef<{ items: Model[]; total: number }>("ModelList")
  .implement({
    fields: (t) => ({
      items: t.expose("items", { type: [ModelType] }),
      total: t.exposeInt("total"),
    }),
  });

export const AdminVideoListType = builder
  .objectRef<{ items: Video[]; total: number }>("AdminVideoList")
  .implement({
    fields: (t) => ({
      items: t.expose("items", { type: [VideoType] }),
      total: t.exposeInt("total"),
    }),
  });

export const AdminArticleListType = builder
  .objectRef<{ items: Article[]; total: number }>("AdminArticleList")
  .implement({
    fields: (t) => ({
      items: t.expose("items", { type: [ArticleType] }),
      total: t.exposeInt("total"),
    }),
  });

export const AdminCommentListType = builder
  .objectRef<{ items: Comment[]; total: number }>("AdminCommentList")
  .implement({
    fields: (t) => ({
      items: t.expose("items", { type: [CommentType] }),
      total: t.exposeInt("total"),
    }),
  });

export const AdminRecordingListType = builder
  .objectRef<{ items: Recording[]; total: number }>("AdminRecordingList")
  .implement({
    fields: (t) => ({
      items: t.expose("items", { type: [RecordingType] }),
      total: t.exposeInt("total"),
    }),
  });

export const AdminUserListType = builder
  .objectRef<{ items: User[]; total: number }>("AdminUserList")
  .implement({
    fields: (t) => ({
      items: t.expose("items", { type: [UserType] }),
      total: t.exposeInt("total"),
    }),
  });

export const AdminUserDetailType = builder.objectRef<AdminUserDetail>("AdminUserDetail").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"),
    is_admin: t.exposeBoolean("is_admin"),
    avatar: t.exposeString("avatar", { nullable: true }),
    banner: t.exposeString("banner", { nullable: true }),
    photo: t.exposeString("photo", { nullable: true }),
    email_verified: t.exposeBoolean("email_verified"),
    date_created: t.expose("date_created", { type: "DateTime" }),
    photos: t.expose("photos", { type: [ModelPhotoType] }),
  }),
});
