/*
 This file is part of GNU Taler
 (C) 2021-2025 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/>
 */

/**
 *
 * @author Martin Schanzenbach
 */

import { AmountJson, Amounts, StatisticBucketRange } from "@gnu-taler/taler-util";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { ChartDataset, Point } from "chart.js";
import { format } from "date-fns";
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
import { Bar } from "react-chartjs-2";
import { FormProvider } from "../../../../components/form/FormProvider.js";
import { InputGroup } from "../../../../components/form/InputGroup.js";
import { InputNumber } from "../../../../components/form/InputNumber.js";
import { InputSelector } from "../../../../components/form/InputSelector.js";

const TALER_SCREEN_ID = 59;

export interface RevenueChartFilter {
  rangeCount: number,
  range: string,
  currency: string,
}

export interface RevenueChartProps {
  chartData?: ChartDataset[];
  chartLabels: number[];
  chartOptions: any;
  availableCurrencies: string[];
  activeFilter: {range: string, currency: string, rangeCount: number};
  onUpdateFilter: (filter: RevenueChartFilter) => void;
}

export function RevenueChart({
  chartData,
  chartLabels,
  chartOptions,
  onUpdateFilter,
  availableCurrencies,
  activeFilter: activeFilter,
}: RevenueChartProps): VNode {
  const { i18n } = useTranslationContext();
  const [showTable, setShowTable] = useState<boolean>(false);
  const translateMap = new Map<string, [string, string]>([
    ["hour", [i18n.str`hour`, i18n.str`hours`]],
    ["day", [i18n.str`day`, i18n.str`days`]],
    ["week", [i18n.str`week`, i18n.str`weeks`]],
    ["month", [i18n.str`month`, i18n.str`months`]],
    ["quarter", [i18n.str`quarter`, i18n.str`quarters`]],
    ["year", [i18n.str`years`, i18n.str`years`]],
  ])
  function translateRange(range: {rangeCount: number, range?: string}) : string {
    if (!translateMap.has(range.range!)) {
      return "";
    }
    return (range.rangeCount < 2) ? translateMap.get(range.range!)![0] : translateMap.get(range.range!)![1];
  };
  const revenueRanges = Object.values(StatisticBucketRange);
  const formatMap = new Map<string, string>([
    ["hour", 'yyyy MMMM d ha'],
    ["day", 'yyyy MMM d'],
    ["week", 'yyyy MMM w'],
    ["month", 'yyyy MMM'],
    ["quarter", 'yyyy qqq'],
    ["year", 'yyyy'],
  ]);
  function getRevenueForLabelAndDataset(label: number, ds: ChartDataset) : string {
    for (let d of (ds.data as (Point & AmountJson)[])) {
      if (d.x === label) {
        console.log(Amounts.toPretty(d));
        return Amounts.toPretty(d);
      }
    }
    return "-";
  }
  const form = activeFilter;
  return (
    <Fragment>
      <div class="tabs" style={{ overflow: "inherit" }}>
         <ul>
           <li class={(!showTable) ? "is-active" : ""}>
             <div
               class="has-tooltip-right"
               data-tooltip={i18n.str`Show chart`}
             >
               <a onClick={() => {setShowTable(false) }}>
                 <i18n.Translate>Revenue chart</i18n.Translate>
               </a>
             </div>
           </li>
           <li class={(showTable) ? "is-active" : ""}>
             <div
               class="has-tooltip-right"
               data-tooltip={i18n.str`Show table`}
             >
               <a onClick={() => {setShowTable(true) }}>
                 <i18n.Translate>Revenue table</i18n.Translate>
               </a>
             </div>
           </li>
         </ul>
       </div>
       <div class="columns">
        <div class="column">
          <div class="buttons is-right">
          <FormProvider
          object={form}
          valueHandler={(updater) => onUpdateFilter(
            {
            rangeCount: updater(form).rangeCount ?? activeFilter.rangeCount,
            range: updater(form).range ?? activeFilter.range,
            currency: updater(form).currency ?? activeFilter.currency
            }
          )}
          >
            <InputGroup
              name="rangeFilter"
              label={i18n.str`Revenue statistics filter`}
            >
            <InputSelector
              name="range"
              label={i18n.str`Time range`}
              values={revenueRanges}
              fromStr={(d) => {
                const idx = revenueRanges.indexOf(d as StatisticBucketRange)
                if (idx === -1) return undefined;
                return d
              }}
              tooltip={i18n.str`Select time range to group dataset by`}
            />
            <InputNumber
              name="rangeCount"
              label={translateMap.get(activeFilter.range)![0]}
              tooltip={i18n.str`Select the number of ranges to include in data set`}

            />
            <InputSelector
              name="currency"
              label={i18n.str`Currency`}
              values={availableCurrencies}
              fromStr={(c) => {
                const idx = availableCurrencies.indexOf(c)
                if (idx === -1) return undefined;
                return c
              }}
              tooltip={i18n.str`Select the currency to show statistics for`}
            />
             </InputGroup>
           </FormProvider>
           </div>
        </div>
      </div>
      <div class="card has-table">
        <header class="card-header">
          <p class="card-header-title">
            <span class="icon">
              <i class="mdi mdi-shopping" />
            </span>
            {i18n.str`Revenue statistics over the past ${activeFilter.rangeCount} ${translateRange(activeFilter)} for currency '${activeFilter.currency}'`}
          </p>
        </header>
        <div class="card-content">
      {(chartData && chartLabels.length > 0) ? (
        (!showTable) ? (
          <Bar data={{labels: chartLabels, datasets: chartData as any}} options={chartOptions}/>
        ) : (
        <div class="b-table has-pagination">
            <div class="table-wrapper has-mobile-cards">
              <div class="table-container">
                <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
                  <thead>
                    <tr>
                      <th>
                        <i18n.Translate>Start time</i18n.Translate>
                      </th>
                     {chartData!.map((d) => {
                        return (
                          <Fragment key={d.label}>
                            <th>
                              {d.label}
                            </th>
                          </Fragment>
                        )})}
                    </tr>
                  </thead>
                  <tbody>
                     {chartLabels.map((l) => {
                        return (
                          <Fragment key={l}>
                            <tr key="info">
                              <td>
                              {format(new Date(l), formatMap.get(activeFilter.range)!)}
                              </td>
                              {chartData?.map((d) => {
                                return (
                                  <Fragment key={d.label}>
                                  <td>
                                  {getRevenueForLabelAndDataset(l, d)}
                                </td>
                                  </Fragment>
                              );})}
                            </tr>
                          </Fragment>
                        );
                      })}
                  </tbody>
                </table>
              </div>
            </div>
          </div>
        )
      ) : (
        <i>{i18n.str`No revenue statistics yet.`}</i>
      )}
        </div>
      </div>
      </Fragment>
  );
}
