import { useState, Fragment, useEffect } from 'react';
import {
  Box, Footer,
  StyledCheckbox, Title,
  WidgetWrapper, LabelText, Spinner,
} from '../../components/ui/Widget';
import "../../utils/configureFormats";
import Modal from '../../components/Modal';
import { IconList } from '../../components/IconList';
import { LinkArrowIcon } from '../../components/LinkArrowIcon';
import { ArrowDownIcon } from '../../components/ArrowDownIcon';
import { Environment, Market, Policy } from 'rm-sdk/build/types';
import BigNumber from "bignumber.js";
import { Web3Provider } from '@ethersproject/providers';
import { getBuyPolicyUrl, getPolicyDetailUrl, renderTemplateString } from '../../utils/commonUtils';
import { QuoteLoader } from '../../helpers/quote-loader';
import { toSuffixFormat } from '../../utils/configureFormats';
import { EntityValue } from 'rm-sdk/build/services/api.service';
import { insertLinksAndSpinnersInString } from '../../utils/uiUtils';

import "./styles.scss";
import { AtomicaLightLogo } from '../../components/ui/AtomicaLightLogo';

const DEFAULT_ACTIVE_PROTECTION_TITLE = "You are covered for {coverage} {coverageCurrency} by a group policy";
const DEFAULT_NO_PROTECTION_TITLE = "No protection activated yet";

export const PolicyWidgetConstants = {
  DEFAULT_ACTIVE_PROTECTION_TITLE,
  DEFAULT_NO_PROTECTION_TITLE,
};

interface IProps {
  provider: Web3Provider;
  environment: Environment | string;
  policyId: string;
  className?: string;
  activeProtectionTitle?: string;
  noProtectionTitle?: string;
  incomeApyRate?: string;
  inlineMode?: boolean;
}

export function PolicyWidget({
  provider,
  policyId,
  environment,
  className,
  activeProtectionTitle,
  noProtectionTitle,
  incomeApyRate,
  inlineMode,
}: IProps) {
  const [quoteLoader, setQuoteLoader] = useState(new QuoteLoader(environment));

  const [policy, setPolicy] = useState<Policy>();
  const [titleProps, setTitleProps] = useState<any>({});
  const [marketEntities, setMarketEntities] = useState<Array<EntityValue | undefined>>([]);
  const [policyActualCoverage, setPolicyActualCoverage] = useState<string>();
  const [totalMarketCapacity, setTotalMarketCapacity] = useState<BigNumber>();
  const [totalMarketLPs, setTotalMarketLPs] = useState<number>();
  const [isModalOpened] = useState(false);
  const [isLoading, setLoading] = useState(true);
  const [isPopUpShown, setPopUpShown] = useState(false);
  const [error, setError] = useState<string>();
  const [isPolicyActive, setPolicyActive] = useState<boolean>();

  useEffect(() => {
    setQuoteLoader(new QuoteLoader(environment));

  }, [environment]);

  useEffect(() => {
    if (quoteLoader) {
      initialize();
    }

  }, [policyId, quoteLoader]);

  useEffect(() => {
    if (!quoteLoader.capitalToken) {
      return;
    }

    setTitleProps({
      coverage: new BigNumber(policyActualCoverage ?? 0).toFixed(0),
      coverageTokenInfo: quoteLoader.capitalToken,
      market: quoteLoader.market,
      incomeApyRate: incomeApyRate,
      quote: quoteLoader.quote?.toFixed(2, BigNumber.ROUND_UP),
      quoteTokenInfo: quoteLoader.premiumToken,
      rate: quoteLoader.rate?.toFixed(2, BigNumber.ROUND_UP),
    });
  }, [policyActualCoverage, quoteLoader.capitalToken, quoteLoader.market]);

  function closePopUp(e: any) {
    if (e.target === e.currentTarget) {
      setPopUpShown(false);
    }
  }

  async function initialize() {
    try {
      setLoading(true);

      const p = await quoteLoader.getPolicy(policyId);
      const isActive = (p !== undefined && p.coverage && p.coverage !== "0") || false;

      setPolicyActive(isActive);

      if (!p) {
        setLoading(false);

        return;
      }

      setPolicy(p);

      await quoteLoader.load(
        provider,
        0,
        p.marketId,
        "0",
      );

      if (quoteLoader.market) {
        calcActualCoverage(p, quoteLoader.market);
        getMarketInfo();
      }
    } catch (e) {
      console.error(e);

      setError((e as any)?.message ? (e as any).message : "Error");
    }

    setLoading(false);
  }

  async function calcActualCoverage(p: Policy, m: Market) {
    const q = quoteLoader.marketCoverage;

    if (!q) {
      return;
    }

    setPolicyActualCoverage(
      q[0].toString() === "0" ?
        "0" :
        new BigNumber(p.coverage).times(q[1].toString()).div(q[0].toString()).toString(),
    );

    setLoading(false);
  }

  async function getMarketInfo() {
    quoteLoader.getMarketCapacity().then(setTotalMarketCapacity);
    quoteLoader.getMarketLPCount().then(setTotalMarketLPs);
    setMarketEntities((await quoteLoader.getMarketEntities()));
  }

  function WidgetLine() {
    return isPolicyActive ?
      policy && quoteLoader.capitalToken ? <div className={`AtomicaWidget--ProtectionInfo ${className}`}>
        {insertLinksAndSpinnersInString(
          renderTemplateString(activeProtectionTitle ?? DEFAULT_ACTIVE_PROTECTION_TITLE, titleProps),
          getPolicyDetailUrl(quoteLoader.uiUrl(), policy?.id),
          getBuyPolicyUrl(quoteLoader.uiUrl(), quoteLoader.market?.id),
        )}
        <div className='c-policy-widget__see-details'>
          <a className={'link-button'} onClick={() => setPopUpShown(!isPopUpShown)}>click for details</a>
          {inlineMode &&
            <div onClick={() => setPopUpShown(!isPopUpShown)} className={`c-policy-widget__arrow-span ${(isPopUpShown && "expanded") || ""}`}>
              <ArrowDownIcon />
            </div>
          }
        </div>
      </div> :
        <Spinner /> :
      isPolicyActive === false ? <>{insertLinksAndSpinnersInString(
        renderTemplateString(noProtectionTitle ?? DEFAULT_NO_PROTECTION_TITLE, titleProps),
        getPolicyDetailUrl(quoteLoader.uiUrl(), policy?.id),
        getBuyPolicyUrl(quoteLoader.uiUrl(), quoteLoader.market?.id),
      )}</> :
        <Spinner />
  }

  const Content = <WidgetContent
    error={error}
    isModalOpened={isModalOpened}
    quoteLoader={quoteLoader}
    marketEntities={marketEntities}
    policy={policy}
    isPolicyActive={isPolicyActive}
    policyActualCoverage={policyActualCoverage}
    totalMarketCapacity={totalMarketCapacity}
    totalMarketLPs={totalMarketLPs}
  />;

  return (<div className={`c-policy-widget ${className === "dark-theme" ? className : "light-theme"}`}>
    <WidgetLine />
    {
      !inlineMode && isPopUpShown &&
      <Modal isOpen={isPopUpShown}
        onBackgroundClick={closePopUp}
        onCloseClick={closePopUp}
        onEscPressed={closePopUp}
        width='auto'
        height='auto'
      >
        <WidgetWrapper className={isLoading ? 'loading' : ''}>
          {Content}
        </WidgetWrapper>
      </Modal>
    }
    {
      inlineMode && <div className={`c-policy-widget__content ${(isPopUpShown && "expanded") || "hidden"}`}>
        {Content}
      </div>
    }
  </div>);
}

function WidgetContent(props: {
  error: string | undefined,
  isModalOpened: boolean | null,
  quoteLoader: QuoteLoader,
  marketEntities: Array<EntityValue | undefined>,
  policy: Policy | undefined,
  isPolicyActive: boolean | undefined,
  policyActualCoverage: string | undefined,
  totalMarketCapacity: BigNumber | undefined,
  totalMarketLPs: number | undefined,
}) {
  const {
    error,
    isModalOpened,
    quoteLoader,
    marketEntities,
    policy,
    isPolicyActive,
    policyActualCoverage,
    totalMarketCapacity,
    totalMarketLPs,
  } = props;

  return <>
    <Title className="title">
      <img className="light-logo" src="https://sdk.atomica.org/full_logo.svg" alt='Atomica logo'></img>
      <span className="dark-logo"><AtomicaLightLogo /></span>
      <p>Protection with Atomica</p>
    </Title>
    <Box className="widget-box">
      {
        error &&
        <Box>{error}</Box>
      }
      {
        !error && isModalOpened !== null &&
        <Fragment>
          <StyledCheckbox>
            <div>
              {
                quoteLoader.market?.entityList &&
                <LabelText margin="5px 0 10px">
                  <div>
                    <IconList icons={marketEntities.map((item) => item?.logo ?? "").filter(Boolean) ?? []} height={40} width={40} />
                  </div>
                  <div>
                    <p>
                      {quoteLoader.market.entityList
                        .map((item: string) => item.length > 16 ? `${item.substring(0, 16)}...` : item)
                        .join(" - ")}
                    </p>
                    <a href={getPolicyDetailUrl(quoteLoader.uiUrl(), policy?.id)} target='_blank' rel="noreferrer">See details <LinkArrowIcon scale={1} /></a>
                  </div>
                </LabelText>
              }
              {
                isPolicyActive === true && policy &&
                <>
                  <LabelText><div>Policy Desired Cover</div> <div>{(quoteLoader.capitalToken && toSuffixFormat(new BigNumber(policy.coverage).div(`1e${quoteLoader.capitalToken.decimals}`), 2)) || "-"} {quoteLoader.capitalToken?.symbol}</div></LabelText>
                  <LabelText><div>Policy Actual Cover</div> <div>{(policyActualCoverage && quoteLoader.capitalToken && toSuffixFormat(new BigNumber(policyActualCoverage).div(`1e${quoteLoader.capitalToken.decimals}`), 2)) || "-"} {quoteLoader.capitalToken?.symbol}</div></LabelText>
                  <LabelText><div>Protection purchased</div> <div>{formatDateInterval(policy.validFrom)} ago</div></LabelText>
                  <LabelText boldLabel={true} boldValue={true}><div>Market Capacity</div> <div>{
                    totalMarketCapacity && quoteLoader.capitalToken && toSuffixFormat(totalMarketCapacity.div(`1e${quoteLoader.capitalToken.decimals}`), 2)} {
                      quoteLoader.capitalToken?.symbol} of {totalMarketLPs ?? "-"
                    } LP(s)</div></LabelText>
                </>
              }
            </div>
            <Footer>
            </Footer>
          </StyledCheckbox>
        </Fragment>
      }
    </Box>
  </>;
}

function formatDateInterval(dateFromSec: string, dateToSec?: string) {
  let diff;
  let f = +dateFromSec;

  if (!dateToSec) {
    diff = +new Date() / 1000 - f;
  } else {
    diff = +dateToSec - f;
  }

  return intervalToString(diff);
}

function intervalToString(intervalInSecs: number): string {
  return `${Math.floor(intervalInSecs / (30 * 24 * 60 * 60)) > 0 ? ` ${Math.floor(intervalInSecs / (30 * 24 * 60 * 60))}m` : ''}${Math.floor(intervalInSecs % (30 * 24 * 60 * 60) / (24 * 60 * 60)) > 0 ? ` ${Math.floor(intervalInSecs % (30 * 24 * 60 * 60) / (24 * 60 * 60))}d` : ''}${Math.floor(intervalInSecs % (24 * 60 * 60) / (60 * 60)) > 0 ? ` ${Math.floor(intervalInSecs % (24 * 60 * 60) / (60 * 60))}h` : ''} ${Math.floor(intervalInSecs % (60 * 60) / 60)}m ${Math.floor(intervalInSecs % 60)}s`;
}
