import { Fragment, VNode, h } from "preact";
import {
  AmlDecisionDetail,
  AmlDecisionDetails,
  AmlState,
  KycDetail,
} from "../types.js";
import {
  AbsoluteTime,
  AmountJson,
  Amounts,
  TranslatedString,
} from "@gnu-taler/taler-util";
import { format } from "date-fns";
import { ArrowDownCircleIcon, ClockIcon } from "@heroicons/react/20/solid";
import { useState } from "preact/hooks";
import { NiceForm } from "../NiceForm.js";
import { FlexibleForm } from "../forms/index.js";
import { UIFormField } from "../handlers/forms.js";
import { Pages } from "../pages.js";

const response: AmlDecisionDetails = {
  aml_history: [
    {
      justification: "Lack of documentation",
      decider_pub: "ASDASDASD",
      decision_time: {
        t_s: Date.now() / 1000,
      },
      new_state: 2,
      new_threshold: "USD:0",
    },
    {
      justification: "Doing a transfer of high amount",
      decider_pub: "ASDASDASD",
      decision_time: {
        t_s: Date.now() / 1000 - 60 * 60 * 24 * 30 * 6,
      },
      new_state: 1,
      new_threshold: "USD:2000",
    },
    {
      justification: "Account is known to the system",
      decider_pub: "ASDASDASD",
      decision_time: {
        t_s: Date.now() / 1000 - 60 * 60 * 24 * 30 * 9,
      },
      new_state: 0,
      new_threshold: "USD:100",
    },
  ],
  kyc_attributes: [
    {
      collection_time: {
        t_s: Date.now() / 1000 - 60 * 60 * 24 * 30 * 8,
      },
      expiration_time: {
        t_s: Date.now() / 1000 - 60 * 60 * 24 * 30 * 4,
      },
      provider_section: "asdasd",
      attributes: {
        name: "Sebastian",
      },
    },
    {
      collection_time: {
        t_s: Date.now() / 1000 - 60 * 60 * 24 * 30 * 5,
      },
      expiration_time: {
        t_s: Date.now() / 1000 - 60 * 60 * 24 * 30 * 2,
      },
      provider_section: "asdasd",
      attributes: {
        creditCard: "12312312312",
      },
    },
  ],
};
type AmlEvent = AmlFormEvent | KycCollectionEvent | KycExpirationEvent;
type AmlFormEvent = {
  type: "aml-form";
  when: AbsoluteTime;
  title: TranslatedString;
  state: AmlState;
  threshold: AmountJson;
};
type KycCollectionEvent = {
  type: "kyc-collection";
  when: AbsoluteTime;
  title: TranslatedString;
  values: object;
  provider: string;
};
type KycExpirationEvent = {
  type: "kyc-expiration";
  when: AbsoluteTime;
  title: TranslatedString;
  fields: string[];
};

type WithTime = { when: AbsoluteTime };

function selectSooner(a: WithTime, b: WithTime) {
  return AbsoluteTime.cmp(a.when, b.when);
}

function getEventsFromAmlHistory(
  aml: AmlDecisionDetail[],
  kyc: KycDetail[],
): AmlEvent[] {
  const ae: AmlEvent[] = aml.map((a) => {
    return {
      type: "aml-form",
      state: a.new_state,
      threshold: Amounts.parseOrThrow(a.new_threshold),
      title: a.justification as TranslatedString,
      when: {
        t_ms:
          a.decision_time.t_s === "never"
            ? "never"
            : a.decision_time.t_s * 1000,
      },
    } as AmlEvent;
  });
  const ke = kyc.reduce((prev, k) => {
    prev.push({
      type: "kyc-collection",
      title: "collection" as TranslatedString,
      when: AbsoluteTime.fromProtocolTimestamp(k.collection_time),
      values: !k.attributes ? {} : k.attributes,
      provider: k.provider_section,
    });
    prev.push({
      type: "kyc-expiration",
      title: "expired" as TranslatedString,
      when: AbsoluteTime.fromProtocolTimestamp(k.expiration_time),
      fields: !k.attributes ? [] : Object.keys(k.attributes),
    });
    return prev;
  }, [] as AmlEvent[]);
  return ae.concat(ke).sort(selectSooner);
}

export function AccountDetails({ account }: { account?: string }) {
  const events = getEventsFromAmlHistory(
    response.aml_history,
    response.kyc_attributes,
  );
  console.log("DETAILS", events, events[events.length - 1 - 2]);
  const [selected, setSelected] = useState<AmlEvent>(
    events[events.length - 1 - 2],
  );
  return (
    <div>
      <a
        href={Pages.newFormEntry.url({ account })}
        class="m-4 block rounded-md w-fit border-0 px-3 py-2 text-center text-sm bg-indigo-700 text-white shadow-sm hover:bg-indigo-700"
      >
        New AML form
      </a>

      <header class="flex items-center justify-between border-b border-white/5 px-4 py-4 sm:px-6 sm:py-6 lg:px-8">
        <h1 class="text-base font-semibold leading-7 text-black">
          Case history
        </h1>
      </header>
      <div class="flow-root">
        <ul role="list">
          {events.map((e, idx) => {
            const isLast = events.length - 1 === idx;
            return (
              <li
                class="hover:bg-gray-200 p-2 rounded cursor-pointer"
                onClick={() => {
                  setSelected(e);
                }}
              >
                <div class="relative pb-6">
                  {!isLast ? (
                    <span
                      class="absolute left-4 top-4 -ml-px h-full w-1 bg-gray-200"
                      aria-hidden="true"
                    ></span>
                  ) : undefined}
                  <div class="relative flex space-x-3">
                    {(() => {
                      switch (e.type) {
                        case "aml-form": {
                          switch (e.state) {
                            case AmlState.normal: {
                              return (
                                <div>
                                  <span class="inline-flex items-center rounded-md bg-green-50 px-2 py-1 text-xs font-medium text-green-700 ring-1 ring-inset ring-green-600/20">
                                    Normal
                                  </span>
                                  <span class="inline-flex items-center  px-2 py-1 text-xs font-medium text-gray-700 ">
                                    {e.threshold.currency}{" "}
                                    {Amounts.stringifyValue(e.threshold)}
                                  </span>
                                </div>
                              );
                            }
                            case AmlState.pending: {
                              return (
                                <div>
                                  <span class="inline-flex items-center rounded-md bg-yellow-50 px-2 py-1 text-xs font-medium text-yellow-700 ring-1 ring-inset ring-green-600/20">
                                    Pending
                                  </span>
                                  <span class="inline-flex items-center  px-2 py-1 text-xs font-medium text-gray-700 ">
                                    {e.threshold.currency}{" "}
                                    {Amounts.stringifyValue(e.threshold)}
                                  </span>
                                </div>
                              );
                            }
                            case AmlState.frozen: {
                              return (
                                <div>
                                  <span class="inline-flex items-center rounded-md bg-red-50 px-2 py-1 text-xs font-medium text-red-700 ring-1 ring-inset ring-green-600/20">
                                    Frozen
                                  </span>
                                  <span class="inline-flex items-center  px-2 py-1 text-xs font-medium text-gray-700 ">
                                    {e.threshold.currency}{" "}
                                    {Amounts.stringifyValue(e.threshold)}
                                  </span>
                                </div>
                              );
                            }
                          }
                        }
                        case "kyc-collection": {
                          return (
                            <ArrowDownCircleIcon class="h-8 w-8 text-green-700" />
                          );
                        }
                        case "kyc-expiration": {
                          return <ClockIcon class="h-8 w-8 text-gray-700" />;
                        }
                      }
                    })()}
                    <div class="flex min-w-0 flex-1 justify-between space-x-4 pt-1.5">
                      <div>
                        <p class="text-sm text-gray-900">{e.title}</p>
                      </div>
                      <div class="whitespace-nowrap text-right text-sm text-gray-500">
                        {e.when.t_ms === "never" ? (
                          "never"
                        ) : (
                          <time dateTime={format(e.when.t_ms, "dd MMM yyyy")}>
                            {format(e.when.t_ms, "dd MMM yyyy")}
                          </time>
                        )}
                      </div>
                    </div>
                  </div>
                </div>
              </li>
            );
          })}
        </ul>
      </div>
      {selected && <ShowEventDetails event={selected} />}
      {selected && <ShowConsolidated history={events} until={selected} />}
    </div>
  );
}

function ShowEventDetails({ event }: { event: AmlEvent }): VNode {
  return <div>type {event.type}</div>;
}

function ShowConsolidated({
  history,
  until,
}: {
  history: AmlEvent[];
  until: AmlEvent;
}): VNode {
  console.log("UNTIL", until);
  const cons = getConsolidated(history, until.when);

  const form: FlexibleForm<Consolidated> = {
    versionId: "1",
    behavior: (form) => {
      return {};
    },
    design: [
      {
        title: "AML" as TranslatedString,
        fields: [
          {
            type: "amount",
            props: {
              label: "Threshold" as TranslatedString,
              name: "aml.threshold",
            },
          },
          {
            type: "choiceHorizontal",
            props: {
              label: "State" as TranslatedString,
              name: "aml.state",
              converter: amlStateConverter,
              choices: [
                {
                  label: "Frozen" as TranslatedString,
                  value: AmlState.frozen,
                },
                {
                  label: "Pending" as TranslatedString,
                  value: AmlState.pending,
                },
                {
                  label: "Normal" as TranslatedString,
                  value: AmlState.normal,
                },
              ],
            },
          },
        ],
      },
      Object.entries(cons.kyc).length > 0
        ? {
            title: "KYC" as TranslatedString,
            fields: Object.entries(cons.kyc).map(([key, field]) => {
              const result: UIFormField = {
                type: "text",
                props: {
                  label: key as TranslatedString,
                  name: `kyc.${key}.value`,
                  help: `${field.provider} since ${
                    field.since.t_ms === "never"
                      ? "never"
                      : format(field.since.t_ms, "dd/MM/yyyy")
                  }` as TranslatedString,
                },
              };
              return result;
            }),
          }
        : undefined,
    ],
  };
  return (
    <Fragment>
      <h1 class="text-base font-semibold leading-7 text-black">
        Consolidated information after{" "}
        {until.when.t_ms === "never"
          ? "never"
          : format(until.when.t_ms, "dd MMMM yyyy")}
      </h1>
      <NiceForm
        key={`${String(Date.now())}`}
        form={form}
        initial={cons}
        onUpdate={() => {}}
      />
    </Fragment>
  );
}

interface Consolidated {
  aml: {
    state?: AmlState;
    threshold?: AmountJson;
    since: AbsoluteTime;
  };
  kyc: {
    [field: string]: {
      value: any;
      provider: string;
      since: AbsoluteTime;
    };
  };
}

function getConsolidated(
  history: AmlEvent[],
  when: AbsoluteTime,
): Consolidated {
  const initial: Consolidated = {
    aml: {
      since: AbsoluteTime.never(),
    },
    kyc: {},
  };
  return history.reduce((prev, cur) => {
    if (AbsoluteTime.cmp(when, cur.when) < 0) {
      return prev;
    }
    switch (cur.type) {
      case "kyc-expiration": {
        cur.fields.forEach((field) => {
          delete prev.kyc[field];
        });
        break;
      }
      case "aml-form": {
        prev.aml.threshold = cur.threshold;
        prev.aml.state = cur.state;
        prev.aml.since = cur.when;
        break;
      }
      case "kyc-collection": {
        Object.keys(cur.values).forEach((field) => {
          prev.kyc[field] = {
            value: (cur.values as any)[field],
            provider: cur.provider,
            since: cur.when,
          };
        });
        break;
      }
    }
    return prev;
  }, initial);
}

export const amlStateConverter = {
  toStringUI: stringifyAmlState,
  fromStringUI: parseAmlState,
};

function stringifyAmlState(s: AmlState | undefined): string {
  if (s === undefined) return "";
  switch (s) {
    case AmlState.normal:
      return "normal";
    case AmlState.pending:
      return "pending";
    case AmlState.frozen:
      return "frozen";
  }
}

function parseAmlState(s: string | undefined): AmlState {
  switch (s) {
    case "normal":
      return AmlState.normal;
    case "pending":
      return AmlState.pending;
    case "frozen":
      return AmlState.frozen;
    default:
      throw Error(`unknown AML state: ${s}`);
  }
}
