/*
 This file is part of GNU Taler
 (C) 2021-2024 Taler Systems S.A.

 GNU Taler 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, or (at your option) any later version.

 GNU Taler 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
 GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
import { AmountString, Amounts, TalerMerchantApi } from "@gnu-taler/taler-util";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useCallback, useEffect, useState } from "preact/hooks";
import { useListener } from "../../hooks/listener.js";
import { undefinedIfEmpty } from "../../utils/table.js";
import { FormErrors, FormProvider } from "../form/FormProvider.js";
import { Input } from "../form/Input.js";
import { InputCurrency } from "../form/InputCurrency.js";
import { InputImage } from "../form/InputImage.js";
import { InputNumber } from "../form/InputNumber.js";
import { InputTaxes } from "../form/InputTaxes.js";
import { usePreference } from "../../hooks/preference.js";

type Entity = TalerMerchantApi.Product;

interface Props {
  onAddProduct: (p: Entity) => Promise<void>;
  productToEdit?: Entity;
}
export function NonInventoryProductFrom({
  productToEdit,
  onAddProduct,
}: Props): VNode {
  const [showCreateProduct, setShowCreateProduct] = useState(false);

  const isEditing = !!productToEdit;

  useEffect(() => {
    setShowCreateProduct(isEditing);
  }, [isEditing]);

  const [submitForm, addFormSubmitter] = useListener<
    Partial<TalerMerchantApi.Product> | undefined
  >((result) => {
    if (result) {
      setShowCreateProduct(false);
      return onAddProduct({
        product_name: result.product_name || "",
        quantity: result.quantity || 0,
        taxes: result.taxes || [],
        description: result.description || "",
        image: result.image || "",
        price: (result.price || "") as AmountString,
        unit: result.unit || "",
      });
    }
    return Promise.resolve();
  });

  const { i18n } = useTranslationContext();

  return (
    <Fragment>
      <div class="buttons">
        <button
          class="button is-success"
          data-tooltip={i18n.str`Describe and add a product that is not in the inventory list`}
          onClick={() => setShowCreateProduct(true)}
        >
          <i18n.Translate>Add custom product</i18n.Translate>
        </button>
      </div>
      {showCreateProduct && (
        <div class="modal is-active">
          <div
            class="modal-background "
            onClick={() => setShowCreateProduct(false)}
          />
          <div class="modal-card">
            <header class="modal-card-head">
              <p class="modal-card-title">{i18n.str`Complete information of the product`}</p>
              <button
                class="delete "
                aria-label="close"
                onClick={() => setShowCreateProduct(false)}
              />
            </header>
            <section class="modal-card-body">
              <ProductForm
                initial={productToEdit}
                onSubscribe={addFormSubmitter}
              />
            </section>
            <footer class="modal-card-foot">
              <div class="buttons is-right" style={{ width: "100%" }}>
                <button
                  class="button "
                  onClick={() => setShowCreateProduct(false)}
                >
                  <i18n.Translate>Cancel</i18n.Translate>
                </button>
                <button
                  class="button is-info "
                  disabled={!submitForm}
                  onClick={submitForm}
                >
                  <i18n.Translate>Confirm</i18n.Translate>
                </button>
              </div>
            </footer>
          </div>
          <button
            class="modal-close is-large "
            aria-label="close"
            onClick={() => setShowCreateProduct(false)}
          />
        </div>
      )}
    </Fragment>
  );
}

interface ProductProps {
  onSubscribe: (c?: () => Entity | undefined) => void;
  initial?: Partial<Entity>;
}

interface NonInventoryProduct {
  quantity: number;
  description: string;
  unit: string;
  price: string;
  image: string;
  taxes: TalerMerchantApi.Tax[];
}

export function ProductForm({ onSubscribe, initial }: ProductProps): VNode {
  const { i18n } = useTranslationContext();
  const [preference] = usePreference();
  const [value, valueHandler] = useState<Partial<NonInventoryProduct>>({
    taxes: [],
    ...initial,
  });
  const errors = undefinedIfEmpty<FormErrors<NonInventoryProduct>>({
    quantity:
      value.quantity === undefined
        ? i18n.str`Required`
        : typeof value.quantity !== "number"
          ? i18n.str`Must be a number.`
          : value.quantity < 1
            ? i18n.str`Must be greater than 0.`
            : undefined,
    description: !value.description ? i18n.str`Required` : undefined,
    unit: !value.unit ? i18n.str`Required` : undefined,
    price: !value.price
      ? i18n.str`Required`
      : Amounts.parse(value.price) === undefined
        ? i18n.str`Invalid`
        : undefined,
  });

  const submit = useCallback((): Entity | undefined => {
    return value as TalerMerchantApi.Product;
  }, [value]);

  const hasErrors = errors !== undefined;

  useEffect(() => {
    onSubscribe(hasErrors ? undefined : submit);
  }, [submit, hasErrors]);

  return (
    <div>
      <FormProvider<NonInventoryProduct>
        name="product"
        errors={errors}
        object={value}
        valueHandler={valueHandler}
      >
        <InputImage<NonInventoryProduct>
          name="image"
          label={i18n.str`Image`}
          tooltip={i18n.str`Photo of the product.`}
        />
        <Input<NonInventoryProduct>
          name="description"
          inputType="multiline"
          label={i18n.str`Description`}
          tooltip={i18n.str`Full product description.`}
        />
        <Input<NonInventoryProduct>
          name="unit"
          label={i18n.str`Unit name`}
          tooltip={i18n.str`Name of the product unit.`}
        />
        <InputCurrency<NonInventoryProduct>
          name="price"
          label={i18n.str`Price per unit`}
          tooltip={i18n.str`Amount in the current currency.`}
        />

        <InputNumber<NonInventoryProduct>
          name="quantity"
          label={i18n.str`Quantity`}
          tooltip={i18n.str`How many products will be added.`}
        />

        {preference.developerMode ? (
          <InputTaxes<NonInventoryProduct>
            name="taxes"
            label={i18n.str`Taxes`}
          />
        ) : (
          <Fragment />
        )}
      </FormProvider>
    </div>
  );
}
