/*
 *  Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *  SPDX-License-Identifier: Apache-2.0
 */

import React, { useState } from "react";
import { useHistory, useParams } from "react-router-dom";
import { useForm } from "react-hook-form";
import TextField from "../components/TextField";
import NumberField from "../components/NumberField";
import Button from "../components/Button";
import Breadcrumbs from "../components/Breadcrumbs";
import { useDashboard, useSettings } from "../hooks";
import Spinner from "../components/Spinner";
import DateRangePicker from "../components/DateRangePicker";
import { useTranslation } from "react-i18next";
import Dropdown from "../components/Dropdown";
import { CurrencyDataType, LocationState, NumberDataType } from "../models";
import "./EditMetric.scss";

interface FormValues {
    title: string;
    value: number;
    changeOverTime: string;
    percentage: string;
    currency: string;
    showTimeChange: boolean;
    showDateRange: boolean;
}

interface PathParams {
    dashboardId: string;
}

function EditMetric() {
    const history = useHistory<LocationState>();
    const { state } = history.location;
    const { t } = useTranslation();
    const { settings, loadingSettings } = useSettings();
    const { dashboardId } = useParams<PathParams>();
    const { dashboard, loading } = useDashboard(dashboardId);
    const { register, errors, handleSubmit } = useForm<FormValues>();
    const [startDate, setStartDate] = useState<Date | null>(
        state.metric && state.metric.startDate ? new Date(state.metric.startDate) : null,
    );
    const [endDate, setEndDate] = useState<Date | null>(
        state.metric && state.metric.endDate ? new Date(state.metric.endDate) : null,
    );
    const [symbolType, setsymbolType] = useState<string>("");

    const hasTimeChange = () => {
        if (state.metric && state.metric.changeOverTime && state.metric.changeOverTime.length > 0) {
            return true;
        } else {
            return false;
        }
    };
    const [showTimeChange, setShowTimeChange] = useState<boolean>(hasTimeChange());

    const hasDateRange = () => {
        if (state.metric && state.metric.startDate) {
            return true;
        } else {
            return false;
        }
    };
    const [showDateRange, setShowDateRange] = useState<boolean>(hasDateRange());

    const onSubmit = async (values: FormValues) => {
        const editedMetric =
            state && state.metrics && state.position !== undefined
                ? state.metrics[state.position]
                : undefined;
        if (editedMetric) {
            editedMetric.title = values.title;
            editedMetric.value = values.value;
            editedMetric.percentage = values.percentage;
            editedMetric.currency = values.currency;
            editedMetric.changeOverTime = showTimeChange ? values.changeOverTime : "";
            editedMetric.startDate = showDateRange && startDate ? startDate.toISOString() : "";
            editedMetric.endDate = showDateRange && endDate ? endDate.toISOString() : "";
        }

        const newMetrics = state && state.metrics ? [...state.metrics] : [];
        history.push((state && state.origin) || `/admin/dashboard/${dashboardId}/add-metrics`, {
            alert: {
                type: "success",
                message: t("EditMetricScreen.MetricSuccessfullyEdited"),
            },
            metrics: newMetrics,
            showTitle: state.showTitle !== false,
            oneMetricPerRow: state.oneMetricPerRow === true,
            metricTitle: state.metricTitle || "",
            datasetType: state.datasetType || undefined,
        });
    };

    const handleSymbol = (e: React.ChangeEvent<HTMLInputElement>) => {
        if (e.target.value === "Percentage") {
            setsymbolType("Percentage");
        } else if (e.target.value === "Currency") {
            setsymbolType("Currency");
        } else if (e.target.value === "") {
            setsymbolType("SelectAnOption");
        }
    };

    const onCancel = () => {
        history.push((state && state.origin) || `/admin/dashboard/${dashboardId}/add-metrics`, {
            metrics: state && state.metrics ? [...state.metrics] : [],
            showTitle: state && state.showTitle !== false,
            oneMetricPerRow: state && state.oneMetricPerRow === true,
            metricTitle: (state && state.metricTitle) || "",
            datasetType: state.datasetType || undefined,
        });
    };

    if (!state || !state.metrics || !state.metric) {
        setTimeout(onCancel, 1000);
        return null;
    }

    const crumbs = [
        {
            label: t("Dashboards"),
            url: "/admin/dashboards",
        },
        {
            label: dashboard?.name,
            url: `/admin/dashboard/edit/${dashboardId}`,
        },
    ];

    if (!loading) {
        crumbs.push({
            label: t("EditMetricScreen.EditMetric"),
            url: "",
        });
    }

    return (
        <>
            <Breadcrumbs crumbs={crumbs} />

            {loading || loadingSettings ? (
                <Spinner className="text-center margin-top-9" label={t("LoadingSpinnerLabel")} />
            ) : (
                <>
                    <div className="grid-row">
                        <div className="grid-col-8">
                            <h1 id="editMetricFormHeader">{t("EditMetricScreen.EditMetric")}</h1>

                            <form
                                aria-labelledby="editMetricFormHeader"
                                onSubmit={handleSubmit(onSubmit)}
                                className="usa-form usa-form--large"
                                data-testid="EditMetricForm"
                            >
                                <fieldset className="usa-fieldset">
                                    <legend className="usa-hint grid-col-6">
                                        {t("EditMetricScreen.Configure")}
                                    </legend>

                                    <TextField
                                        id="title"
                                        name="title"
                                        label={t("EditMetricScreen.MetricTitle")}
                                        register={register}
                                        defaultValue={state.metric.title}
                                        error={
                                            errors.title && t("EditMetricScreen.MetricTitleError")
                                        }
                                        required
                                        aria-describedby="title-hint"
                                    />
                                    <div className="usa-hint" id="title-hint">
                                        {t("EditMetricScreen.MetricTitleHint")}
                                    </div>

                                    <NumberField
                                        id="value"
                                        name="value"
                                        label={t("EditMetricScreen.MetricValue")}
                                        register={register}
                                        error={
                                            errors.value && t("EditMetricScreen.MetricValueError")
                                        }
                                        defaultValue={state.metric.value}
                                        step={0.01}
                                        required
                                    />

                                    <Dropdown
                                        id="percentage"
                                        name="percentage"
                                        label={t("NumberFormat")}
                                        options={[
                                            {
                                                value: "",
                                                label: t("SelectAnOption"),
                                            },
                                            {
                                                value: NumberDataType.Percentage,
                                                label: t("Percentage"),
                                            },
                                            {
                                                value: NumberDataType.Currency,
                                                label: t("Currency"),
                                            },
                                        ]}
                                        defaultValue={state.metric.percentage}
                                        onChange={handleSymbol}
                                        register={register}
                                        className="tablet:grid-col-6"
                                    />

                                    {symbolType === "Currency" &&
                                        (state.metric.percentage === "Percentage" ||
                                            state.metric.percentage === "SelectAnOption" ||
                                            state.metric.percentage === "" ||
                                            state.metric.percentage === undefined) && (
                                            <Dropdown
                                                id="currency"
                                                name="currency"
                                                label={t("Currency")}
                                                options={[
                                                    {
                                                        value: "",
                                                        label: t("SelectAnOption"),
                                                    },
                                                    {
                                                        value: CurrencyDataType["Dollar $"],
                                                        label: t("Dollar"),
                                                    },
                                                    {
                                                        value: CurrencyDataType["Euro €"],
                                                        label: t("Euro"),
                                                    },
                                                    {
                                                        value: CurrencyDataType["Pound £"],
                                                        label: t("Pound"),
                                                    },
                                                ]}
                                                defaultValue={state.metric.currency}
                                                register={register}
                                                required
                                            />
                                        )}
                                    {state.metric.percentage === "Currency" &&
                                        symbolType !== "Percentage" &&
                                        symbolType !== "SelectAnOption" && (
                                            <Dropdown
                                                id="currency"
                                                name="currency"
                                                label={t("Currency")}
                                                hint={t("AddMetricScreen.MetricCurrencyHint")}
                                                options={[
                                                    {
                                                        value: "",
                                                        label: t("SelectAnOption"),
                                                    },
                                                    {
                                                        value: CurrencyDataType["Dollar $"],
                                                        label: t("Dollar"),
                                                    },
                                                    {
                                                        value: CurrencyDataType["Euro €"],
                                                        label: t("Euro"),
                                                    },
                                                    {
                                                        value: CurrencyDataType["Pound £"],
                                                        label: t("Pound"),
                                                    },
                                                ]}
                                                defaultValue={state.metric.currency}
                                                register={register}
                                                required
                                            />
                                        )}

                                    <div className="usa-checkbox margin-top-4">
                                        <input
                                            className="usa-checkbox__input"
                                            type="checkbox"
                                            id="showTimeChange"
                                            name="showTimeChange"
                                            checked={showTimeChange}
                                            onClick={() => setShowTimeChange(!showTimeChange)}
                                            onChange={() => setShowTimeChange(!showTimeChange)}
                                        />
                                        <label
                                            className="usa-checkbox__label"
                                            htmlFor="showTimeChange"
                                        >
                                            {`${t("EditMetricScreen.ShowTimeChange")}`}
                                        </label>
                                    </div>

                                    {showTimeChange && (
                                        <>
                                            <TextField
                                                id="changeOverTime"
                                                name="changeOverTime"
                                                label={t("EditMetricScreen.ChangeOverTime")}
                                                register={register}
                                                defaultValue={state.metric.changeOverTime}
                                                error={
                                                    errors.changeOverTime &&
                                                    errors.changeOverTime.type === "validate"
                                                        ? t("EditMetricScreen.ChangeOverTimeError")
                                                        : undefined
                                                }
                                                validate={(input: string) => {
                                                    return (
                                                        !input ||
                                                        input[0] === "+" ||
                                                        input[0] === "-"
                                                    );
                                                }}
                                                aria-describedby="changeOverTime-hint"
                                                required
                                            />
                                            <div className="usa-hint" id="changeOverTime-hint">
                                                {t("EditMetricScreen.ChangeOverTimeHint")}
                                            </div>
                                        </>
                                    )}

                                    <div className="usa-checkbox margin-top-4">
                                        <input
                                            className="usa-checkbox__input"
                                            type="checkbox"
                                            id="showDateRange"
                                            name="showDateRange"
                                            checked={showDateRange}
                                            onClick={() => setShowDateRange(!showDateRange)}
                                            onChange={() => setShowDateRange(!showDateRange)}
                                        />
                                        <label
                                            className="usa-checkbox__label"
                                            htmlFor="showDateRange"
                                        >
                                            {`${t("EditMetricScreen.ShowDateRange")}`}
                                        </label>
                                    </div>

                                    {showDateRange && (
                                        <DateRangePicker
                                            start={{
                                                id: "startDate",
                                                name: "startDate",
                                                label: t("EditMetricScreen.StartDate"),
                                                hint: settings.dateTimeFormat.date,
                                                date: startDate,
                                                dateFormat: settings.dateTimeFormat.date
                                                    .toLowerCase()
                                                    .replace(/m/g, "M"),
                                                setDate: setStartDate,
                                            }}
                                            end={{
                                                id: "endDate",
                                                name: "endDate",
                                                label: t("EditMetricScreen.EndDate"),
                                                hint: settings.dateTimeFormat.date,
                                                date: endDate,
                                                dateFormat: settings.dateTimeFormat.date
                                                    .toLowerCase()
                                                    .replace(/m/g, "M"),
                                                setDate: setEndDate,
                                            }}
                                        />
                                    )}
                                </fieldset>
                                <br />
                                <br />
                                <Button type="submit" className="margin-top-1">
                                    {t("Save")}
                                </Button>
                                <Button
                                    className="text-base-dark hover:text-base-darker active:text-base-darkest margin-top-1"
                                    variant="unstyled"
                                    type="button"
                                    onClick={onCancel}
                                >
                                    {t("Cancel")}
                                </Button>
                            </form>
                        </div>
                    </div>
                </>
            )}
        </>
    );
}

export default EditMetric;