-- Manga metadata: status, alternative titles, normalized authors,
-- curated genres, and user-extensible tags. Each new concept gets its
-- own table joined to mangas rather than being jammed onto the mangas
-- row, in line with the extension philosophy in 0001_init.sql.

-- 1. Inline columns: status (curated enum-like) and alt_titles (array).
ALTER TABLE mangas
    ADD COLUMN status text NOT NULL DEFAULT 'ongoing'
        CHECK (status IN ('ongoing', 'completed')),
    ADD COLUMN alt_titles text[] NOT NULL DEFAULT '{}';

-- 2. Authors: normalized so an author page can list works.
--    Display name preserves casing; lookups go through lower(name) for
--    case-insensitive de-dup. Trigram index supports autocomplete.
CREATE TABLE authors (
    id          uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    name        text NOT NULL,
    created_at  timestamptz NOT NULL DEFAULT now()
);
CREATE UNIQUE INDEX authors_name_lower_uniq ON authors (lower(name));
CREATE INDEX authors_name_trgm_idx ON authors USING gin (name gin_trgm_ops);

CREATE TABLE manga_authors (
    manga_id   uuid NOT NULL REFERENCES mangas(id) ON DELETE CASCADE,
    author_id  uuid NOT NULL REFERENCES authors(id) ON DELETE CASCADE,
    position   integer NOT NULL DEFAULT 0,
    PRIMARY KEY (manga_id, author_id)
);
CREATE INDEX manga_authors_author_idx ON manga_authors (author_id);

-- 3. Genres: curated controlled vocabulary, seeded below. Uploaders
--    pick from this list; users do not add new genres (that's what
--    tags are for).
CREATE TABLE genres (
    id    uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    name  text NOT NULL UNIQUE
);

INSERT INTO genres (name) VALUES
    ('Action'),
    ('Adventure'),
    ('Comedy'),
    ('Drama'),
    ('Fantasy'),
    ('Horror'),
    ('Mystery'),
    ('Romance'),
    ('Sci-Fi'),
    ('Slice of Life'),
    ('Sports'),
    ('Supernatural'),
    ('Thriller')
ON CONFLICT DO NOTHING;

CREATE TABLE manga_genres (
    manga_id  uuid NOT NULL REFERENCES mangas(id) ON DELETE CASCADE,
    genre_id  uuid NOT NULL REFERENCES genres(id) ON DELETE CASCADE,
    PRIMARY KEY (manga_id, genre_id)
);
CREATE INDEX manga_genres_genre_idx ON manga_genres (genre_id);

-- 4. Tags: free-form but globally shared. Any signed-in user can
--    attach a tag to a manga — creating the tag if new. `added_by`
--    records the attacher so the UI can show a remove button only to
--    them. ON DELETE SET NULL keeps the tag intact if the user leaves.
CREATE TABLE tags (
    id          uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    name        text NOT NULL,
    created_at  timestamptz NOT NULL DEFAULT now()
);
CREATE UNIQUE INDEX tags_name_lower_uniq ON tags (lower(name));
CREATE INDEX tags_name_trgm_idx ON tags USING gin (name gin_trgm_ops);

CREATE TABLE manga_tags (
    manga_id    uuid NOT NULL REFERENCES mangas(id) ON DELETE CASCADE,
    tag_id      uuid NOT NULL REFERENCES tags(id) ON DELETE CASCADE,
    added_by    uuid REFERENCES users(id) ON DELETE SET NULL,
    created_at  timestamptz NOT NULL DEFAULT now(),
    PRIMARY KEY (manga_id, tag_id)
);
CREATE INDEX manga_tags_tag_idx ON manga_tags (tag_id);

-- 5. Backfill the existing single `author` column into the normalized
--    tables. Trim whitespace; skip blanks. After backfill, drop the
--    trigram index on the old column and then drop the column itself.
INSERT INTO authors (name)
    SELECT DISTINCT trim(author)
      FROM mangas
     WHERE author IS NOT NULL
       AND trim(author) <> ''
ON CONFLICT (lower(name)) DO NOTHING;

INSERT INTO manga_authors (manga_id, author_id, position)
    SELECT m.id, a.id, 0
      FROM mangas m
      JOIN authors a ON lower(a.name) = lower(trim(m.author))
     WHERE m.author IS NOT NULL
       AND trim(m.author) <> ''
ON CONFLICT DO NOTHING;

DROP INDEX IF EXISTS mangas_author_trgm_idx;
ALTER TABLE mangas DROP COLUMN author;
