module attachment.data_impl_sqlite;

import handy_http_primitives : Optional;
import d2sqlite3;

import attachment.model;
import attachment.data;
import util.sqlite;

import std.datetime;
import std.format;

class SqliteAttachmentRepository : AttachmentRepository {
    private Database db;
    this(Database db) {
        this.db = db;
    }

    Optional!Attachment findById(ulong id) {
        return findOne(
            db,
            "SELECT * FROM attachment WHERE id = ?",
            &parseAttachment,
            id
        );
    }

    Attachment[] findAllByLinkedEntity(string subquery, ulong entityId) {
        const query = format!"SELECT * FROM attachment WHERE id IN (%s)"(subquery);
        return findAll(db, query, &parseAttachment, entityId);
    }
    
    ulong save(SysTime uploadedAt, string filename, string contentType, ubyte[] content) {
        util.sqlite.update(
            db,
            q"SQL
                INSERT INTO attachment
                (uploaded_at, filename, content_type, size, content)
                VALUES (?, ?, ?, ?, ?)
SQL",
            uploadedAt.toISOExtString(),
            filename,
            contentType,
            cast(ulong) content.length,
            content
        );
        return db.lastInsertRowid();
    }
    
    void remove(ulong id) {
        util.sqlite.update(
            db,
            "DELETE FROM attachment WHERE id = ?",
            id
        );
    }

    static Attachment parseAttachment(Row row) {
        return Attachment(
            row.peek!ulong(0),
            parseISOTimestamp(row, 1),
            row.peek!string(2),
            row.peek!string(3),
            row.peek!ulong(4),
            parseBlob(row, 5)
        );
    }
}
