//! SQLite error handling
//!
//! Maps SQLite error codes to Zig errors for idiomatic error handling.

const c = @import("c.zig").c;

/// SQLite error codes mapped to Zig errors
pub const Error = error{
    /// Generic error
    SqliteError,
    /// Internal logic error in SQLite
    InternalError,
    /// Access permission denied
    PermissionDenied,
    /// Callback routine requested an abort
    Abort,
    /// The database file is locked
    Busy,
    /// A table in the database is locked
    Locked,
    /// A malloc() failed
    OutOfMemory,
    /// Attempt to write a readonly database
    ReadOnly,
    /// Operation terminated by sqlite3_interrupt()
    Interrupt,
    /// Some kind of disk I/O error occurred
    IoError,
    /// The database disk image is malformed
    Corrupt,
    /// Unknown opcode in sqlite3_file_control()
    NotFound,
    /// Insertion failed because database is full
    Full,
    /// Unable to open the database file
    CantOpen,
    /// Database lock protocol error
    Protocol,
    /// Internal use only
    Empty,
    /// The database schema changed
    Schema,
    /// String or BLOB exceeds size limit
    TooBig,
    /// Abort due to constraint violation
    Constraint,
    /// Data type mismatch
    Mismatch,
    /// Library used incorrectly
    Misuse,
    /// Uses OS features not supported on host
    NoLfs,
    /// Authorization denied
    Auth,
    /// Not used
    Format,
    /// Parameter out of range
    Range,
    /// File opened that is not a database file
    NotADatabase,
    /// Notifications from sqlite3_log()
    Notice,
    /// Warnings from sqlite3_log()
    Warning,
    /// sqlite3_step() has another row ready
    Row,
    /// sqlite3_step() has finished executing
    Done,
};

/// Converts a SQLite result code to a Zig error
pub fn resultToError(result: c_int) Error {
    return switch (result) {
        c.SQLITE_ERROR => Error.SqliteError,
        c.SQLITE_INTERNAL => Error.InternalError,
        c.SQLITE_PERM => Error.PermissionDenied,
        c.SQLITE_ABORT => Error.Abort,
        c.SQLITE_BUSY => Error.Busy,
        c.SQLITE_LOCKED => Error.Locked,
        c.SQLITE_NOMEM => Error.OutOfMemory,
        c.SQLITE_READONLY => Error.ReadOnly,
        c.SQLITE_INTERRUPT => Error.Interrupt,
        c.SQLITE_IOERR => Error.IoError,
        c.SQLITE_CORRUPT => Error.Corrupt,
        c.SQLITE_NOTFOUND => Error.NotFound,
        c.SQLITE_FULL => Error.Full,
        c.SQLITE_CANTOPEN => Error.CantOpen,
        c.SQLITE_PROTOCOL => Error.Protocol,
        c.SQLITE_EMPTY => Error.Empty,
        c.SQLITE_SCHEMA => Error.Schema,
        c.SQLITE_TOOBIG => Error.TooBig,
        c.SQLITE_CONSTRAINT => Error.Constraint,
        c.SQLITE_MISMATCH => Error.Mismatch,
        c.SQLITE_MISUSE => Error.Misuse,
        c.SQLITE_NOLFS => Error.NoLfs,
        c.SQLITE_AUTH => Error.Auth,
        c.SQLITE_FORMAT => Error.Format,
        c.SQLITE_RANGE => Error.Range,
        c.SQLITE_NOTADB => Error.NotADatabase,
        c.SQLITE_NOTICE => Error.Notice,
        c.SQLITE_WARNING => Error.Warning,
        c.SQLITE_ROW => Error.Row,
        c.SQLITE_DONE => Error.Done,
        else => Error.SqliteError,
    };
}

/// Returns a human-readable description for an error
pub fn errorDescription(err: Error) []const u8 {
    return switch (err) {
        Error.SqliteError => "Generic SQLite error",
        Error.InternalError => "Internal logic error in SQLite",
        Error.PermissionDenied => "Access permission denied",
        Error.Abort => "Callback routine requested an abort",
        Error.Busy => "The database file is locked",
        Error.Locked => "A table in the database is locked",
        Error.OutOfMemory => "A malloc() failed",
        Error.ReadOnly => "Attempt to write a readonly database",
        Error.Interrupt => "Operation terminated by sqlite3_interrupt()",
        Error.IoError => "Some kind of disk I/O error occurred",
        Error.Corrupt => "The database disk image is malformed",
        Error.NotFound => "Unknown opcode in sqlite3_file_control()",
        Error.Full => "Insertion failed because database is full",
        Error.CantOpen => "Unable to open the database file",
        Error.Protocol => "Database lock protocol error",
        Error.Empty => "Internal use only",
        Error.Schema => "The database schema changed",
        Error.TooBig => "String or BLOB exceeds size limit",
        Error.Constraint => "Abort due to constraint violation",
        Error.Mismatch => "Data type mismatch",
        Error.Misuse => "Library used incorrectly",
        Error.NoLfs => "Uses OS features not supported on host",
        Error.Auth => "Authorization denied",
        Error.Format => "Not used",
        Error.Range => "Parameter out of range",
        Error.NotADatabase => "File opened that is not a database file",
        Error.Notice => "Notifications from sqlite3_log()",
        Error.Warning => "Warnings from sqlite3_log()",
        Error.Row => "sqlite3_step() has another row ready",
        Error.Done => "sqlite3_step() has finished executing",
    };
}
