import React, { useCallback, useEffect, useState } from "react";

import { SellOutlined } from "@mui/icons-material";
import CopyAllOutlinedIcon from "@mui/icons-material/CopyAllOutlined";
import { Button, Chip, Collapse, Stack } from "@mui/material";

import { DateTime } from "luxon";
import { useSnackbar } from "notistack";

import CardActions from "../../../components/Card/CardActions";
import CardCloseButton from "../../../components/Card/CardCloseButton";
import CardContent from "../../../components/Card/CardContent";
import CardFieldDate from "../../../components/Card/CardFieldDate";
import CardFieldText from "../../../components/Card/CardFieldText";
import CardRow from "../../../components/Card/CardRow";
import { useApi } from "../../../contexts/ApiContext";
import { useCardContext } from "../../../contexts/CardContext";
import { useDialog } from "../../../contexts/DialogContext";
import { useI18n } from "../../../contexts/I18nContext";
import { useUser } from "../../../contexts/UserContext";
import { PageProps } from "../../../types";
import { hasPermission } from "../../../util/has_permission";
import { toTitleCase } from "../../../util/to_title_case";
import { currencyFormat } from "../../pos/utils/amountToCurrencyString";
import {
  Subscription,
  SubscriptionPeriod,
  SubscriptionPeriodResponse,
} from "../types/subscription";

import EndSubscriptionButton from "./EndSubscriptionButton";
import ResumeSubscriptionButton from "./ResumeSubscriptionButton";
import StartSubscriptionButton from "./StartSubscriptionButton";
import SubscriptionsDialog from "./SubscriptionsDialog";
import SubscriptionsList from "./SubscriptionsList";

export interface SubscriptionsCardContentProps {
  subscription: Subscription;
  membership_number?: number;
  refresh: PageProps["refresh"];
}

const SubscriptionsCardContent: React.FC<SubscriptionsCardContentProps> = ({
  subscription,
  membership_number,
  refresh,
}) => {
  const [cancelDialogOpen, setCancelDialogOpen] = useState(false);
  const [periods, setPeriods] = useState<SubscriptionPeriod[] | null>(null);
  const openDialog = useDialog();
  const api = useApi();
  const { user } = useUser();
  const { isOpen } = useCardContext();
  const { t } = useI18n();
  const { enqueueSnackbar } = useSnackbar();

  const handleRefresh = async () => {
    refresh();
    await fetchPeriods();
  };

  const fetchPeriods = async () => {
    const response = await api.operations["subscription.period:list"].call({
      params: {
        subscription_id: subscription.id,
      },
    });
    const data: SubscriptionPeriodResponse = await response.json();
    // TODO Coerce dates
    if (periods == null) setPeriods(data.results);
  };

  const subscribeAgain = useCallback(async () => {
    if (
      await openDialog(
        t("Subscribe"),
        `Are you sure you want to subscribe this member to "${subscription.name}" again?`,
        {
          ok: t("Yes, subscribe"),
          cancel: t("Cancel"),
        },
      )
    ) {
      const action = api.operations["subscription.contrib:member-subscription-create"];
      if (!action) {
        throw new Error('Invalid action "subscription.contrib:member-subscription-create".');
      }

      const response = await action.call({
        params: { membership_number },
        body: { reference: subscription.plan },
      });
      if (response.status == 201) {
        refresh();
        enqueueSnackbar(t("New subscription created"), { variant: "success" });
      } else if (response.status == 200) {
        enqueueSnackbar(t("Member already subscribed"), { variant: "info" });
      } else {
        console.error("[SUBSCRIBE_AGAIN]", response);
        enqueueSnackbar(t("Failed to subscribe"), { variant: "error" });
      }
    }
  }, [api, subscription]);

  useEffect(() => {
    if (periods != null) return;
    fetchPeriods();
  }, [subscription, fetchPeriods, periods]);

  return (
    <>
      <Collapse in={isOpen} timeout="auto">
        <CardContent>
          <CardRow columns={subscription.is_cancelled ? 4 : 3}>
            <CardFieldText
              formName="periodicity"
              isEditable={false}
              label={t("Periodicity")}
              required={true}
              size={1}
              value={toTitleCase(subscription.periodicity)}
            />

            <CardFieldText
              formName="frequency"
              isEditable={false}
              label={t("Frequency")}
              required={true}
              size={1}
              value={String(subscription.nth)}
            />

            <CardFieldText
              formName="amount"
              isEditable={false}
              label={t("Price")}
              size={1}
              value={currencyFormat(Number.parseFloat(subscription.amount), subscription.currency)}
            />
          </CardRow>

          <CardRow columns={subscription.is_cancelled ? 4 : 3}>
            <CardFieldDate
              formName="date_created"
              isEditable={false}
              label={t("Date created")}
              required={true}
              size={1}
              value={DateTime.fromISO(subscription.date_created as string)}
            />

            {subscription.start_date != null && (
              <CardFieldDate
                fallback="Not started"
                formName="start_date"
                isEditable={false}
                label={t("Started")}
                size={1}
                value={DateTime.fromISO(subscription.start_date as string)}
              />
            )}

            {subscription.is_cancelled && (
              <CardFieldDate
                formName="date_cancelled"
                isEditable={false}
                label={t("Date cancelled")}
                size={1}
                value={DateTime.fromISO(subscription.date_cancelled as string)}
              />
            )}

            {subscription.end_date && (
              <CardFieldDate
                formName="end_date"
                isEditable={false}
                label={t("End date")}
                size={1}
                value={DateTime.fromISO(subscription.end_date as string)}
              />
            )}

            {!subscription.is_cancelled && subscription.state === "RUNNING" && (
              <CardFieldDate
                formName="expiry_date"
                isEditable={false}
                label={t("Next payment")}
                size={1}
                value={DateTime.fromISO(subscription.expiry_date as string)}
              />
            )}
          </CardRow>

          {subscription.voucher_codes.length > 0 && (
            <Stack direction="row" spacing={1}>
              {subscription.voucher_codes.map((voucher) => (
                <Chip
                  key={voucher}
                  color="info"
                  icon={<SellOutlined />}
                  label={voucher}
                  size="small"
                  sx={{ pl: 0.5 }}
                />
              ))}
            </Stack>
          )}
        </CardContent>

        <SubscriptionsList periods={periods} refresh={handleRefresh} />

        <CardActions>
          <Stack direction="row" justifyContent="space-between" width="100%">
            {subscription.state === "PENDING" && (
              <Stack direction="row" spacing={2}>
                <StartSubscriptionButton refresh={handleRefresh} subscriptionId={subscription.id} />
                <EndSubscriptionButton refresh={handleRefresh} subscriptionId={subscription.id} />
              </Stack>
            )}

            {subscription.state === "RUNNING" && subscription.is_cancelled === false && (
              <Stack direction="row" spacing={2}>
                <Button variant="outlined" onClick={() => setCancelDialogOpen(true)}>
                  Cancel subscription
                </Button>
              </Stack>
            )}

            {subscription.state === "RUNNING" && subscription.is_cancelled === true && (
              <Stack direction="row" spacing={2}>
                <ResumeSubscriptionButton
                  refresh={handleRefresh}
                  subscriptionId={subscription.id}
                />
                <EndSubscriptionButton refresh={handleRefresh} subscriptionId={subscription.id} />
              </Stack>
            )}

            {subscription.state === "ENDED" &&
              hasPermission(user, "subscription.add_subscription") && (
                <Button
                  startIcon={<CopyAllOutlinedIcon />}
                  variant="outlined"
                  onClick={subscribeAgain}
                >
                  Subscribe Again
                </Button>
              )}

            <CardCloseButton />
          </Stack>
        </CardActions>
      </Collapse>

      <SubscriptionsDialog
        open={cancelDialogOpen}
        refresh={handleRefresh}
        setOpen={setCancelDialogOpen}
        subscriptionId={subscription.id}
      />
    </>
  );
};

export default SubscriptionsCardContent;
