/*
 This file is part of GNU Taler
 (C) 2022-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/>
 */
import {
  AmlDecision,
  EventsDerivation_TOPS,
  TalerFormAttributes,
} from "@gnu-taler/taler-util";
import {
  FormDesign,
  FormUI,
  InternationalizationAPI,
  onComponentUnload,
  SelectUiChoice,
  useForm,
  useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { h, VNode } from "preact";
import {
  DecisionRequest,
  useCurrentDecisionRequest,
} from "../../hooks/decision-request.js";

const TALER_SCREEN_ID = 108;

/**
 * Trigger additional events
 *
 * @param param0
 * @returns
 */
export function Events(): VNode {
  const { i18n } = useTranslationContext();
  const [request, updateRequest] = useCurrentDecisionRequest();
  // const [pref] = usePreferences();
  // const { config } = useExchangeApiContext();

  // const dialect =
  //   (pref.testingDialect ? undefined : config.config.aml_spa_dialect) ??
  //   AmlSpaDialect.TESTING;

  function ShowEventForm({ events: calculatedEvents }: { events: Events }) {
    const design = formDesign(i18n, calculatedEvents);

    const calculated =
      request.triggering_events === undefined
        ? calculatedEvents.triggered
        : request.triggering_events.filter((name) =>
            calculatedEvents.triggered.includes(name),
          );

    const rest =
      request.triggering_events === undefined
        ? []
        : request.triggering_events.filter((name) =>
            calculatedEvents.rest.includes(name),
          );

    const form = useForm<FormType>(design, {
      calculated,
      rest,
    });

    onComponentUnload(() => {
      updateRequest("onload event", {
        custom_events: !form.status.result.custom
          ? []
          : form.status.result.custom,
        triggering_events: [
          ...(form.status.result.calculated ?? []),
          ...(form.status.result.rest ?? []),
        ],
      });
    });

    return (
      <div>
        <FormUI design={design} model={form.model} />
      </div>
    );
  }

  const events = calculateEventsBasedOnState(
    request.original,
    request,
    // i18n,
    // dialect,
  );
  return <ShowEventForm events={events} />;
}

type Events = {
  triggered: string[];
  rest: string[];
};

type FormType = {
  calculated: string[];
  rest: string[];
  custom: string[];
};

const formDesign = (
  i18n: InternationalizationAPI,
  events: {
    triggered: string[];
    rest: string[];
  },
): FormDesign => ({
  type: "double-column",
  sections: [
    {
      title: i18n.str`Events`,
      description: i18n.str`The events will be triggered only after the decision has been confirmed.`,
      fields: [
        {
          type: "selectMultiple",
          id: "calculated",
          label: i18n.str`Calculated`,
          help: i18n.str`Events based on properties and new attributes that should be triggered`,
          choices: events.triggered.map(
            (name) =>
              ({
                label: name,
                value: name,
              }) as SelectUiChoice,
          ),
        },
        {
          type: "selectMultiple",
          id: "rest",
          label: i18n.str`Others`,
          help: i18n.str`Events that can be triggered manually`,
          choices: events.rest.map(
            (name) =>
              ({
                label: name,
                value: name,
              }) as SelectUiChoice,
          ),
        },
        {
          id: "custom",
          type: "array",
          label: i18n.str`Custom list`,
          help: i18n.str`Events without built-in support.`,
          labelFieldId: "name",
          fields: [
            {
              type: "text",
              label: i18n.str`Name`,
              id: "name",
            },
          ],
        },
      ],
    },
  ],
});

// function labelForEvent_tops(
//   event: TOPS_AmlEventsName,
//   i18n: InternationalizationAPI,
// ) {
//   switch (event) {
//     case TOPS_AmlEventsName.INCR_ACCOUNT_OPEN:
//     case TOPS_AmlEventsName.DECR_ACCOUNT_OPEN:
//     case TOPS_AmlEventsName.INCR_HIGH_RISK_CUSTOMER:
//     case TOPS_AmlEventsName.DECR_HIGH_RISK_CUSTOMER:
//     case TOPS_AmlEventsName.INCR_HIGH_RISK_COUNTRY:
//     case TOPS_AmlEventsName.DECR_HIGH_RISK_COUNTRY:
//     case TOPS_AmlEventsName.INCR_PEP:
//     case TOPS_AmlEventsName.DECR_PEP:
//     case TOPS_AmlEventsName.INCR_PEP_FOREIGN:
//     case TOPS_AmlEventsName.DECR_PEP_FOREIGN:
//     case TOPS_AmlEventsName.INCR_PEP_DOMESTIC:
//     case TOPS_AmlEventsName.DECR_PEP_DOMESTIC:
//     case TOPS_AmlEventsName.INCR_PEP_INTERNATIONAL_ORGANIZATION:
//     case TOPS_AmlEventsName.DECR_PEP_INTERNATIONAL_ORGANIZATION:
//     case TOPS_AmlEventsName.MROS_REPORTED_SUSPICION_SIMPLE:
//     case TOPS_AmlEventsName.MROS_REPORTED_SUSPICION_SUBSTANTIATED:
//     case TOPS_AmlEventsName.INCR_INVESTIGATION_CONCLUDED:
//     case TOPS_AmlEventsName.DECR_INVESTIGATION_CONCLUDED:
//       // case TOPS_AmlEventsName.ACCOUNT_OPENED:
//       return i18n.str`Account opened`;
//     // case TOPS_AmlEventsName.ACCOUNT_CLOSED:
//     //   return i18n.str`Account closed`;
//     // case TOPS_AmlEventsName.ACCOUNT_OPENED_HIGH_RISK:
//     //   return i18n.str`High risk account incorporated`;
//     // case TOPS_AmlEventsName.ACCOUNT_CLOSED_HIGH_RISK:
//     //   return i18n.str`High risk account removed`;
//     // case TOPS_AmlEventsName.ACCOUNT_OPENED_DOMESTIC_PEP:
//     //   return i18n.str`Account from dometic PEP incorporated`;
//     // case TOPS_AmlEventsName.ACCOUNT_CLOSED_DOMESTIC_PEP:
//     //   return i18n.str`Account from dometic PEP removed`;
//     // case TOPS_AmlEventsName.ACCOUNT_OPENED_FOREIGN_PEP:
//     //   return i18n.str`Account from foreign PEP incorporated`;
//     // case TOPS_AmlEventsName.ACCOUNT_CLOSED_FOREIGN_PEP:
//     //   return i18n.str`Account from foreign PEP removed`;
//     // case TOPS_AmlEventsName.ACCOUNT_OPENED_HR_COUNTRY:
//     //   return i18n.str`Account from high-risk country incorporated`;
//     // case TOPS_AmlEventsName.ACCOUNT_CLOSED_HR_COUNTRY:
//     //   return i18n.str`Account from high-risk country removed`;
//     // case TOPS_AmlEventsName.ACCOUNT_MROS_REPORTED_SUSPICION_SIMPLE:
//     //   return i18n.str`MROS reported by obligation`;
//     // case TOPS_AmlEventsName.ACCOUNT_MROS_REPORTED_SUSPICION_SUBSTANTIATED:
//     //   return i18n.str`MROS reported by right`;
//     // case TOPS_AmlEventsName.ACCOUNT_INVESTIGATION_COMPLETED:
//     //   return i18n.str`Investigations after Art 6 Gwg completed`;
//     // case TOPS_AmlEventsName.ACCOUNT_INVESTIGATION_STARTED:
//     //   return i18n.str`Investigations after Art 6 Gwg started`;
//     // case TOPS_AmlEventsName.ACCOUNT_OPENED_INT_ORG_PEP:
//     //   return i18n.str`Account from international organization PEP incorporated`;
//     // case TOPS_AmlEventsName.ACCOUNT_CLOSED_INT_ORG_PEP:
//     //   return i18n.str`Account from international organization PEP removed`;
//     default: {
//       assertUnreachable(event);
//     }
//   }
// }

// function labelForEvent_gls(
//   event: GLS_AmlEventsName,
//   i18n: InternationalizationAPI,
// ) {
//   switch (event) {
//     case GLS_AmlEventsName.ACCOUNT_OPENED:
//       return i18n.str`Account opened`;
//     case GLS_AmlEventsName.ACCOUNT_CLOSED:
//       return i18n.str`Account closed`;
//     default: {
//       assertUnreachable(event);
//     }
//   }
// }

function calculateEventsBasedOnState(
  currentState: AmlDecision | undefined,
  request: DecisionRequest,
  // i18n: InternationalizationAPI,
  // dialect: AmlSpaDialect,
): Events {
  const init: Events = { triggered: [], rest: [] };
  const form = (request.attributes ?? {}) as Record<string, unknown>;
  const formId = form[TalerFormAttributes.FORM_ID]! as string;
  return Object.entries(EventsDerivation_TOPS).reduce((prev, [name, info]) => {
    if (
      info.shouldBeTriggered(
        formId,
        currentState?.limits?.rules,
        request.rules,
        currentState?.properties,
        request.properties,
        form,
      )
    ) {
      prev.triggered.push(name);
    } else {
      prev.rest.push(name);
    }
    return prev;
  }, init);
}
