CREATE TYPE monitor_state AS ENUM ('monitored', 'unmonitored', 'excluded');

CREATE TABLE artists (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    external_id     VARCHAR(255) NOT NULL UNIQUE,
    name            VARCHAR(500) NOT NULL,
    artist_type     VARCHAR(50),
    country         VARCHAR(10),
    genres          TEXT[],
    image_url       TEXT,
    monitor_state   monitor_state NOT NULL DEFAULT 'unmonitored',
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE albums (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    external_id     VARCHAR(255) NOT NULL UNIQUE,
    artist_id       UUID NOT NULL REFERENCES artists(id) ON DELETE CASCADE,
    title           VARCHAR(500) NOT NULL,
    album_type      VARCHAR(50),
    release_date    DATE,
    total_tracks    INT,
    total_discs     INT DEFAULT 1,
    label           VARCHAR(255),
    genres          TEXT[],
    cover_url       TEXT,
    monitor_state   monitor_state NOT NULL DEFAULT 'unmonitored',
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_albums_artist ON albums(artist_id);
CREATE INDEX idx_albums_monitored ON albums(monitor_state) WHERE monitor_state = 'monitored';

CREATE TABLE tracks (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    external_id     VARCHAR(255) NOT NULL UNIQUE,
    album_id        UUID NOT NULL REFERENCES albums(id) ON DELETE CASCADE,
    title           VARCHAR(500) NOT NULL,
    duration_ms     INT,
    isrc            VARCHAR(20),
    disc_number     INT DEFAULT 1,
    track_number    INT NOT NULL,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_tracks_album ON tracks(album_id);

CREATE TABLE torrents (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    album_id        UUID NOT NULL REFERENCES albums(id) ON DELETE CASCADE,
    info_hash       VARCHAR(40) NOT NULL UNIQUE,
    tracker         VARCHAR(100) NOT NULL,
    title           TEXT NOT NULL,
    format          VARCHAR(20) NOT NULL,
    quality         VARCHAR(20),
    source          VARCHAR(20),
    bit_depth       INT,
    sample_rate     INT,
    seeders         INT DEFAULT 0,
    peers           INT DEFAULT 0,
    size            BIGINT,
    track_count     INT,
    has_cover_art   BOOLEAN DEFAULT FALSE,
    has_cue_sheet   BOOLEAN DEFAULT FALSE,
    has_rip_log     BOOLEAN DEFAULT FALSE,
    download_link   TEXT,
    torrent_file    BYTEA,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_torrents_album ON torrents(album_id);
CREATE INDEX idx_torrents_album_format ON torrents(album_id, format);

CREATE TYPE download_state AS ENUM (
    'pending', 'downloading', 'completed', 'failed', 'seeding', 'paused'
);

CREATE TABLE downloads (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    torrent_id      UUID NOT NULL REFERENCES torrents(id) ON DELETE CASCADE,
    album_id        UUID NOT NULL,
    format          VARCHAR(20) NOT NULL,
    quality         VARCHAR(20),
    state           download_state NOT NULL DEFAULT 'pending',
    qbit_hash       VARCHAR(64),
    save_path       TEXT,
    error_message   TEXT,
    queued_at       TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    started_at      TIMESTAMPTZ,
    completed_at    TIMESTAMPTZ,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE UNIQUE INDEX idx_unique_active_torrent
    ON downloads(torrent_id)
    WHERE state NOT IN ('failed');

CREATE UNIQUE INDEX idx_unique_owned_album_quality
    ON downloads(album_id, format, quality)
    WHERE state IN ('completed', 'seeding');

CREATE INDEX idx_downloads_state ON downloads(state);
CREATE INDEX idx_downloads_album ON downloads(album_id);

CREATE TABLE download_files (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    download_id     UUID NOT NULL REFERENCES downloads(id) ON DELETE CASCADE,
    track_id        UUID REFERENCES tracks(id),
    file_path       TEXT NOT NULL,
    file_size       BIGINT NOT NULL,
    file_type       VARCHAR(20) NOT NULL,
    sha256_hash     VARCHAR(64),
    verified_at     TIMESTAMPTZ,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_download_files_download ON download_files(download_id);
CREATE INDEX idx_download_files_hash ON download_files(sha256_hash) WHERE sha256_hash IS NOT NULL;

CREATE TABLE album_releases (
    id                UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    album_id          UUID NOT NULL REFERENCES albums(id) ON DELETE CASCADE,
    download_id       UUID NOT NULL REFERENCES downloads(id) ON DELETE CASCADE,
    format            VARCHAR(20) NOT NULL,
    bit_depth         INT,
    sample_rate       INT,
    channels          INT DEFAULT 2,
    is_lossless       BOOLEAN NOT NULL DEFAULT FALSE,
    source            VARCHAR(20),
    total_size        BIGINT NOT NULL DEFAULT 0,
    total_duration_ms INT NOT NULL DEFAULT 0,
    track_count       INT NOT NULL DEFAULT 0,
    has_cover_art     BOOLEAN DEFAULT FALSE,
    has_cue_sheet     BOOLEAN DEFAULT FALSE,
    has_rip_log       BOOLEAN DEFAULT FALSE,
    path              TEXT NOT NULL,
    created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_album_releases_album ON album_releases(album_id);
CREATE UNIQUE INDEX idx_album_releases_download ON album_releases(download_id);

CREATE TABLE track_releases (
    id                  UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    album_release_id    UUID NOT NULL REFERENCES album_releases(id) ON DELETE CASCADE,
    track_id            UUID REFERENCES tracks(id),
    download_file_id    UUID REFERENCES download_files(id),
    title               VARCHAR(500) NOT NULL,
    track_number        INT NOT NULL DEFAULT 1,
    disc_number         INT NOT NULL DEFAULT 1,
    duration_ms         INT,
    format              VARCHAR(20) NOT NULL,
    bit_depth           INT,
    sample_rate         INT,
    channels            INT DEFAULT 2,
    bitrate_kbps        INT,
    file_size           BIGINT NOT NULL DEFAULT 0,
    file_path           TEXT NOT NULL,
    created_at          TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_track_releases_album_release ON track_releases(album_release_id);
