import React, {FC, useState, useEffect, useRef} from 'react';
import {Loadable} from '../store';
import AsyncButton from '../components/AsyncButton';

type AppCommit = {
  id: number;
  remark: string;
  publishStatus: string;
  isPublished: boolean;
  createdAt: string;
};

async function fetchCommits(appId: string): Promise<AppCommit[]> {
    return fetch(`${process.env.REACT_APP_SERVER_URL}/plugin-server/home/${appId}/commits`)
    .then(res => res.json());
}

const dateFormatter = Intl.DateTimeFormat("en-US", {
  dateStyle: 'long',
  timeStyle: 'short'
});

function CommitManagerRenderer(props: {commits: Loadable<AppCommit[]>; onRefresh: () => Promise<void>;}) {
  const inputEl = useRef<HTMLInputElement>(null);
  const requestAppSave = () => {
    return new Promise((resolve, reject) => {
      if (inputEl.current) {
        const message = inputEl.current.value;
        window.parent.postMessage({type: "requestAppConfigSave", message}, "*");
        setTimeout(() => {resolve({})}, 10000);
      } else {
        alert("whelp!! I give up!");
        reject();
      }
    });
  }

  const {commits} = props;
  let loadingState = null;
  if (commits.loadingInfo.status === "notstarted") {
    loadingState = <div>Not started yet! Stale data displayed</div>;
  } else if (commits.loadingInfo.status === "inprogress") {
    loadingState = <div>Loading... </div>;
  } else if (commits.loadingInfo.status === "error") {
    loadingState = <div>Error: {commits.loadingInfo.errorMessage}</div>;
  }

  let commitsList = [<div>No data!</div>];
  if (commits.payload?.length > 0) {
    commitsList = commits.payload.map(commit => {
      return (<div key={commit.id} className="m-2 border">
        <div className="text-sm">{dateFormatter.format(new Date(commit.createdAt))}</div>
        <div className="text-sm">({commit.id})&nbsp;{commit.remark}</div>
        <div className="flex flex-row justify-between">
          {commit.isPublished ? <div className="text-sm border">Published</div> : null}
          <div className="text-sm border">{commit.publishStatus}</div>
        </div>
      </div>);
    });
  }

  return (<div className="border">
    <div className="flex flex-row">
      <input ref={inputEl} placeholder="message"/>
      <AsyncButton label="request appsave" onClick={requestAppSave} />
    </div>
    <AsyncButton label="refresh" onClick={props.onRefresh} />
    {loadingState}
    {commitsList}
  </div>);
}

type CommitManagerProps = {
  appId: string;
};

const CommitManager: FC<CommitManagerProps> = function CommitManager({appId}) {
  const [commits, setCommits] = useState<Loadable<AppCommit[]>>({
    loadingInfo: {
      status: "notstarted",
      errorMessage: "",
      error: null
    },
    payload: []
  });

  const handleCommitFetch = async (appId: string) => {
    setCommits(prev => ({
      loadingInfo: {
        status: "inprogress",
        errorMessage: "",
        error: null
      },
      payload: prev.payload
    }));

    return fetchCommits(appId)
      .then(commits => setCommits({
        loadingInfo: {
          status: "success",
          errorMessage: "",
          error: null
        },
        payload: commits
      }))
      .catch(err => {
        setCommits(prev => ({
          loadingInfo: {
            status: "error",
            errorMessage: err.message,
            error: err
          },
          payload: prev.payload
        }))
      });
  };

  useEffect(() => {
    handleCommitFetch(appId);
  }, [appId]);  

  return <CommitManagerRenderer commits={commits} onRefresh={() => handleCommitFetch(appId)}/>;
}

export default CommitManager;
