import { Button } from "../components/Button.tsx";
import { useEffect, useRef } from "preact/hooks";
import { ComponentChildren } from "preact";
import { Signal, useSignal } from "@preact/signals";
import { IS_BROWSER } from "$fresh/runtime.ts";
import { mapValues } from "$std/collections/map_values.ts";

interface StockProps {
  pageName: string;
}

interface ToggleButtonProps {
  disabled?: boolean;
  toggle: Signal<boolean>;
  children?: ComponentChildren;
}

function ToggleButton(props: ToggleButtonProps) {
  const { disabled, toggle, ...rest } = props;
  return (
    <button
      {...rest}
      disabled={!IS_BROWSER || disabled}
      onClick={() => toggle.value = !toggle.value}
      class={"px-2 py-1 border-2 rounded transition-colors" + (
        toggle.value
          ? "border-gray-500 bg-white hover:bg-gray-200"
          : "border-gray-200 bg-gray-800 hover:bg-gray-500 text-white"
      )}
    />
  );
}

type QueryStatus<T> = {
  type: "loading";
} | {
  type: "complete";
  data: T;
} | {
  type: "error";
  err: Error;
};

function useAsync<T>(fn: () => Promise<T>): Signal<QueryStatus<T>> {
  const state = useSignal({
    type: "loading",
  } as QueryStatus<T>);
  useEffect(() => {
    (async () => {
      try {
        const data = await fn();
        state.value = {
          type: "complete",
          data: data,
        };
      } catch (err) {
        state.value = {
          type: "error",
          err: err,
        };
      }
    })();
  }, []);
  return state;
}

interface Coperation {
  Name: string;
  Code: string;
  Sector: string;
  Product: string;
  ListingDay: string;
  ClosingMonth: string;
  Representative: string;
  Homepage: string;
  AddressArea: string;
  LastUpdate: string;
}

interface PageCorpsInfo {
  name: string;
  description: string;
  corpListByDate: Record<string, Coperation[]>;
}

interface CorpSimple {
  code: string;
  name: string;
}

function StockListByDate({prevSet, rows, name}:{prevSet:Set<string>, 
  rows:Coperation[],
name: string}){
  const parent = useRef<HTMLDivElement>(null);
  useEffect(()=>{
    (async ()=>{
      console.log("animation mount on ",name);
      const {default:autoAnimate} = await import("https://esm.sh/@formkit/auto-animate@0.7.0");
      parent.current && autoAnimate(parent.current)
    })();
  },[parent]);

  return <div ref={parent}>
  <h2 class="text-lg">{name}</h2>
  {rows.map((row) => {
    const firstOccur = !prevSet.has(row.Code);
    return (
      <div
        key={row.Code}
        class={[
          "bg-white",
          firstOccur ? "text-[#ff5454]" : "text-black",
        ].join(" ")}
      >
        <a href={`https://stockplus.com/m/stocks/KOREA-A${row.Code}`}>
          {row.Name}
        </a>
      </div>
    );
  })}
</div>
}

function StockList({ data }: { data: PageCorpsInfo }) {
  console.log("data");

  const corpListByDate = data.corpListByDate;
  const keys = Object.keys(corpListByDate).sort().reverse().slice(0, 5)
    .reverse();
  const sets = keys.map((x) => new Set(corpListByDate[x].map((y) => y.Code)));
  //const rows = data.corpListbyDate;
  return (
    <div class="flex">
      {keys.map((x, i) => {
        const prevSet = i == 0 ? new Set<string>() : sets[i - 1];
        const rows = corpListByDate[x];
        return (
          <StockListByDate key={x} name={x} prevSet={prevSet} rows={rows}></StockListByDate>
        );
      })}
    </div>
  );
}


type FilterInfoOption = {
  list: {
    items: CorpSimple[];
    include: boolean;
  }[];
  otherwise: boolean;
};

function filterInfo(info: Coperation[], filterList: FilterInfoOption) {
  const checkMap = new Map<string, boolean>();
  for (const l of filterList.list) {
    for (const i of l.items) {
      checkMap.set(i.code, l.include);
    }
  }
  return info.filter((x) => {
    const v = checkMap.get(x.Code);
    if (v === undefined) {
      return filterList.otherwise;
    } else {
      return v;
    }
  });
}

export default function StockListUI(props: StockProps) {
  const sig = useAsync<[PageCorpsInfo, CorpSimple[], CorpSimple[]]>(async () => {
    const res = await Promise.all([
      fetch("/api/pages/" + encodeURIComponent(props.pageName)),
      fetch("/api/kospi"),
      fetch("/api/kosdaq"),
    ]);
    const corpsInfo = await res[0].json() as PageCorpsInfo;
    const kospi = await res[1].json();
    const kosdaq = await res[2].json();
    return [corpsInfo, kospi, kosdaq];
  });
  const viewKospi = useSignal(true);
  const viewKosdaq = useSignal(false);
  const viewOtherwise = useSignal(false);
  return (
    <div class="my-2">
      <div class="flex gap-2">
        <ToggleButton toggle={viewKospi}>Kospi</ToggleButton>
        <ToggleButton toggle={viewKosdaq}>Kosdaq</ToggleButton>
        <ToggleButton toggle={viewOtherwise}>Otherwise</ToggleButton>
      </div>
      <div class="flex gap-8 py-6 flex-col">
        {sig.value.type == "loading"
          ? (new Array(20).fill(0).map((_) => (
            <div class="animate-pulse bg-gray-300 p-2"></div>
          )))
          : (
            <div>
              {sig.value.type == "error"
                ? (
                  <div>
                    <p>File Loading Failed</p>
                  </div>
                )
                : <StockList data={applyFilter(sig.value.data[0], sig.value.data[1], sig.value.data[2])}></StockList>}
            </div>
          )}
      </div>
    </div>
  );
  function applyFilter(data: PageCorpsInfo, kospi: CorpSimple[], kosdaq: CorpSimple[]): PageCorpsInfo{
    const filter = getFilters(kospi,kosdaq);
    return {
      name: data.name,
      description: data.description,
      corpListByDate: mapValues(data.corpListByDate, (it: Coperation[])=>{
        return filterInfo(it, filter);
      })
    }
  }
  function getFilters(kospi: CorpSimple[], kosdaq: CorpSimple[]): FilterInfoOption{
    return {
      otherwise: viewOtherwise.value,
      list: [{
          include: viewKospi.value,
          items: kospi
        },
        {
          include: viewKosdaq.value,
          items: kosdaq
        }
      ]
    }
  }
}
