import React, {
  createContext,
  useContext,
  useState,
  useEffect,
  useRef,
  FC,
} from "react";
import { HeaderConfig } from "@/lib/HeaderConfig";

import useInterval from "@/lib/useInterval";
import { useStationList } from "@/stateBox/useStationList";
import { checkDuplicateTrainData } from "@/lib/checkDuplicateTrainData";
import { getStationID } from "@/lib/eachTrainInfoCoreLib/getStationData";
import { trainDataType } from "@/lib/trainPositionTextArray";
  type loading = "loading" | "success" | "error";
const initialState = {
  webview: undefined,
  currentTrain: [],
  setCurrentTrain: (e) => {},
  currentTrainLoading: "loading" as loading,
  setCurrentTrainLoading: (e) => {},
  getCurrentTrain: () => {},
  inject: (i) => {},
  fixedPosition: null,
  setFixedPosition: (e) => {},
  setInjectData: (e) => {},
  getCurrentStationData: ((e) => {}) as (e: string) => trainDataType | undefined,
  getPosition: ((e) => {}) as (e: trainDataType) => string[] | undefined,
};

type initialStateType = {
  webview: React.MutableRefObject<any>;
  currentTrain: trainDataType[];
  setCurrentTrain: (e: trainDataType[]) => void;
  currentTrainLoading: loading;
  setCurrentTrainLoading: (e: loading) => void;
  getCurrentTrain: () => void;
  inject: (i: string) => void;
  fixedPosition: { type: "station" | "train"; value: string } | null;
  setFixedPosition: (e: { type: "station" | "train"; value: string } | null) => void;
  setInjectData: (e: { type: "station" | "train"; value: string; fixed: boolean }) => void;
  getCurrentStationData: (e: string) => trainDataType | undefined;
  getPosition: (e: trainDataType) => string[] | undefined;
};

const CurrentTrainContext = createContext<initialStateType>(initialState);

export const useCurrentTrain = () => {
  return useContext(CurrentTrainContext);
};
type props = {
  children: React.ReactNode;
}
export const CurrentTrainProvider:FC<props> = ({ children }) => {
  const [currentTrain, setCurrentTrain] = useState<trainDataType[]>([]); //現在在線中の全列車 { num: 列車番号, delay: 遅延時分(状態), Pos: 位置情報 }
  const [currentTrainLoading, setCurrentTrainLoading] =
    useState<loading>("loading");

  const { getInjectJavascriptAddress, stationList, originalStationList } =
    useStationList();

  const [fixedPosition, setFixedPosition] = useState<{
    type: "station" | "train";
    value: string;
  }>({
    type: null,
    value: null,
  });
  const [_, setIntervalState] = useInterval(
    () => {
      if (!webview.current) return;
      if (fixedPosition.type == "station") {
        const script = getInjectJavascriptAddress(fixedPosition.value);
        inject(script);
      } else if (fixedPosition.type == "train") {
        const currentTrain = getCurrentStationData(fixedPosition.value);
        const values = getPosition(currentTrain);
        if (!values) return;
        if (values[0] == "M12" || values[1] == "M12") {
          const script = getInjectJavascriptAddress("M12");
          inject(script);
          return;
        }

        const script = getInjectJavascriptAddress(
          values[values.length == 2 ? currentTrain.Direction : 0]
        );
        inject(script);
      }
    },
    5000, //60000,
    false
  );
  useEffect(() => {
    if (fixedPosition) {
      setIntervalState.start();
    } else {
      setIntervalState.stop();
    }
  }, [fixedPosition]);

  type getPositionFuncType = (currentTrainData: trainDataType) => string[] | undefined;
  const getPosition: getPositionFuncType = (currentTrainData) => {
    //currentTrainData.Pos = "鴨川～端岡"; //test
    if (!currentTrainData) return;
    if (!currentTrainData?.Pos) return;
    if (currentTrainData?.Pos.match("～")) {
      const pos = currentTrainData?.Pos.replace("（下り）", "")
        .replace("（上り）", "")
        .replace("（徳島線）", "")
        .replace("（高徳線）", "")
        .split("～");
      const direction = currentTrainData?.Direction || 0;
      if (pos[0] == "児島" && pos[1] == "宇多津") {
        return ["M12", "Y09"];
      } else if (pos[1] == "児島" && pos[0] == "宇多津") {
        return ["Y09", "M12"];
      } else if (pos[0] == "伊予若宮" && pos[1] == "伊予白滝") {
        return ["S18", "S14"];
      } else if (pos[0] == "伊予白滝" && pos[1] == "伊予若宮") {
        return ["S14", "S18"];
      } else if (pos[0] == "伊予大洲" && pos[1] == "伊予若宮") {
        return ["U14", "U14"];
      } else if (pos[0] == "伊予若宮" && pos[1] == "伊予大洲") {
        return ["U14", "U14"];
      }
      const currentPosID = Object.keys(originalStationList).map((key) => {
        let firstStation = false;
        let firstStationID = "";
        let secondStation = false;
        let secondStationID = "";
        originalStationList[key].forEach((station) => {
          if (station.Station_JP === pos[0]) {
            firstStation = true;
            firstStationID = station.StationNumber;
          }
          if (station.Station_JP === pos[1]) {
            secondStation = true;
            secondStationID = station.StationNumber;
          }
        });
        if (firstStation && secondStation) {
          return [firstStationID, secondStationID];
        } else return false;
      });
      const currentPos = currentPosID.filter((d) => d != false)[0];
      if (currentPos) {
        return direction == 0 ? currentPos.reverse() : currentPos;
      } else if (direction == 0) {
        return [
          getStationID(pos[1], stationList),
          getStationID(pos[0], stationList),
        ];
      } else {
        return [
          getStationID(pos[0], stationList),
          getStationID(pos[1], stationList),
        ];
      }
    } else {
      return [getStationID(currentTrainData?.Pos, stationList)];
    }
  };
  const getCurrentStationData: (e: string) => trainDataType | undefined = (
    e
  ) => {
    //e:trainNumber
    if (!currentTrain.length) return;
    return checkDuplicateTrainData(
      currentTrain.filter((d) => d.num == e),
      stationList
    );
  };

  type injectDataType = {
    type: "station" | "train";
    value: string;
    fixed: boolean;
  };
  type injectDataFuncType = (data: injectDataType) => void;
  const setInjectData: injectDataFuncType = ({ type, value, fixed }) => {
    if (type === "station") {
      const script = getInjectJavascriptAddress(value);
      inject(script);
    } else if (type === "train") {
      const currentTrain = getCurrentStationData(value);
      const values = getPosition(currentTrain);
      if (!values) return;
      let script;
      if (values[0] == "M12" || values[1] == "M12") {
        script = getInjectJavascriptAddress("M12");
      } else {
        const valuesIndex = values.length == 2 ? currentTrain.Direction : 0;
        script = getInjectJavascriptAddress(values[valuesIndex]);
      }
      inject(script);
    }
    if (fixed) {
      setFixedPosition({ type, value });
    }
  };
  const getCurrentTrain = () => {
    fetch("https://n8n.haruk.in/webhook/c501550c-7d1b-4e50-927b-4429fe18931a")
      .then((response) => response.json())
      .then((d) => d.data)
      .then((d) =>
        d.map((x) => ({
          Index: x.Index,
          num: x.TrainNum,
          delay: x.delay,
          Pos: x.Pos,
          PosNum: x.PosNum,
          Direction: x.Direction,
          Type: x.Type,
          Line: x.Line,
        }))
      )
      .then((d) => {
        setCurrentTrain(d);
        setCurrentTrainLoading("success");
      })
      .catch(() => {
        //alert("現在の全在線列車取得エラー/再取得します");
        fetch(
          "https://script.google.com/macros/s/AKfycby9Y2-Bm75J_WkbZimi7iS8v5r9wMa9wtzpdwES9sOGF4i6HIYEJOM60W6gM1gXzt1o/exec",
          HeaderConfig
        )
          .then((response) => response.json())
          .then((d) =>
            d.map((x) => ({ num: x.TrainNum, delay: x.delay, Pos: x.Pos }))
          )
          .then((d) => {
            setCurrentTrain(d);
            setCurrentTrainLoading("success");
          })
          .catch(() => {
            // エラー時の処理
            setCurrentTrainLoading("error");
          });
      });
  };
  const inject = (i) => {
    webview.current?.injectJavaScript(i);
  };

  useEffect(() => {
    getCurrentTrain();
  }, []); //初回だけ現在の全在線列車取得

  useInterval(getCurrentTrain, 15000); //15秒毎に全在線列車取得

  const webview = useRef();
  return (
    <CurrentTrainContext.Provider
      value={{
        webview,
        currentTrain,
        setCurrentTrain,
        currentTrainLoading,
        setCurrentTrainLoading,
        getCurrentTrain,
        inject,
        setInjectData,
        getCurrentStationData,
        getPosition,
        fixedPosition,
        setFixedPosition,
      }}
    >
      {children}
    </CurrentTrainContext.Provider>
  );
};
