CREATE TYPE "public"."library_mode" AS ENUM('reference', 'copy');--> statement-breakpoint CREATE TYPE "public"."playlist_visibility" AS ENUM('public', 'unlisted', 'private');--> statement-breakpoint CREATE TYPE "public"."track_status" AS ENUM('pending', 'approved', 'rejected');--> statement-breakpoint CREATE TABLE "albums" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "title" text NOT NULL, "artist_id" uuid, "mb_release_group_id" text, "mb_release_id" text, "release_date" text, "cover_url" text, "metadata" jsonb, "created_at" timestamp with time zone DEFAULT now() NOT NULL, "updated_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint CREATE TABLE "artist_follows" ( "user_id" uuid NOT NULL, "artist_id" uuid NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL, CONSTRAINT "artist_follows_user_id_artist_id_pk" PRIMARY KEY("user_id","artist_id") ); --> statement-breakpoint CREATE TABLE "artists" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "name" text NOT NULL, "sort_name" text, "mb_artist_id" text, "description" text, "image_url" text, "country" text, "metadata" jsonb, "created_at" timestamp with time zone DEFAULT now() NOT NULL, "updated_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint CREATE TABLE "comments" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "track_id" uuid NOT NULL, "user_id" uuid NOT NULL, "parent_id" uuid, "body" text NOT NULL, "deleted" boolean DEFAULT false NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL, "updated_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint CREATE TABLE "library_playlists" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "user_id" uuid NOT NULL, "playlist_id" uuid NOT NULL, "mode" "library_mode" DEFAULT 'reference' NOT NULL, "copied_playlist_id" uuid, "can_edit" boolean DEFAULT false NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint CREATE TABLE "playlist_collaborators" ( "playlist_id" uuid NOT NULL, "user_id" uuid NOT NULL, "can_edit" boolean DEFAULT true NOT NULL, CONSTRAINT "playlist_collaborators_playlist_id_user_id_pk" PRIMARY KEY("playlist_id","user_id") ); --> statement-breakpoint CREATE TABLE "playlist_tracks" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "playlist_id" uuid NOT NULL, "track_id" uuid NOT NULL, "position" integer DEFAULT 0 NOT NULL, "added_by_id" uuid, "created_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint CREATE TABLE "playlists" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "owner_id" uuid NOT NULL, "title" text NOT NULL, "description" text, "cover_url" text, "visibility" "playlist_visibility" DEFAULT 'private' NOT NULL, "is_shareable" boolean DEFAULT false NOT NULL, "allow_collaborator_edit" boolean DEFAULT true NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL, "updated_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint CREATE TABLE "track_likes" ( "user_id" uuid NOT NULL, "track_id" uuid NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL, CONSTRAINT "track_likes_user_id_track_id_pk" PRIMARY KEY("user_id","track_id") ); --> statement-breakpoint CREATE TABLE "tracks" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "title" text NOT NULL, "artist_id" uuid, "album_id" uuid, "duration_ms" integer, "track_number" integer, "disc_number" integer, "release_date" text, "lyrics_plain" text, "lyrics_synced" jsonb, "lyrics_source" text, "file_key" text NOT NULL, "file_size" bigint, "mime_type" text, "uploaded_by_id" uuid, "status" "track_status" DEFAULT 'pending' NOT NULL, "rejection_reason" text, "fingerprint" text, "mb_recording_id" text, "cover_url" text, "play_count" integer DEFAULT 0 NOT NULL, "metadata" jsonb, "created_at" timestamp with time zone DEFAULT now() NOT NULL, "updated_at" timestamp with time zone DEFAULT now() NOT NULL, "approved_at" timestamp with time zone ); --> statement-breakpoint CREATE TABLE "users" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "email" text NOT NULL, "username" text NOT NULL, "display_name" text, "password_hash" text NOT NULL, "avatar_url" text, "bio" text, "is_super_admin" boolean DEFAULT false NOT NULL, "permissions" jsonb DEFAULT '{"canCreatePlaylists":true,"canUploadTracks":true,"canAutoApprove":false,"canModerate":false,"canManageUsers":false,"canManageLibrary":false,"canViewAllPlaylists":false}'::jsonb NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL, "updated_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint ALTER TABLE "albums" ADD CONSTRAINT "albums_artist_id_artists_id_fk" FOREIGN KEY ("artist_id") REFERENCES "public"."artists"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint ALTER TABLE "artist_follows" ADD CONSTRAINT "artist_follows_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "artist_follows" ADD CONSTRAINT "artist_follows_artist_id_artists_id_fk" FOREIGN KEY ("artist_id") REFERENCES "public"."artists"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "comments" ADD CONSTRAINT "comments_track_id_tracks_id_fk" FOREIGN KEY ("track_id") REFERENCES "public"."tracks"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "comments" ADD CONSTRAINT "comments_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "comments" ADD CONSTRAINT "comments_parent_id_comments_id_fk" FOREIGN KEY ("parent_id") REFERENCES "public"."comments"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "library_playlists" ADD CONSTRAINT "library_playlists_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "library_playlists" ADD CONSTRAINT "library_playlists_playlist_id_playlists_id_fk" FOREIGN KEY ("playlist_id") REFERENCES "public"."playlists"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "library_playlists" ADD CONSTRAINT "library_playlists_copied_playlist_id_playlists_id_fk" FOREIGN KEY ("copied_playlist_id") REFERENCES "public"."playlists"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint ALTER TABLE "playlist_collaborators" ADD CONSTRAINT "playlist_collaborators_playlist_id_playlists_id_fk" FOREIGN KEY ("playlist_id") REFERENCES "public"."playlists"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "playlist_collaborators" ADD CONSTRAINT "playlist_collaborators_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "playlist_tracks" ADD CONSTRAINT "playlist_tracks_playlist_id_playlists_id_fk" FOREIGN KEY ("playlist_id") REFERENCES "public"."playlists"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "playlist_tracks" ADD CONSTRAINT "playlist_tracks_track_id_tracks_id_fk" FOREIGN KEY ("track_id") REFERENCES "public"."tracks"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "playlist_tracks" ADD CONSTRAINT "playlist_tracks_added_by_id_users_id_fk" FOREIGN KEY ("added_by_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint ALTER TABLE "playlists" ADD CONSTRAINT "playlists_owner_id_users_id_fk" FOREIGN KEY ("owner_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "track_likes" ADD CONSTRAINT "track_likes_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "track_likes" ADD CONSTRAINT "track_likes_track_id_tracks_id_fk" FOREIGN KEY ("track_id") REFERENCES "public"."tracks"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "tracks" ADD CONSTRAINT "tracks_artist_id_artists_id_fk" FOREIGN KEY ("artist_id") REFERENCES "public"."artists"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint ALTER TABLE "tracks" ADD CONSTRAINT "tracks_album_id_albums_id_fk" FOREIGN KEY ("album_id") REFERENCES "public"."albums"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint ALTER TABLE "tracks" ADD CONSTRAINT "tracks_uploaded_by_id_users_id_fk" FOREIGN KEY ("uploaded_by_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint CREATE INDEX "albums_title_idx" ON "albums" USING btree ("title");--> statement-breakpoint CREATE UNIQUE INDEX "albums_mb_rg_idx" ON "albums" USING btree ("mb_release_group_id");--> statement-breakpoint CREATE INDEX "artists_name_idx" ON "artists" USING btree ("name");--> statement-breakpoint CREATE UNIQUE INDEX "artists_mb_idx" ON "artists" USING btree ("mb_artist_id");--> statement-breakpoint CREATE INDEX "comments_track_idx" ON "comments" USING btree ("track_id","created_at");--> statement-breakpoint CREATE INDEX "comments_parent_idx" ON "comments" USING btree ("parent_id");--> statement-breakpoint CREATE UNIQUE INDEX "library_playlists_uniq" ON "library_playlists" USING btree ("user_id","playlist_id");--> statement-breakpoint CREATE INDEX "library_playlists_user_idx" ON "library_playlists" USING btree ("user_id");--> statement-breakpoint CREATE INDEX "playlist_tracks_playlist_idx" ON "playlist_tracks" USING btree ("playlist_id","position");--> statement-breakpoint CREATE INDEX "playlist_tracks_track_idx" ON "playlist_tracks" USING btree ("track_id");--> statement-breakpoint CREATE INDEX "playlists_owner_idx" ON "playlists" USING btree ("owner_id");--> statement-breakpoint CREATE INDEX "playlists_visibility_idx" ON "playlists" USING btree ("visibility");--> statement-breakpoint CREATE INDEX "tracks_status_idx" ON "tracks" USING btree ("status");--> statement-breakpoint CREATE INDEX "tracks_title_idx" ON "tracks" USING btree ("title");--> statement-breakpoint CREATE INDEX "tracks_uploader_idx" ON "tracks" USING btree ("uploaded_by_id");--> statement-breakpoint CREATE INDEX "tracks_fingerprint_idx" ON "tracks" USING btree ("fingerprint");--> statement-breakpoint CREATE INDEX "tracks_mb_recording_idx" ON "tracks" USING btree ("mb_recording_id");--> statement-breakpoint CREATE UNIQUE INDEX "users_email_idx" ON "users" USING btree (lower("email"));--> statement-breakpoint CREATE UNIQUE INDEX "users_username_idx" ON "users" USING btree (lower("username"));