import { eq, or, inArray, type Db, projects, teamMembers } from '@mosaicstack/db';

export type Project = typeof projects.$inferSelect;
export type NewProject = typeof projects.$inferInsert;

export function createProjectsRepo(db: Db) {
  return {
    async findAll(): Promise<Project[]> {
      return db.select().from(projects);
    },

    /**
     * Return only the projects visible to a given user:
     *   – projects directly owned by the user (ownerType = 'user', ownerId = userId), OR
     *   – projects owned by a team the user belongs to (ownerType = 'team', teamId IN user's teams)
     */
    async findAllForUser(userId: string): Promise<Project[]> {
      // Fetch the team IDs the user is a member of.
      const memberRows = await db
        .select({ teamId: teamMembers.teamId })
        .from(teamMembers)
        .where(eq(teamMembers.userId, userId));

      const teamIds = memberRows.map((r) => r.teamId);

      if (teamIds.length === 0) {
        // No team memberships — return only directly owned projects.
        return db.select().from(projects).where(eq(projects.ownerId, userId));
      }

      return db
        .select()
        .from(projects)
        .where(or(eq(projects.ownerId, userId), inArray(projects.teamId, teamIds)));
    },

    async findById(id: string): Promise<Project | undefined> {
      const rows = await db.select().from(projects).where(eq(projects.id, id));
      return rows[0];
    },

    async create(data: NewProject): Promise<Project> {
      const rows = await db.insert(projects).values(data).returning();
      return rows[0]!;
    },

    async update(id: string, data: Partial<NewProject>): Promise<Project | undefined> {
      const rows = await db
        .update(projects)
        .set({ ...data, updatedAt: new Date() })
        .where(eq(projects.id, id))
        .returning();
      return rows[0];
    },

    async remove(id: string): Promise<boolean> {
      const rows = await db.delete(projects).where(eq(projects.id, id)).returning();
      return rows.length > 0;
    },
  };
}

export type ProjectsRepo = ReturnType<typeof createProjectsRepo>;
