<script lang="ts">
    import { onMount, onDestroy } from 'svelte';
    import { slide } from 'svelte/transition';
    import { cubicOut } from 'svelte/easing';
    import SettingsCard from '$lib/components/SettingsCard.svelte';
    import Collapsible from '$lib/components/Collapsible.svelte';
    import Spinner from '$lib/components/Spinner.svelte';
    import { useFeatureFlags } from '$lib/stores';
    import { notifications } from '$lib/components/toasts/notifications';
    import { TIME_ZONES } from './timezones';
    import type { NTPSettings, NTPStatus } from '$lib/types/models';
    import { api } from '$lib/api';
    import { NTP, UTC, Stopwatch, Clock, Server } from '$lib/components/icons';

    const features = useFeatureFlags();

    let ntpSettings: NTPSettings;
    let ntpStatus: NTPStatus;

    async function getNTPStatus() {
        const result = await api.get<NTPStatus>('/api/ntp/status');
        if (result.isErr()) {
            console.error('Error:', result.inner);
            return;
        }
        ntpStatus = result.inner;
    }

    async function getNTPSettings() {
        const result = await api.get<NTPSettings>('/api/ntp/settings');
        if (result.isErr()) {
            console.error('Error:', result.inner);
            return;
        }
        ntpSettings = result.inner;
    }

    const interval = setInterval(async () => getNTPStatus(), 5000);

    onDestroy(() => clearInterval(interval));

    onMount(getNTPSettings);

    let formField: any;

    let formErrors = {
        server: false
    };

    async function postNTPSettings(data: NTPSettings) {
        const result = await api.post<NTPSettings>('/api/ntp/settings', data);
        if (result.isErr()) {
            notifications.error('User not authorized.', 3000);
            console.error('Error:', result.inner);
            return;
        }
        ntpSettings = result.inner;
    }

    function handleSubmitNTP() {
        let valid = true;

        // Validate Server
        // RegEx for IPv4
        const regexExpIPv4 =
            /\b(?:(?:2(?:[0-4][0-9]|5[0-5])|[0-1]?[0-9]?[0-9])\.){3}(?:(?:2([0-4][0-9]|5[0-5])|[0-1]?[0-9]?[0-9]))\b/;
        const regexExpURL =
            /[-a-zA-Z0-9@:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&//=]*)?/i;

        if (!regexExpURL.test(ntpSettings.server) && !regexExpIPv4.test(ntpSettings.server)) {
            valid = false;
            formErrors.server = true;
        } else {
            formErrors.server = false;
        }

        ntpSettings.tz_format = TIME_ZONES[ntpSettings.tz_label];

        // Submit JSON to REST API
        if (valid) {
            postNTPSettings(ntpSettings);
            //alert('Form Valid');
        }
    }

    function convertSeconds(seconds: number) {
        // Calculate the number of seconds, minutes, hours, and days
        let minutes = Math.floor(seconds / 60);
        let hours = Math.floor(minutes / 60);
        let days = Math.floor(hours / 24);

        // Calculate the remaining hours, minutes, and seconds
        hours = hours % 24;
        minutes = minutes % 60;
        seconds = seconds % 60;

        // Create the formatted string
        let result = '';
        if (days > 0) {
            result += days + ' day' + (days > 1 ? 's' : '') + ' ';
        }
        if (hours > 0) {
            result += hours + ' hour' + (hours > 1 ? 's' : '') + ' ';
        }
        if (minutes > 0) {
            result += minutes + ' minute' + (minutes > 1 ? 's' : '') + ' ';
        }
        result += seconds + ' second' + (seconds > 1 ? 's' : '');

        return result;
    }
</script>

<SettingsCard collapsible={false}>
    <Clock slot="icon" class="lex-shrink-0 mr-2 h-6 w-6 self-end" />
    <span slot="title">Network Time</span>
    <div class="w-full overflow-x-auto">
        {#await getNTPStatus()}
            <Spinner />
        {:then nothing}
            <div
                class="flex w-full flex-col space-y-1"
                transition:slide|local={{ duration: 300, easing: cubicOut }}
            >
                <div class="rounded-box bg-base-100 flex items-center space-x-3 px-4 py-2">
                    <div
                        class="mask mask-hexagon h-auto w-10 {ntpStatus.status === 1 ?
                            'bg-success'
                        :   'bg-error'}"
                    >
                        <NTP
                            class="h-auto w-full scale-75 {ntpStatus.status === 1 ?
                                'text-success-content'
                            :   'text-error-content'}"
                        />
                    </div>
                    <div>
                        <div class="font-bold">Status</div>
                        <div class="text-sm opacity-75">
                            {ntpStatus.status === 1 ? 'Active' : 'Inactive'}
                        </div>
                    </div>
                </div>

                <div class="rounded-box bg-base-100 flex items-center space-x-3 px-4 py-2">
                    <div class="mask mask-hexagon bg-primary h-auto w-10">
                        <Server class="text-primary-content h-auto w-full scale-75" />
                    </div>
                    <div>
                        <div class="font-bold">NTP Server</div>
                        <div class="text-sm opacity-75">
                            {ntpStatus.server}
                        </div>
                    </div>
                </div>

                <div class="rounded-box bg-base-100 flex items-center space-x-3 px-4 py-2">
                    <div class="mask mask-hexagon bg-primary h-auto w-10">
                        <Clock class="text-primary-content h-auto w-full scale-75" />
                    </div>
                    <div>
                        <div class="font-bold">Local Time</div>
                        <div class="text-sm opacity-75">
                            {new Intl.DateTimeFormat('en-GB', {
                                dateStyle: 'long',
                                timeStyle: 'long'
                            }).format(new Date(ntpStatus.local_time))}
                        </div>
                    </div>
                </div>

                <div class="rounded-box bg-base-100 flex items-center space-x-3 px-4 py-2">
                    <div class="mask mask-hexagon bg-primary h-auto w-10">
                        <UTC class="text-primary-content h-auto w-full scale-75" />
                    </div>
                    <div>
                        <div class="font-bold">UTC Time</div>
                        <div class="text-sm opacity-75">
                            {new Intl.DateTimeFormat('en-GB', {
                                dateStyle: 'long',
                                timeStyle: 'long',
                                timeZone: 'UTC'
                            }).format(new Date(ntpStatus.utc_time))}
                        </div>
                    </div>
                </div>

                <div class="rounded-box bg-base-100 flex items-center space-x-3 px-4 py-2">
                    <div class="mask mask-hexagon bg-primary h-auto w-10">
                        <Stopwatch class="text-primary-content h-auto w-full scale-75" />
                    </div>
                    <div>
                        <div class="font-bold">Uptime</div>
                        <div class="text-sm opacity-75">
                            {convertSeconds(ntpStatus.uptime)}
                        </div>
                    </div>
                </div>
            </div>
        {/await}
    </div>

    <Collapsible open={false} on:closed={getNTPSettings}>
        <span slot="title">Change NTP Settings</span>
        <form
            class="form-control w-full"
            on:submit|preventDefault={handleSubmitNTP}
            novalidate
            bind:this={formField}
        >
            <label class="label cursor-pointer justify-start gap-4">
                <input
                    type="checkbox"
                    bind:checked={ntpSettings.enabled}
                    class="checkbox checkbox-primary"
                />
                <span class="">Enable NTP</span>
            </label>
            <label class="label" for="server">
                <span class="label-text text-md">Server</span>
            </label>
            <input
                type="text"
                min="3"
                max="64"
                class="input input-bordered invalid:border-error w-full invalid:border-2 {(
                    formErrors.server
                ) ?
                    'border-error border-2'
                :   ''}"
                bind:value={ntpSettings.server}
                id="server"
                required
            />
            <label class="label" for="subnet">
                <span class="label-text-alt text-error {formErrors.server ? '' : 'hidden'}"
                    >Must be a valid IPv4 address or URL</span
                >
            </label>
            <label class="label" for="tz">
                <span class="label-text text-md">Pick Time Zone</span>
            </label>
            <select class="select select-bordered" bind:value={ntpSettings.tz_label} id="tz">
                {#each Object.entries(TIME_ZONES) as [tz_label, tz_format]}
                    <option value={tz_label}>{tz_label}</option>
                {/each}
            </select>

            <div class="mt-6 place-self-end">
                <button class="btn btn-primary" type="submit">Apply Settings</button>
            </div>
        </form>
    </Collapsible>
</SettingsCard>
