const db = require('./DataBaseConnection');
const DateTime = require('../DateTime');

class AnimeRepository {
    constructor() {
        this.db = db.getConnection();
    }

    async GetAll(user, group = null, status = null) {
        try {
            const sql =  `
                SELECT 
                    anm_animes.an_id,
                    anm_animes.an_title,
                    anm_animes.an_date,
                    COALESCE(anm_favorites.fv_episode, 1) AS fv_episode,
                    COALESCE(anm_favorites.fv_state, 0) AS fv_state,
                    COALESCE(anm_segregated.st_group, 0) AS st_group,
                    anm_animes.an_url,
                    anm_animes.an_episodes,
                    anm_animes.an_miniature
                FROM anm_animes
                LEFT JOIN anm_favorites ON anm_animes.an_id = anm_favorites.fv_anime AND anm_favorites.fv_user=?
                LEFT JOIN anm_segregated ON anm_animes.an_id = anm_segregated.st_anime AND anm_segregated.st_user=?
                WHERE anm_animes.an_user=?
                AND (anm_segregated.st_group=? OR ? IS NULL)
                AND (anm_favorites.fv_state=? OR ? IS NULL);
                `;
    
            const [rows] = await this.db.execute(sql, [user, user, user, group, group, status, status]);
        
            return rows;
        }
        catch(e) {
            console.error(e);
            return null;
        }
    }

    async GetDescription(id, user) {
        try {
            const sql = `
                SELECT
                    anm_animes.an_title,
                    anm_animes.an_episodes,
                    COALESCE(anm_descriptions.ds_description, NULL) AS ds_description,
                    COALESCE(anm_descriptions.ds_poster, NULL) AS ds_poster
                FROM anm_animes
                LEFT JOIN anm_descriptions ON anm_animes.an_id = anm_descriptions.ds_anime
                WHERE anm_animes.an_id=? AND anm_animes.an_user=?;
            `;
    
            const [rows] = await this.db.execute(sql, [id, user]);
    
            return rows[0];
        }
        catch(e) {
            console.error(e);
            return null;
        }
    }

    async Delete(anime, user) {
        try {
            const _anime = Array.isArray(anime) ? anime.map(Number) : [Number(anime)];

            if (_anime.some(isNaN)) {
                throw new Error("ANIME REPO: Nieprawidłowa wartość w anime");
            }

            const placeholder = _anime.map(() => '?').join(',');

            const sql = `DELETE FROM anm_animes WHERE an_id IN (${placeholder}) AND an_user = ?;`;
            const [result] = await this.db.execute(sql, [..._anime, user]);
    
            return result.affectedRows;
        }
        catch(e) {
            console.error(`ERROR: Nie można skasować rekordów Anime: ${e}`);
            return -1;
        }
    }

    async Update(data) {
        try {
            const sql = `
                UPDATE anm_animes
                SET
                    an_title = ?,
                    an_url = ?,
                    an_episodes = ?,
                    an_miniature = IF(?, ?, an_miniature)
                WHERE
                    an_id = ?
                AND
                    an_user = ?;
            `;

            const [rows] = await this.db.execute(sql, [
                data.title, 
                data.url, 
                data.episodes, 

                //Aktualizacja miniaturki
                data.updateMiniature,
                data.miniature,
                
                //Wskazanie indexu recordu
                data.id,
                data.user
            ]);

            return rows;
        }
        catch(e) {
            console.error(`ERROR QUERY ANIME UPDATE: Nie udało się zaktualizaować rekordu ${e}`);

            return null;
        }
    }

    // Dodaj nowe anime do bazydanech
    async Add(anime, blob, user) {
        try {
            const sql = `
                INSERT INTO anm_animes (
                    an_date, 
                    an_title, 
                    an_url, 
                    an_episodes,
                    an_user,
                    an_miniature,
                    ) VALUES (?, ?, ?, ?, ?, ?);
            `;

            const today = DateTime.GetDateNow();
            const [result] = await this.db.execute(sql, [
                today,
                anime.title,
                anime.url,
                anime.episodes,
                user,
                blob.miniature
            ]);

            return result.insertId;
        }
        catch(e){
            console.error(`ERROR! Nie udało się dodać anime do bazy danych: ${e}`);
            return null;
        }
    }

    // Dodaj opis do bazy danych
    async AddDescription(data) {
        try {
            const sql = `
                INSERT INTO anm_descriptions (
                    ds_anime,
                    ds_description,
                    ds_poster
                ) VALUES (?, ?, ?);
            `;

            const [rows] = await this.db.execute(sql, [
                data.anime,
                data.description,
                data.poster
            ]);

            return rows[0];
        }
        catch(e) {
            console.error(`ERROR: Nie udało się dodać opisu: ${e}`);
            return null;
        }
    }

    // Edytuj opis
    async EditDescription(data) {
        try {
            const sql = `
                UPDATE anm_descriptions
                SET
                    ds_description = ?,
                    ds_poster = IF(?, ?, ds_poster)
                WHERE ds_anime = ?;
            `;

            const [rows] = await this.db.execute(sql, [
                data.description,

                //Warunkowa aktualizacja grafiki
                data.posterUpdate,
                data.poster,

                data.anime
            ]);

            return rows[0];
        }
        catch(e) {
            console.error(`ERROR: Nie udało się dodać opisu: ${e}`);
            return null;
        }
    }

    // Skasuj opis
    async DeleteDescription(anime) {
        try {
            const sql = `DELETE FROM anm_descriptions WHERE ds_anime = ?;`;
            const [rows] = await this.db.execute(sql, [anime]);

            return rows[0];
        }
        catch(e) {
            console.error(`ERROR: Nie udało się skasować opisu: ${e}`);
            return null;
        }
    }

    // Pobierz konkretny rekord anime
    async GetRecord(id, user) {
        try {
            const sql = `
                SELECT
                    anm_animes.an_title,
                    anm_animes.an_url,
                    anm_animes.an_episodes,
                    COALESCE(anm_descriptions.ds_description, NULL) AS ds_description,
                    COALESCE(anm_descriptions.ds_poster, NULL) AS ds_poster
                FROM anm_animes
                LEFT JOIN anm_descriptions ON anm_animes.an_id = anm_descriptions.ds_anime
                WHERE anm_animes.an_id = ? AND anm_animes.an_user = ?;
            `;

            const [rows] = await this.db.execute(sql, [id, user]);
            return rows[0];
        }
        catch(e) {
            console.error(`ERROR: Nie udało się pobrać recordu: ${e}`);
            return null;
        }
    }
}

module.exports = new AnimeRepository();