//! Basic example demonstrating zsqlite usage
//!
//! This example shows:
//! - Opening a database
//! - Creating tables
//! - Inserting data with prepared statements
//! - Querying data
//! - Transactions

const std = @import("std");
const sqlite = @import("zsqlite");

pub fn main() !void {
    std.debug.print("zsqlite basic example\n", .{});
    std.debug.print("SQLite version: {s}\n\n", .{sqlite.version()});

    // Open an in-memory database
    var db = try sqlite.openMemory();
    defer db.close();

    // Enable foreign keys (recommended)
    try db.setForeignKeys(true);

    // Create tables
    try db.exec(
        \\CREATE TABLE users (
        \\    id INTEGER PRIMARY KEY,
        \\    name TEXT NOT NULL,
        \\    email TEXT UNIQUE,
        \\    created_at TEXT DEFAULT CURRENT_TIMESTAMP
        \\);
        \\
        \\CREATE TABLE posts (
        \\    id INTEGER PRIMARY KEY,
        \\    user_id INTEGER NOT NULL REFERENCES users(id),
        \\    title TEXT NOT NULL,
        \\    content TEXT
        \\);
    );

    std.debug.print("Tables created successfully\n\n", .{});

    // Insert users with prepared statement
    {
        var stmt = try db.prepare("INSERT INTO users (name, email) VALUES (?, ?)");
        defer stmt.finalize();

        const users = [_][2][]const u8{
            .{ "Alice", "alice@example.com" },
            .{ "Bob", "bob@example.com" },
            .{ "Charlie", "charlie@example.com" },
        };

        for (users) |user| {
            try stmt.bindText(1, user[0]);
            try stmt.bindText(2, user[1]);
            _ = try stmt.step();
            try stmt.reset();
            try stmt.clearBindings();
        }

        std.debug.print("Inserted {} users\n", .{db.totalChanges()});
    }

    // Insert posts
    {
        var stmt = try db.prepare("INSERT INTO posts (user_id, title, content) VALUES (?, ?, ?)");
        defer stmt.finalize();

        try stmt.bindInt(1, 1); // Alice
        try stmt.bindText(2, "Hello World");
        try stmt.bindText(3, "This is my first post!");
        _ = try stmt.step();
        try stmt.reset();
        try stmt.clearBindings();

        try stmt.bindInt(1, 1); // Alice
        try stmt.bindText(2, "Zig is awesome");
        try stmt.bindNull(3); // No content
        _ = try stmt.step();
        try stmt.reset();
        try stmt.clearBindings();

        try stmt.bindInt(1, 2); // Bob
        try stmt.bindText(2, "SQLite rocks");
        try stmt.bindText(3, "Zero dependencies!");
        _ = try stmt.step();
    }

    std.debug.print("Inserted posts\n\n", .{});

    // Query users
    std.debug.print("All users:\n", .{});
    std.debug.print("-" ** 50 ++ "\n", .{});
    {
        var stmt = try db.prepare("SELECT id, name, email FROM users ORDER BY name");
        defer stmt.finalize();

        while (try stmt.step()) {
            const id = stmt.columnInt(0);
            const name = stmt.columnText(1) orelse "(null)";
            const email = stmt.columnText(2) orelse "(null)";
            std.debug.print("  [{d}] {s} <{s}>\n", .{ id, name, email });
        }
    }

    // Query posts with JOIN
    std.debug.print("\nPosts with authors:\n", .{});
    std.debug.print("-" ** 50 ++ "\n", .{});
    {
        var stmt = try db.prepare(
            \\SELECT p.title, u.name, p.content
            \\FROM posts p
            \\JOIN users u ON p.user_id = u.id
            \\ORDER BY p.id
        );
        defer stmt.finalize();

        while (try stmt.step()) {
            const title = stmt.columnText(0) orelse "(null)";
            const author = stmt.columnText(1) orelse "(null)";
            const content = stmt.columnText(2) orelse "(no content)";
            std.debug.print("  \"{s}\" by {s}\n", .{ title, author });
            std.debug.print("    {s}\n", .{content});
        }
    }

    // Demonstrate transaction rollback
    std.debug.print("\nTransaction demo:\n", .{});
    std.debug.print("-" ** 50 ++ "\n", .{});
    {
        // Count before
        var count_stmt = try db.prepare("SELECT COUNT(*) FROM users");
        defer count_stmt.finalize();
        _ = try count_stmt.step();
        const count_before = count_stmt.columnInt(0);
        std.debug.print("  Users before transaction: {d}\n", .{count_before});

        // Start transaction and insert, then rollback
        try db.begin();
        try db.exec("INSERT INTO users (name, email) VALUES ('Temporary', 'temp@example.com')");
        try db.rollback();

        // Count after rollback
        try count_stmt.reset();
        _ = try count_stmt.step();
        const count_after = count_stmt.columnInt(0);
        std.debug.print("  Users after rollback: {d}\n", .{count_after});
        std.debug.print("  Transaction was rolled back successfully!\n", .{});
    }

    std.debug.print("\nDone!\n", .{});
}
