const std = @import("std");
const zap = @import("zap");

const web = @import("../root.zig");

const Self = @This();

allocator: std.mem.Allocator,
channels: *web.stores.Channels,

path: []const u8,
error_strategy: zap.Endpoint.ErrorStrategy = .log_to_console,

pub fn init(allocator: std.mem.Allocator, channels: *web.stores.Channels, path: []const u8) Self {
    return .{
        .allocator = allocator,
        .channels = channels,
        .path = path,
    };
}

pub fn channelIdFromParams(r: zap.Request) ?web.api.models.Channel.Id {
    if (r.getParamSlice("id")) |str| {
        return std.fmt.parseUnsigned(web.api.models.Channel.Id, str, 10) catch null;
    }
    return null;
}

pub fn parseChannelId(r: zap.Request) ?web.api.models.Channel.Id {
    if (channelIdFromParams(r)) |id| return id;
    r.setStatus(.bad_request);
    r.markAsFinished(true);
    return null;
}

pub fn get(self: *Self, r: zap.Request) !void {
    web.endpoints.pathGuard(r, self.path) catch return;

    r.parseQuery();
    const channel_id = parseChannelId(r) orelse return;
    const channel_internal = self.channels.get(channel_id) orelse {
        r.setStatus(.no_content);
        r.markAsFinished(true);
        return;
    };

    const channel = web.api.models.Channel.fromInternal(&channel_internal);
    const json = try std.json.stringifyAlloc(self.allocator, channel, .{});
    defer self.allocator.free(json);
    try r.setContentType(.JSON);
    try r.sendBody(json);
}

pub fn post(self: *Self, r: zap.Request) !void {
    web.endpoints.pathGuard(r, self.path) catch return;

    r.setStatus(.method_not_allowed);
    r.markAsFinished(true);
}

pub fn put(self: *Self, r: zap.Request) !void {
    web.endpoints.pathGuard(r, self.path) catch return;

    r.setStatus(.method_not_allowed);
    r.markAsFinished(true);
}

pub fn delete(self: *Self, r: zap.Request) !void {
    web.endpoints.pathGuard(r, self.path) catch return;

    r.setStatus(.method_not_allowed);
    r.markAsFinished(true);
}

pub fn patch(self: *Self, r: zap.Request) !void {
    web.endpoints.pathGuard(r, self.path) catch return;

    r.setStatus(.method_not_allowed);
    r.markAsFinished(true);
}

pub fn options(self: *Self, r: zap.Request) !void {
    web.endpoints.pathGuard(r, self.path) catch return;

    try r.setHeader("Access-Control-Allow-Origin", "*");
    try r.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS, HEAD");
    r.setStatus(.no_content);
    r.markAsFinished(true);
}

pub fn head(self: *Self, r: zap.Request) !void {
    web.endpoints.pathGuard(r, self.path) catch return;

    r.setStatus(.no_content);
    r.markAsFinished(true);
}
