/*
 * Vencord, a modification for Discord's desktop app
 * Copyright (c) 2023 Vendicated and contributors
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

import { showNotification } from "@api/Notifications";
import { Settings, useSettings } from "@api/Settings";
import { CheckedTextInput } from "@components/CheckedTextInput";
import { Divider } from "@components/Divider";
import { FormSwitch } from "@components/FormSwitch";
import { Grid } from "@components/Grid";
import { Link } from "@components/Link";
import { NxCard, NxText, NxTitle } from "@components/NxComponents";
import { Paragraph } from "@components/Paragraph";
import { SettingsTab, wrapTab } from "@components/settings/tabs/BaseTab";
import { authorizeCloud, checkCloudUrlCsp, cloudLogger, deauthorizeCloud, getCloudAuth, getCloudUrl } from "@utils/cloud";
import { Margins } from "@utils/margins";
import { deleteCloudSettings, getCloudSettings, putCloudSettings } from "@utils/settingsSync";
import { Alerts, Button, Forms, Tooltip } from "@webpack/common";

function validateUrl(url: string) {
    try {
        new URL(url);
        return true;
    } catch {
        return "Invalid URL";
    }
}

async function eraseAllData() {
    if (!await checkCloudUrlCsp()) return;

    const res = await fetch(new URL("/v1/", getCloudUrl()), {
        method: "DELETE",
        headers: { Authorization: await getCloudAuth() }
    });

    if (!res.ok) {
        cloudLogger.error(`Failed to erase data, API returned ${res.status}`);
        showNotification({
            title: "Cloud Integrations",
            body: `Could not erase all data (API returned ${res.status}), please contact support.`,
            color: "var(--red-360)"
        });
        return;
    }

    Settings.cloud.authenticated = false;
    await deauthorizeCloud();

    showNotification({
        title: "Cloud Integrations",
        body: "Successfully erased all data.",
        color: "var(--green-360)"
    });
}

function SettingsSyncSection() {
    const { cloud } = useSettings(["cloud.authenticated", "cloud.settingsSync"]);
    const sectionEnabled = cloud.authenticated && cloud.settingsSync;

    return (
        <section className={Margins.top16}><NxCard>
            <NxTitle>Settings Sync</NxTitle>

            <Paragraph className={Margins.bottom20}>
                Synchronize your settings to the cloud. This allows easy synchronization across multiple devices with
                minimal effort.
            </Paragraph>
            <FormSwitch
                key="cloud-sync"
                title="Settings Sync"
                value={cloud.settingsSync}
                onChange={v => { cloud.settingsSync = v; }}
                className="nx-removeSwitchDivider"
                disabled={!cloud.authenticated}
            />
            <div className="vc-cloud-settings-sync-grid">
                <Button
                    size={Button.Sizes.SMALL}
                    disabled={!sectionEnabled}
                    onClick={() => putCloudSettings(true)}
                >
                    Sync to Cloud
                </Button>
                <Tooltip text="This will overwrite your local settings with the ones on the cloud. Use wisely!">
                    {({ onMouseLeave, onMouseEnter }) => (
                        <Button
                            onMouseLeave={onMouseLeave}
                            onMouseEnter={onMouseEnter}
                            size={Button.Sizes.SMALL}
                            color={Button.Colors.RED}
                            disabled={!sectionEnabled}
                            onClick={() => getCloudSettings(true, true)}
                        >
                            Sync from Cloud
                        </Button>
                    )}
                </Tooltip>
                <Button
                    size={Button.Sizes.SMALL}
                    color={Button.Colors.RED}
                    disabled={!sectionEnabled}
                    onClick={() => deleteCloudSettings()}
                >
                    Delete Cloud Settings
                </Button>
            </div>
        </NxCard ></section>
    );
}

function CloudTab() {
    const settings = useSettings(["cloud.authenticated", "cloud.url"]);

    return (
        <SettingsTab title="Vencord Cloud">
            <section className={Margins.top16}>
                <NxCard className={Margins.bottom20}>
                    <NxText>
                        Vencord comes with a cloud integration that adds goodies like settings sync across devices.
                        It <Link href="https://vencord.dev/cloud/privacy">respects your privacy</Link>, and
                        the <Link href="https://github.com/Vencord/Backend">source code</Link> is AGPL 3.0 licensed so you
                        can host it yourself. It may or may not work with Nexulien; use with caution.
                    </NxText>
                </NxCard>
                <FormSwitch
                    key="backend"
                    title="Enable Cloud Integrations"
                    description="This will request authorization if you have not yet set up cloud integrations."
                    value={settings.cloud.authenticated}
                    onChange={v => {
                        if (v)
                            authorizeCloud();
                        else
                            settings.cloud.authenticated = v;
                    }}
                    hideBorder={!settings.cloud.authenticated}
                />

                {settings.cloud.authenticated ? <>
                    <NxCard>
                        <NxTitle>Backend URL</NxTitle>
                        <Forms.FormText className={Margins.bottom8}>
                            Which backend to use when using cloud integrations.
                        </Forms.FormText>
                        <CheckedTextInput
                            key="backendUrl"
                            value={settings.cloud.url}
                            onChange={async v => {
                                settings.cloud.url = v;
                                settings.cloud.authenticated = false;
                                deauthorizeCloud();
                            }}
                            validate={validateUrl}
                        />

                        <Grid columns={2} gap="1em" className={Margins.top8}>
                            <Button
                                size={Button.Sizes.MEDIUM}
                                disabled={!settings.cloud.authenticated}
                                onClick={async () => {
                                    await deauthorizeCloud();
                                    settings.cloud.authenticated = false;
                                    await authorizeCloud();
                                }}
                            >
                                Reauthorise
                            </Button>
                            <Button
                                size={Button.Sizes.MEDIUM}
                                color={Button.Colors.RED}
                                disabled={!settings.cloud.authenticated}
                                onClick={() => Alerts.show({
                                    title: "Are you sure?",
                                    body: "Once your data is erased, we cannot recover it. There's no going back!",
                                    onConfirm: eraseAllData,
                                    confirmText: "Erase it!",
                                    confirmColor: "vc-cloud-erase-data-danger-btn",
                                    cancelText: "Nevermind"
                                })}
                            >
                                Erase All Data
                            </Button>
                        </Grid>
                    </NxCard >

                    <Divider className={Margins.top16} />
                    <SettingsSyncSection />
                </> : <></>}
            </section>
        </SettingsTab>
    );
}

export default wrapTab(CloudTab, "Cloud");
