import { Api } from "@src/lib/apiValidator.ts";
import { createValidationError, z } from "@shared/utils/validator.ts";
import {
    adminPasswordAlreadySetErrorSchema,
    adminPasswordNotSetErrorSchema,
    commandExecutionErrorSchema,
    failedToParseRequestAsJSONErrorSchema,
    invalidPasswordErrorSchema,
    passwordsMustMatchErrorSchema,
    queryExecutionErrorSchema,
    requestValidationErrorSchema,
    tooManyRequestsErrorSchema,
    unauthorizedErrorSchema,
    usbipUnknownErrorSchema,
} from "@src/lib/errors.ts";

const loginApiSchema = {
    req: z.obj({
        password: z.string(),
    }),
    res: z.result(
        z.void(),
        z.union([
            adminPasswordNotSetErrorSchema,
            queryExecutionErrorSchema,
            failedToParseRequestAsJSONErrorSchema,
            requestValidationErrorSchema,
            tooManyRequestsErrorSchema,
            invalidPasswordErrorSchema,
        ]),
    ),
};

export const loginApi = new Api("/login", "POST", loginApiSchema);

const passwordSetupApiSchema = {
    req: z.obj({
        password: z.string().min(
            10,
            "Password must be at least 10 characters long",
        ).regex(
            /^[a-zA-Z0-9]+$/,
            "Password must consist of lower or upper case latin letters and numbers",
        ),
        passwordRepeat: z.string(),
    }).addCheck((v) => {
        if (v.passwordRepeat !== v.password) {
            return createValidationError(v, {
                kind: "general",
                msg: "Passwords must match",
            });
        }
    }),
    res: z.result(
        z.void(),
        z.union([
            passwordsMustMatchErrorSchema,
            adminPasswordAlreadySetErrorSchema,
            queryExecutionErrorSchema,
            failedToParseRequestAsJSONErrorSchema,
            requestValidationErrorSchema,
            tooManyRequestsErrorSchema,
        ]),
    ),
};

export const passwordSetupApi = new Api(
    "/setup",
    "POST",
    passwordSetupApiSchema,
);

const updateDevicesApiSchema = {
    req: z.void(),
    res: z.result(
        z.void(),
        z.union([
            queryExecutionErrorSchema,
            tooManyRequestsErrorSchema,
            unauthorizedErrorSchema,
            commandExecutionErrorSchema,
            usbipUnknownErrorSchema,
        ]),
    ),
};

export const updateDevicesApi = new Api(
    "/api/devices/detect",
    "GET",
    updateDevicesApiSchema,
);

const versionApiSchema = {
    req: z.void(),
    res: z.result(
        z.obj({
            app: z.literal("Keyborg"),
            version: z.string(),
        }),
        z.union([
            tooManyRequestsErrorSchema,
        ]),
    ),
};
export const versionApi = new Api(
    "/api/version",
    "GET",
    versionApiSchema,
);
