<?php

use mystic\forum\orm\User;
use mystic\forum\orm\UserPermissions;
use mystic\forum\utils\RequestUtils;
use mystic\forum\utils\ValidationUtils;
use Symfony\Component\Mailer\Exception\TransportException;
use Symfony\Component\Mailer\Transport;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;

$formId = $_POST["form_id"] ?? null;
if ($formId === null) {
    http_response_code(400);
    msg_error("Missing form_id");
    exit;
}

if ($formId === "update_password") {
    if (!$currentUser) {
        http_response_code(403);
        msg_error(__("You must be logged in to update your password"));
        exit;
    }

    if (!$isOwnProfile) {
        RequestUtils::triggerFormError(__("You don't have permission to update this user's password"), $formId);
    }

    RequestUtils::ensureRequestMethod("POST");
    $currentPassword = RequestUtils::getRequiredField("current_password", $formId);
    $newPassword = RequestUtils::getRequiredField("new_password", $formId);
    $retypePassword = RequestUtils::getRequiredField("retype_password", $formId);

    if (!password_verify($currentPassword, $currentUser->passwordHash)) {
        RequestUtils::triggerFormError(__("Current password is incorrect"), $formId);
    }

    if ($newPassword !== $retypePassword) {
        RequestUtils::triggerFormError(__("New passwords don't match"), $formId);
    }

    if (strlen($newPassword) < 8) {
        RequestUtils::triggerFormError(__("Password too short! Your password must consist of 8 or more characters"), $formId);
    }

    $currentUser->passwordHash = password_hash($newPassword, PASSWORD_DEFAULT);
    
    if (!$db->update($currentUser)) {
        RequestUtils::triggerFormError(__("Failed to update password"), $formId);
    }

    header("Location: $_SERVER[REQUEST_URI]");
} elseif ($formId === "update_profile") {
    if (!$currentUser) {
        http_response_code(403);
        msg_error(__("You must be logged in to update your profile"));
        exit;
    }

    $canEdit = ($currentUser?->id === $user?->id && $user?->hasPermission(UserPermissions::EDIT_OWN_USER))
            || ($currentUser?->hasPermission(UserPermissions::EDIT_OTHER_USER));

    if (!$canEdit) {
        http_response_code(403);
        msg_error(__("You don't have permission to update this profile"));
        exit;
    }

    $displayName = RequestUtils::getRequiredField("display_name", $formId);
    $pfpAction = RequestUtils::getRequiredField("pfp_action", $formId);

    $userName = $_POST["name"] ?? $user->name;
    $email = $_POST["email"] ?? $user->email;

    $user->displayName = $displayName;

    $userName = strtolower($userName);

    if ($userName !== $user->name) {
        if ($lastNameChangeTooRecent) {
            RequestUtils::triggerFormError(__("You can only change your username every 30 days!"), $formId);
        } else {
            if (!ValidationUtils::isUsernameValid($userName))
                RequestUtils::triggerFormError(__("Invalid username!"), $formId);
            if (!ValidationUtils::isUsernameAvailable($db, $userName))
                RequestUtils::triggerFormError(__("This username is already taken!"), $formId);
            $user->name = $userName;
            $user->nameLastChanged = new DateTimeImmutable();
        }
    }

    if ($email !== $user->email) {
        if ($user->pendingEmailCreated !== null) {
            RequestUtils::triggerFormError(__("Please verify your email first!"), $formId);
        } else {
            $queryUser = new User();
            $queryUser->email = $email;
            $queryUser->pendingEmail = $email;
            if ($db->fetchWhere($queryUser, "email") || $db->fetchWhere($queryUser, "pending_email")) {
                RequestUtils::triggerFormError(__("This email address is already in use!"), $formId);
            }
            $user->pendingEmail = $email;
            $user->pendingEmailCreated = new DateTimeImmutable();
            $user->activationToken = $db->generateId(12);

            try {
                Transport::fromDsn(env("MAILER_DSN"))->send(
                    (new Email())
                        ->from(env("MAILER_FROM"))
                        ->to(new Address($email, $displayName))
                        ->text(__(
                            "Hello, %user_display_name%!\n" .
                            "\n" .
                            "Please verify your new email address by clicking the link below:\n" .
                            "%verify_link%\n" .
                            "\n" .
                            "Kind regards,\n" .
                            "%forum_copyright%",
                            params: [
                                "forum_title" => (env("MYSTIC_FORUM_TITLE") ?? "Forum"),
                                "user_display_name" => $displayName,
                                "verify_link" => env("PUBLIC_URL") . "?_action=verifyemail&token=" . urlencode($user->activationToken) . "&sig=" . urlencode(base64_encode(hash("sha256", env("SECRET") . $user->activationToken . $user->id, true))),
                                "forum_copyright" => (env("MYSTIC_FORUM_COPYRIGHT") ?? env("MYSTIC_FORUM_TITLE") ?? "Forum")
                            ]
                        ))
                        ->subject(__("Please verify your email address"))
                );
            } catch (TransportException $_) {
                RequestUtils::triggerFormError(__("Failed to send verification email"), $formId);
            }
        }
    }

    switch ($pfpAction) {
        case "keep":
            // Do nothing
            break;
        case "remove":
            $user->profilePicture = null;
            break;
        case "replace": {
            if (!isset($_FILES["pfp"]) || $_FILES["pfp"]["error"] !== UPLOAD_ERR_OK) {
                RequestUtils::triggerFormError(__("Please upload an image to change your profile picture"), $formId);
            }
            $im = @imagecreatefromjpeg($_FILES["pfp"]["tmp_name"]);
            if ($im === false)
                $im = @imagecreatefrompng($_FILES["pfp"]["tmp_name"]);
            if ($im === false)
                RequestUtils::triggerFormError(__("Please upload a valid PNG or JPEG file"), $formId);
            /** @var \GdImage $im */
            $thumb = imagecreatetruecolor(64, 64);
            imagecopyresampled($thumb, $im, 0, 0, 0, 0, 64, 64, imagesx($im), imagesy($im));
            imagedestroy($im);
            $stream = fopen("php://memory", "w+");
            imagejpeg($thumb, $stream, 50);
            rewind($stream);
            imagedestroy($thumb);
            $user->profilePicture = stream_get_contents($stream);
            fclose($stream);
        } break;
        default:
            RequestUtils::triggerFormError("Invalid value for pfp_action", $formId);
            break;
    }

    if (!$db->update($user))
        RequestUtils::triggerFormError(__("Failed to save changes", context: "Update profile"), $formId);

    header("Location: $_SERVER[REQUEST_URI]");
} else {
    msg_error("Invalid formId");
}