CREATE EXTENSION IF NOT EXISTS "pgcrypto";

CREATE TYPE "DevicePlatform" AS ENUM ('MACOS', 'IPHONE');
CREATE TYPE "TrackStatus" AS ENUM ('ACTIVE', 'DELETED');
CREATE TYPE "UploadSessionStatus" AS ENUM ('PENDING', 'READY_TO_UPLOAD', 'COMPLETED', 'FAILED');
CREATE TYPE "EntityType" AS ENUM ('TRACK', 'AUDIO_ASSET', 'ARTWORK_ASSET');
CREATE TYPE "EventAction" AS ENUM ('CREATED', 'UPDATED', 'DELETED');

CREATE TABLE "devices" (
    "id" UUID NOT NULL DEFAULT gen_random_uuid(),
    "platform" "DevicePlatform" NOT NULL,
    "device_name" TEXT NOT NULL,
    "app_version" TEXT NOT NULL,
    "install_token_hash" TEXT NOT NULL,
    "last_seen_at" TIMESTAMP(3) NOT NULL,
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT "devices_pkey" PRIMARY KEY ("id")
);

CREATE TABLE "tracks" (
    "id" UUID NOT NULL DEFAULT gen_random_uuid(),
    "primary_audio_asset_id" UUID,
    "artwork_asset_id" UUID,
    "title" TEXT NOT NULL,
    "artist" TEXT NOT NULL,
    "album" TEXT,
    "album_artist" TEXT,
    "genre" TEXT,
    "disc_number" INTEGER,
    "track_number" INTEGER,
    "year" INTEGER,
    "duration_ms" INTEGER,
    "status" "TrackStatus" NOT NULL DEFAULT 'ACTIVE',
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "deleted_at" TIMESTAMP(3),
    CONSTRAINT "tracks_pkey" PRIMARY KEY ("id")
);

CREATE TABLE "audio_assets" (
    "id" UUID NOT NULL DEFAULT gen_random_uuid(),
    "track_id" UUID,
    "sha256" TEXT NOT NULL,
    "storage_key" TEXT NOT NULL,
    "original_filename" TEXT NOT NULL,
    "mime_type" TEXT NOT NULL,
    "file_extension" TEXT NOT NULL,
    "file_size_bytes" BIGINT NOT NULL,
    "bit_rate_kbps" INTEGER,
    "sample_rate_hz" INTEGER,
    "channels" INTEGER,
    "duration_ms" INTEGER,
    "source_device_id" UUID,
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT "audio_assets_pkey" PRIMARY KEY ("id")
);

CREATE TABLE "artwork_assets" (
    "id" UUID NOT NULL DEFAULT gen_random_uuid(),
    "sha256" TEXT NOT NULL,
    "storage_key" TEXT NOT NULL,
    "mime_type" TEXT NOT NULL,
    "width" INTEGER,
    "height" INTEGER,
    "file_size_bytes" BIGINT NOT NULL,
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT "artwork_assets_pkey" PRIMARY KEY ("id")
);

CREATE TABLE "upload_sessions" (
    "id" UUID NOT NULL DEFAULT gen_random_uuid(),
    "device_id" UUID NOT NULL,
    "expected_sha256" TEXT NOT NULL,
    "expected_size_bytes" BIGINT NOT NULL,
    "received_bytes" BIGINT NOT NULL DEFAULT 0,
    "temp_storage_path" TEXT NOT NULL,
    "status" "UploadSessionStatus" NOT NULL DEFAULT 'PENDING',
    "expires_at" TIMESTAMP(3) NOT NULL,
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT "upload_sessions_pkey" PRIMARY KEY ("id")
);

CREATE TABLE "library_events" (
    "id" BIGSERIAL NOT NULL,
    "entity_type" "EntityType" NOT NULL,
    "entity_id" UUID NOT NULL,
    "action" "EventAction" NOT NULL,
    "payload_version" INTEGER NOT NULL DEFAULT 1,
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT "library_events_pkey" PRIMARY KEY ("id")
);

CREATE TABLE "device_sync_cursors" (
    "device_id" UUID NOT NULL,
    "last_event_id" BIGINT NOT NULL DEFAULT 0,
    "last_full_sync_at" TIMESTAMP(3),
    "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT "device_sync_cursors_pkey" PRIMARY KEY ("device_id")
);

CREATE UNIQUE INDEX "tracks_primary_audio_asset_id_key" ON "tracks"("primary_audio_asset_id");
CREATE UNIQUE INDEX "tracks_artwork_asset_id_key" ON "tracks"("artwork_asset_id");
CREATE UNIQUE INDEX "audio_assets_sha256_key" ON "audio_assets"("sha256");
CREATE UNIQUE INDEX "audio_assets_storage_key" ON "audio_assets"("storage_key");
CREATE UNIQUE INDEX "artwork_assets_sha256_key" ON "artwork_assets"("sha256");
CREATE UNIQUE INDEX "artwork_assets_storage_key" ON "artwork_assets"("storage_key");

ALTER TABLE "audio_assets"
  ADD CONSTRAINT "audio_assets_track_id_fkey"
  FOREIGN KEY ("track_id") REFERENCES "tracks"("id")
  ON DELETE SET NULL ON UPDATE CASCADE;

ALTER TABLE "audio_assets"
  ADD CONSTRAINT "audio_assets_source_device_id_fkey"
  FOREIGN KEY ("source_device_id") REFERENCES "devices"("id")
  ON DELETE SET NULL ON UPDATE CASCADE;

ALTER TABLE "tracks"
  ADD CONSTRAINT "tracks_primary_audio_asset_id_fkey"
  FOREIGN KEY ("primary_audio_asset_id") REFERENCES "audio_assets"("id")
  ON DELETE SET NULL ON UPDATE CASCADE;

ALTER TABLE "tracks"
  ADD CONSTRAINT "tracks_artwork_asset_id_fkey"
  FOREIGN KEY ("artwork_asset_id") REFERENCES "artwork_assets"("id")
  ON DELETE SET NULL ON UPDATE CASCADE;

ALTER TABLE "upload_sessions"
  ADD CONSTRAINT "upload_sessions_device_id_fkey"
  FOREIGN KEY ("device_id") REFERENCES "devices"("id")
  ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE "device_sync_cursors"
  ADD CONSTRAINT "device_sync_cursors_device_id_fkey"
  FOREIGN KEY ("device_id") REFERENCES "devices"("id")
  ON DELETE CASCADE ON UPDATE CASCADE;
