import React, { useState, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import {
  List,
  ListItem,
  Alert,
  Chip,
  ListItemAvatar,
  ListItemText,
  ListItemIcon,
  Divider,
  Grid,
  Collapse,
  useTheme,
  Typography,
  IconButton,
} from '@mui/material';

import Countdown, { CountdownRenderProps, zeroPad } from 'react-countdown';
import RobotAvatar from '../../components/RobotAvatar';

import currencies from '../../../static/assets/currencies.json';
import {
  AccessTime,
  Numbers,
  PriceChange,
  Payments,
  Article,
  HourglassTop,
  ExpandLess,
  ExpandMore,
} from '@mui/icons-material';
import { PaymentStringAsIcons } from '../../components/PaymentMethods';
import { FlagWithProps, SendReceiveIcon } from '../Icons';
import LinearDeterminate from './LinearDeterminate';

import { Order, Info } from '../../models';
import { statusBadgeColor, pn, amountToString, computeSats } from '../../utils';
import TakeButton from './TakeButton';

interface OrderDetailsProps {
  order: Order;
  setOrder: (state: Order) => void;
  info: Info;
  baseUrl: string;
  hasRobot: boolean;
}

const OrderDetails = ({
  order,
  info,
  setOrder,
  baseUrl,
  hasRobot,
}: OrderDetailsProps): JSX.Element => {
  const { t } = useTranslation();
  const theme = useTheme();

  const currencyCode: string = currencies[`${order.currency}`];
  const [showSatsDetails, setShowSatsDetails] = useState<boolean>(false);

  const amountString = useMemo(() => {
    // precision to 8 decimal if currency is BTC otherwise 4 decimals
    if (order.currency == 1000) {
      return (
        amountToString(
          order.amount * 100000000,
          order.amount ? false : order.has_range,
          order.min_amount * 100000000,
          order.max_amount * 100000000,
        ) + ' Sats'
      );
    } else {
      return (
        amountToString(
          order.amount,
          order.amount ? false : order.has_range,
          order.min_amount,
          order.max_amount,
        ) + ` ${currencyCode}`
      );
    }
  }, [order.currency, order.amount, order.min_amount, order.max_amount, order.has_range]);

  // Countdown Renderer callback with condition
  const countdownRenderer = function ({
    total,
    hours,
    minutes,
    seconds,
    completed,
  }: CountdownRenderProps) {
    if (completed) {
      // Render a completed state
      return <span> {t('The order has expired')}</span>;
    } else {
      let color = 'inherit';
      const fraction_left = total / 1000 / order.total_secs_exp;
      // Make orange at 25% of time left
      if (fraction_left < 0.25) {
        color = theme.palette.warning.main;
      }
      // Make red at 10% of time left
      if (fraction_left < 0.1) {
        color = theme.palette.error.main;
      }
      // Render a countdown, bold when less than 25%
      return fraction_left < 0.25 ? (
        <a style={{ color }}>
          <b>{`${hours}h ${zeroPad(minutes)}m ${zeroPad(seconds)}s `}</b>
        </a>
      ) : (
        <a style={{ color }}>{`${hours}h ${zeroPad(minutes)}m ${zeroPad(seconds)}s `}</a>
      );
    }
  };

  const timerRenderer = function (seconds: number) {
    const hours = Math.floor(seconds / 3600);
    const minutes = Math.floor((seconds - hours * 3600) / 60);
    return (
      <span>
        {hours > 0 ? hours + 'h' : ''} {minutes > 0 ? zeroPad(minutes) + 'm' : ''}{' '}
      </span>
    );
  };

  // Countdown Renderer callback with condition
  const countdownPenaltyRenderer = function ({ minutes, seconds, completed }) {
    if (completed) {
      // Render a completed state
      return <span> {t('Penalty lifted, good to go!')}</span>;
    } else {
      return (
        <span>
          {' '}
          {t('You cannot take an order yet! Wait {{timeMin}}m {{timeSec}}s', {
            timeMin: zeroPad(minutes),
            timeSec: zeroPad(seconds),
          })}{' '}
        </span>
      );
    }
  };

  const satsSummary = useMemo(() => {
    let send: string = '';
    let receive: string = '';
    let sats: string = '';

    const isBuyer = (order.type == 0 && order.is_maker) || (order.type == 1 && !order.is_maker);
    const tradeFee = order.is_maker ? info?.maker_fee ?? 0 : info?.taker_fee ?? 0;
    const defaultRoutingBudget = 0.001;
    const btc_now = order.satoshis_now / 100000000;
    const rate = order.amount ? order.amount / btc_now : order.max_amount / btc_now;

    if (isBuyer) {
      if (order.amount) {
        sats = computeSats({
          amount: order.amount,
          fee: -tradeFee,
          routingBudget: defaultRoutingBudget,
          rate: rate,
        });
      } else {
        const min = computeSats({
          amount: Number(order.min_amount),
          fee: -tradeFee,
          routingBudget: defaultRoutingBudget,
          rate: rate,
        });
        const max = computeSats({
          amount: Number(order.max_amount),
          fee: -tradeFee,
          routingBudget: defaultRoutingBudget,
          rate: rate,
        });
        sats = `${min}-${max}`;
      }
      send = t('You send via {{method}} {{amount}}', {
        amount: amountString,
        method: order.payment_method,
        currencyCode,
      });
      receive = t('You receive via Lightning {{amount}} Sats (Approx)', {
        amount: sats,
      });
    } else {
      if (order.amount) {
        sats = computeSats({
          amount: order.amount,
          fee: tradeFee,
          rate: rate,
        });
      } else {
        const min = computeSats({
          amount: order.min_amount,
          fee: tradeFee,
          rate: rate,
        });
        const max = computeSats({
          amount: order.max_amount,
          fee: tradeFee,
          rate: rate,
        });
        sats = `${min}-${max}`;
      }
      send = t('You send via Lightning {{amount}} Sats (Approx)', { amount: sats });
      receive = t('You receive via {{method}} {{amount}}', {
        amount: amountString,
        method: order.payment_method,
      });
    }
    return { send, receive };
  }, [order.currency, order.satoshis_now, order.amount, order.has_range]);

  return (
    <Grid container spacing={0}>
      <Grid item xs={12}>
        <List dense={true}>
          <ListItem>
            <ListItemAvatar sx={{ width: '4em', height: '4em' }}>
              <RobotAvatar
                statusColor={statusBadgeColor(order.maker_status)}
                nickname={order.maker_nick}
                tooltip={t(order.maker_status)}
                orderType={order.type}
                baseUrl={baseUrl}
                small={true}
              />
            </ListItemAvatar>
            <ListItemText
              primary={`${order.maker_nick} (${
                order.type
                  ? t(order.currency == 1000 ? 'Swapping Out' : 'Seller')
                  : t(order.currency == 1000 ? 'Swapping In' : 'Buyer')
              })`}
              secondary={t('Order maker')}
            />
          </ListItem>

          <Collapse in={order.is_participant && order.taker_nick !== 'None'}>
            <Divider />
            <ListItem>
              <ListItemText
                primary={`${order.taker_nick} (${
                  order.type
                    ? t(order.currency == 1000 ? 'Swapping In' : 'Buyer')
                    : t(order.currency == 1000 ? 'Swapping Out' : 'Seller')
                })`}
                secondary={t('Order taker')}
              />
              <ListItemAvatar>
                <RobotAvatar
                  avatarClass='smallAvatar'
                  statusColor={statusBadgeColor(order.taker_status)}
                  nickname={order.taker_nick == 'None' ? undefined : order.taker_nick}
                  tooltip={t(order.taker_status)}
                  orderType={order.type === 0 ? 1 : 0}
                  baseUrl={baseUrl}
                  small={true}
                />
              </ListItemAvatar>
            </ListItem>
          </Collapse>
          <Divider>
            <Chip label={t('Order Details')} />
          </Divider>

          <Collapse in={order.is_participant}>
            <ListItem>
              <ListItemIcon>
                <Article />
              </ListItemIcon>
              <ListItemText primary={t(order.status_message)} secondary={t('Order status')} />
            </ListItem>
            <Divider />
          </Collapse>

          <ListItem>
            <ListItemIcon>
              <div
                style={{
                  zoom: 1.25,
                  opacity: 0.7,
                  msZoom: 1.25,
                  WebkitZoom: 1.25,
                  MozTransform: 'scale(1.25,1.25)',
                  MozTransformOrigin: 'left center',
                }}
              >
                <FlagWithProps code={currencyCode} width='1.2em' height='1.2em' />
              </div>
            </ListItemIcon>
            <ListItemText
              primary={amountString}
              secondary={order.amount ? 'Amount' : 'Amount Range'}
            />
            <ListItemIcon>
              <IconButton onClick={() => setShowSatsDetails(!showSatsDetails)}>
                {showSatsDetails ? <ExpandLess /> : <ExpandMore color='primary' />}
              </IconButton>
            </ListItemIcon>
          </ListItem>

          <Collapse in={showSatsDetails}>
            <List dense={true} sx={{ position: 'relative', bottom: '0.5em' }}>
              <ListItem>
                <ListItemIcon sx={{ position: 'relative', left: '0.3em' }}>
                  <SendReceiveIcon
                    sx={{ transform: 'scaleX(-1)', width: '0.9em', opacity: 0.7 }}
                    color='secondary'
                  />
                </ListItemIcon>
                <Typography variant='body2'>{satsSummary.send}</Typography>
              </ListItem>

              <ListItem>
                <ListItemIcon sx={{ position: 'relative', left: '0.3em' }}>
                  <SendReceiveIcon
                    sx={{ left: '0.1em', width: '0.9em', opacity: 0.7 }}
                    color='primary'
                  />
                </ListItemIcon>
                <Typography variant='body2'>{satsSummary.receive}</Typography>
              </ListItem>
            </List>
          </Collapse>

          <Divider />

          <ListItem>
            <ListItemIcon>
              <Payments />
            </ListItemIcon>
            <ListItemText
              primary={
                <PaymentStringAsIcons
                  size={1.42 * theme.typography.fontSize}
                  othersText={t('Others')}
                  verbose={true}
                  text={order.payment_method}
                />
              }
              secondary={
                order.currency == 1000 ? t('Swap destination') : t('Accepted payment methods')
              }
            />
          </ListItem>
          <Divider />

          {/* If there is live Price and Premium data, show it. Otherwise show the order maker settings */}
          <ListItem>
            <ListItemIcon>
              <PriceChange />
            </ListItemIcon>

            {order.price_now !== undefined ? (
              <ListItemText
                primary={t('{{price}} {{currencyCode}}/BTC - Premium: {{premium}}%', {
                  price: pn(order.price_now),
                  currencyCode,
                  premium: order.premium_now,
                })}
                secondary={t('Price and Premium')}
              />
            ) : null}

            {!order.price_now && order.is_explicit ? (
              <ListItemText primary={pn(order.satoshis)} secondary={t('Amount of Satoshis')} />
            ) : null}

            {!order.price_now && !order.is_explicit ? (
              <ListItemText
                primary={parseFloat(Number(order.premium).toFixed(2)) + '%'}
                secondary={t('Premium over market price')}
              />
            ) : null}
          </ListItem>

          <Divider />

          <ListItem>
            <ListItemIcon>
              <Numbers />
            </ListItemIcon>
            <Grid container>
              <Grid item xs={4.5}>
                <ListItemText primary={order.id} secondary={t('Order ID')} />
              </Grid>
              <Grid item xs={7.5}>
                <Grid container>
                  <Grid item xs={2}>
                    <ListItemIcon sx={{ position: 'relative', top: '12px', left: '-5px' }}>
                      <HourglassTop />
                    </ListItemIcon>
                  </Grid>
                  <Grid item xs={10}>
                    <ListItemText
                      primary={timerRenderer(order.escrow_duration)}
                      secondary={t('Deposit timer')}
                    ></ListItemText>
                  </Grid>
                </Grid>
              </Grid>
            </Grid>
          </ListItem>

          {/* if order is in a status that does not expire, do not show countdown */}
          <Collapse in={![4, 5, 12, 13, 14, 15, 16, 17, 18].includes(order.status)}>
            <Divider />
            <ListItem>
              <ListItemIcon>
                <AccessTime />
              </ListItemIcon>
              <ListItemText secondary={t('Expires in')}>
                <Countdown date={new Date(order.expires_at)} renderer={countdownRenderer} />
              </ListItemText>
            </ListItem>
            <LinearDeterminate totalSecsExp={order.total_secs_exp} expiresAt={order.expires_at} />
          </Collapse>
        </List>

        {/* If the user has a penalty/limit */}
        {order.penalty !== undefined ? (
          <Grid item xs={12}>
            <Alert severity='warning' sx={{ borderRadius: '0' }}>
              <Countdown date={new Date(order.penalty)} renderer={countdownPenaltyRenderer} />
            </Alert>
          </Grid>
        ) : (
          <></>
        )}

        {!order.is_participant ? (
          <Grid item xs={12}>
            <TakeButton
              order={order}
              setOrder={setOrder}
              baseUrl={baseUrl}
              hasRobot={hasRobot}
              info={info}
            />
          </Grid>
        ) : (
          <></>
        )}
      </Grid>
    </Grid>
  );
};

export default OrderDetails;
