const std = @import("std");
const httpz = @import("../.deps/http.zig/src/httpz.zig");
const models = @import("../db/models.zig");
const ztime = @import("../.deps/time.zig");
const utils = @import("../utils.zig");
const trans = @import("transactions.zig");
const note = @import("shared_note.zig");
const handler = @import("../http_handler.zig");
const auth = @import("auth.zig");

pub fn getDashboard(req: *httpz.Request, res: *httpz.Response) !void {
    const db = handler.getDb();

    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    const token = auth.verifyRequest(req, res, null, null) catch {
        return;
    };

    // const family_id = std.fmt.parseInt(u32, family_id_str.?, 0) catch {
    //     res.status = 400;
    //     res.body = "Bad Request: Bad FamilyId";
    //     return;
    // };

    const family = db.selectOneById(models.Family, allocator, token.family_id) catch |err| {
        std.log.err("Error getting family in dashboard: {any}", .{err});
        return handler.returnError("Unexpected Server Error", 500, res);
    };

    if (family == null) {
        std.log.err("Family not found, invalidating client token", .{});
        return handler.returnError("Family does not exist or forbidden", 403, res);
    }

    const user = db.selectOneById(models.User, allocator, token.user_id) catch |err| {
        std.log.err("User not found, invalidating client token, Err: {any}", .{err});
        return handler.returnError("Could not get user or forbidden", 403, res);
    };

    if (user == null) {
        std.log.err("User not found, invalidating client token", .{});
        return handler.returnError("User not found or forbidden", 403, res);
    }

    const transactions = trans.fetchTransFromDb(allocator, family.?.id) catch |err| {
        std.log.err("Unexpected error while getting transactions: {any}", .{err});
        handler.returnError("Internal Server Error", 500, res);
        return;
    };

    const notes = note.fetchNotesFromDb(allocator, family.?.id) catch |err| {
        std.log.err("Unexpected error while getting transactions: {any}", .{err});
        handler.returnError("Internal Server Error", 500, res);
        return;
    };

    const budget_query = try models.createSelectOnFieldQuery(models.Budget, null, "family_id", "=");
    const budget = db.selectOne(models.Budget, allocator, budget_query, .{ .family_id = token.family_id }) catch |err| {
        std.log.err("Unexpected error while getting budget: {any}", .{err});
        handler.returnError("Internal Server Error", 500, res);
        return;
    };

    var budget_categories: ?[]models.BudgetCategory = null;
    if (budget != null) {
        budget_categories = db.selectAllWhere(models.BudgetCategory, allocator, "WHERE budget_id = ? AND hide = ?", .{ .budget_id = budget.?.id, .hide = 0 }, null, null, null, null) catch |err| {
            std.log.err("Unexpected error while getting budget categories: {any}", .{err});
            handler.returnError("Internal Server Error", 500, res);
            return;
        };
    }

    if (budget_categories == null) {
        budget_categories = &[_]models.BudgetCategory{};
    }
    const response_body = .{
        .family = family.?,
        .user = user.?,
        .budget = budget,
        .budget_categories = budget_categories,
        .transactions = transactions,
        .shared_notes = notes,
        .success = true,
    };
    try res.json(response_body, .{});
}
