import styled from '@emotion/styled';
import { useQuery } from '@tanstack/react-query';

import {
  BarElement,
  CategoryScale,
  Chart as ChartJS,
  Colors,
  Filler,
  LinearScale,
  LineElement,
  PointElement,
  Tooltip,
} from 'chart.js';
import { add, format } from 'date-fns';
import { useCallback, useMemo, useState } from 'react';
import { Bar, Chart } from 'react-chartjs-2';
import {
  ash,
  gray600,
  gray700,
  green500,
  lightPastelBlue,
  newBlue,
  paddleDark,
  paddleLight,
  paddlePrimary,
  red500,
  stripeDark,
  stripeLight,
  stripePrimary,
} from '../../colors';
import { dateToString, getDateString, getRelativeDate } from '../../lib/date';
import { AdminButton } from './common';

ChartJS.register(CategoryScale, LinearScale, PointElement, BarElement, LineElement, Tooltip, Colors, Filler);

const SectionTitle = styled.h1`
  margin: 50px 0 20px 0;
`;
const ChartContainer = styled.div`
  height: 400px;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
`;

const DateWrapper = styled.div`
  display: flex;
  gap: 10px;
  align-items: center;
  justify-content: left;
  p {
    margin: 0;
    font-size: 1.2rem;
  }
  input {
    height: 40px;
    padding: 10px;
    font-size: 1rem;
  }
`;

const DashboardButtonWrapper = styled.div`
  display: flex;
  justify-content: left;
  gap: 20px;
  margin-bottom: 20px;
`;

const Notice = styled.div`
  color: ${gray600};
  font-size: 1rem;
  margin: 0 0 20px 0;
  padding: 0 10px;
`;

const StatsContainer = styled.div`
  display: flex;
  gap: 10px;
  margin: 0 0 10px 0;
  padding: 20px;
  border-radius: 10px;
  border: 1px solid ${gray600};
`;

const StatColumn = styled.div`
  display: flex;
  flex-direction: column;
  text-align: center;
  width: 100%;
  gap: 10px;

  * {
    margin: 0;
  }

  h2 {
    font-size: 1rem;
    color: ${gray600};
  }

  p {
    color: ${gray600};
    font-size: 1.3rem;
  }
  p:last-child {
    font-size: 1.5rem;
  }
`;

const LegendContainer = styled.div`
  display: flex;
  justify-content: center;
  gap: 20px;
  margin: 20px 0;
`;

const Legend = styled.div`
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: center;

  span {
    width: 20px;
    height: 20px;
    border-radius: 5px;
  }
  p {
    margin: 0;
    color: ${gray600};
    font-size: 1rem;
  }
`;

const ButtonBar = styled.div`
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 20px;
`;

enum TimeSelection {
  Daily = 'Daily',
  Weekly = 'Weekly',
  Monthly = 'Monthly',
}

enum SubscriberGroupBy {
  PaymentProvider = 'PaymentProvider',
  Tier = 'Tier',
}

type ActiveSubBreakdown = {
  pro: {
    renewing: number;
    nonRenewing: number;
  };
  pro_trial: {
    renewing: number;
    nonRenewing: number;
  };
  indie: {
    renewing: number;
    nonRenewing: number;
  };
};

type ActiveSubData = {
  date: string;
  stripe: ActiveSubBreakdown;
  paddle: ActiveSubBreakdown;
  stripeLastMonth: ActiveSubBreakdown;
  paddleLastMonth: ActiveSubBreakdown;
};

type TrialConversionData = {
  trials: number;
  conversions: number;
};

type TrialConversionDate = {
  date: string;
  stats: TrialConversionData;
  statsLastMonth: TrialConversionData;
};

type ChurnData = {
  date: string;
  existing: number;
  churned: number;
  new: number;
};

const DashboardUsers = ({ serverUri }: { serverUri: string }) => {
  const [timeSelection, setTimeSelection] = useState<TimeSelection>(TimeSelection.Daily);

  const [currentDate, setCurrentDate] = useState<string>(getDateString());

  const { data: signupData, isLoading: signupLoading } = useQuery({
    queryKey: ['admin-dashboards-signups', currentDate],
    queryFn: async () => {
      const response = await fetch(`${serverUri}/api/admin/dashboard/${currentDate}/signups`, {
        credentials: 'include',
      });
      const {
        daily,
        weekly,
        monthly,
        newSubs,
      }: {
        daily: { signup_date: string; signup_count: number }[];
        weekly: { signup_week: string; signup_count: number }[];
        monthly: { signup_month: string; signup_count: number }[];
        newSubs: { date: string; count: number }[];
      } = await response.json();

      return { daily, weekly, monthly, newSubs };
    },
  });

  let signupProperty = 'signup_date';
  if (timeSelection === TimeSelection.Weekly) signupProperty = 'signup_week';
  if (timeSelection === TimeSelection.Monthly) signupProperty = 'signup_month';
  const data = signupData && {
    labels: signupData[timeSelection.toLowerCase()].map((row) => row[signupProperty]),
    datasets: [
      {
        label: `${timeSelection} Signups`,
        data: signupData[timeSelection.toLowerCase()].map((row) => row.signup_count),
        backgroundColor: lightPastelBlue,
      },
    ],
  };

  const [groupBy, setGroupBy] = useState<SubscriberGroupBy>(SubscriberGroupBy.Tier);
  const [showTrials, setShowTrials] = useState<boolean>(true);
  const [showNotRenewing, setShowNotRenewing] = useState<boolean>(true);

  const { data: activeSubsData, isLoading: activeSubsLoading } = useQuery({
    queryKey: ['admin-dashboards-active-subs', currentDate],
    queryFn: async () => {
      const response = await fetch(`${serverUri}/api/admin/dashboard/${currentDate}/activeSubs`, {
        credentials: 'include',
      });
      const activeSubs: ActiveSubData[] = (await response.json()) as ActiveSubData[];
      // Sort by date
      activeSubs.sort((a, b) => (a.date > b.date ? 1 : -1));
      return activeSubs;
    },
  });

  const getDaySubs = useCallback(
    (day: ActiveSubData, lastMonth: boolean = false) => {
      const stripeKey = lastMonth ? 'stripeLastMonth' : 'stripe';
      const paddleKey = lastMonth ? 'paddleLastMonth' : 'paddle';
      let proSubs = day[stripeKey].pro.renewing + day[paddleKey].pro.renewing;
      if (showNotRenewing) {
        proSubs += day[stripeKey].pro.nonRenewing;
        proSubs += day[paddleKey].pro.nonRenewing;
      }
      if (showTrials) {
        proSubs += day[stripeKey].pro_trial.renewing;
        proSubs += day[paddleKey].pro_trial.renewing;
        if (showNotRenewing) {
          proSubs += day[stripeKey].pro_trial.nonRenewing;
          proSubs += day[paddleKey].pro_trial.nonRenewing;
        }
      }

      let indieSubs = day[stripeKey].indie.renewing + day[paddleKey].indie.renewing;
      if (showNotRenewing) {
        indieSubs += day[stripeKey].indie.nonRenewing;
        indieSubs += day[paddleKey].indie.nonRenewing;
      }
      return {
        pro: proSubs,
        indie: indieSubs,
      };
    },
    [showTrials, showNotRenewing]
  );

  const subStats = useMemo(() => {
    if (!activeSubsData) return null;
    const current = getDaySubs(activeSubsData[activeSubsData.length - 1]);
    const lastWeek = getDaySubs(activeSubsData[activeSubsData.length - 8]);
    const lastMonth = getDaySubs(activeSubsData[activeSubsData.length - 1], true);
    return {
      current,
      lastWeek,
      lastMonth,
    };
  }, [activeSubsData, showTrials, showNotRenewing]);

  const subStatDelta = useMemo(() => {
    if (!subStats) return null;
    return {
      lastWeek: {
        pro: subStats.current.pro - subStats.lastWeek.pro,
        indie: subStats.current.indie - subStats.lastWeek.indie,
        total: subStats.current.pro + subStats.current.indie - subStats.lastWeek.pro - subStats.lastWeek.indie,
        proPercent:
          subStats.lastWeek.pro === 0
            ? 0
            : ((subStats.current.pro - subStats.lastWeek.pro) / subStats.lastWeek.pro) * 100,
        indiePercent:
          subStats.lastWeek.indie === 0
            ? 0
            : ((subStats.current.indie - subStats.lastWeek.indie) / subStats.lastWeek.indie) * 100,
        totalPercent:
          ((subStats.current.pro + subStats.current.indie - subStats.lastWeek.pro - subStats.lastWeek.indie) /
            (subStats.lastWeek.pro + subStats.lastWeek.indie)) *
          100,
      },
      lastMonth: {
        pro: subStats.current.pro - subStats.lastMonth.pro,
        indie: subStats.current.indie - subStats.lastMonth.indie,
        total: subStats.current.pro + subStats.current.indie - subStats.lastMonth.pro - subStats.lastMonth.indie,
        proPercent:
          subStats.lastMonth.pro === 0
            ? 0
            : ((subStats.current.pro - subStats.lastMonth.pro) / subStats.lastMonth.pro) * 100,
        indiePercent:
          subStats.lastMonth.indie === 0
            ? 0
            : ((subStats.current.indie - subStats.lastMonth.indie) / subStats.lastMonth.indie) * 100,
        totalPercent:
          ((subStats.current.pro + subStats.current.indie - subStats.lastMonth.pro - subStats.lastMonth.indie) /
            (subStats.lastMonth.pro + subStats.lastMonth.indie)) *
          100,
      },
    };
  }, [subStats]);

  const subDatasets = useMemo(() => {
    if (!activeSubsData) return [];
    const datasets = [];
    const stripeProTrial = {
      label: 'Pro Trial - Stripe',
      data: activeSubsData.map(
        (row) => row.stripe.pro_trial.renewing + (showNotRenewing ? row.stripe.pro_trial.nonRenewing : 0)
      ),
      backgroundColor: stripeDark,
      type: 'bar',
    };
    const stripePro = {
      label: 'Pro - Stripe',
      data: activeSubsData.map((row) => row.stripe.pro.renewing + (showNotRenewing ? row.stripe.pro.nonRenewing : 0)),
      backgroundColor: stripePrimary,
      type: 'bar',
    };
    const stripeIndie = {
      label: 'Indie - Stripe',
      data: activeSubsData.map(
        (row) => row.stripe.indie.renewing + (showNotRenewing ? row.stripe.indie.nonRenewing : 0)
      ),
      backgroundColor: stripeLight,
      type: 'bar',
    };
    const paddleProTrial = {
      label: 'Pro Trial - Paddle',
      data: activeSubsData.map(
        (row) => row.paddle.pro_trial.renewing + (showNotRenewing ? row.paddle.pro_trial.nonRenewing : 0)
      ),
      backgroundColor: paddleDark,
      type: 'bar',
    };
    const paddlePro = {
      label: 'Pro - Paddle',
      data: activeSubsData.map((row) => row.paddle.pro.renewing + (showNotRenewing ? row.paddle.pro.nonRenewing : 0)),
      backgroundColor: paddlePrimary,
      type: 'bar',
    };
    const paddleIndie = {
      label: 'Indie - Paddle',
      data: activeSubsData.map(
        (row) => row.paddle.indie.renewing + (showNotRenewing ? row.paddle.indie.nonRenewing : 0)
      ),
      backgroundColor: paddleLight,
      type: 'bar',
    };

    if (groupBy === SubscriberGroupBy.PaymentProvider) {
      datasets.push(stripeIndie);
      datasets.push(stripePro);
      if (showTrials) datasets.push(stripeProTrial);
      datasets.push(paddleIndie);
      datasets.push(paddlePro);
      if (showTrials) datasets.push(paddleProTrial);
    } else {
      datasets.push({
        label: 'Last Month Pro',
        data: activeSubsData.map((row) => {
          let lastMonthPro = row.stripeLastMonth.pro.renewing + row.paddleLastMonth.pro.renewing;
          if (showNotRenewing) {
            lastMonthPro += row.stripeLastMonth.pro.nonRenewing;
            lastMonthPro += row.paddleLastMonth.pro.nonRenewing;
          }
          if (showTrials) {
            lastMonthPro += row.stripeLastMonth.pro_trial.renewing;
            lastMonthPro += row.paddleLastMonth.pro_trial.renewing;
            if (showNotRenewing) {
              lastMonthPro += row.stripeLastMonth.pro_trial.nonRenewing;
              lastMonthPro += row.paddleLastMonth.pro_trial.nonRenewing;
            }
          }
          return lastMonthPro;
        }),
        type: 'line',
        fill: false,
        borderColor: '#33333366',
      });
      datasets.push({
        label: 'Last Month Indie',
        data: activeSubsData.map((row) => {
          let lastMonthIndie = row.stripeLastMonth.indie.renewing + row.paddleLastMonth.indie.renewing;
          if (showNotRenewing) {
            lastMonthIndie += row.stripeLastMonth.indie.nonRenewing;
            lastMonthIndie += row.paddleLastMonth.indie.nonRenewing;
          }
          return lastMonthIndie;
        }),
        type: 'line',
        fill: false,
        borderColor: '#77777766',
      });
      datasets.push(stripeIndie);
      datasets.push(paddleIndie);
      datasets.push(stripePro);
      datasets.push(paddlePro);
      if (showTrials) {
        datasets.push(stripeProTrial);
        datasets.push(paddleProTrial);
      }
    }
    return datasets;
  }, [activeSubsData, groupBy, showTrials, showNotRenewing]);

  const { data: trialConversionData, isLoading: trialConversionLoading } = useQuery({
    queryKey: ['admin-dashboards-trial-conversion', currentDate],
    queryFn: async () => {
      const response = await fetch(`${serverUri}/api/admin/dashboard/${currentDate}/trialConversion`, {
        credentials: 'include',
      });
      const trialConversion: TrialConversionDate[] = (await response.json()) as TrialConversionDate[];
      // Sort by date
      trialConversion.sort((a, b) => (a.date > b.date ? 1 : -1));
      return trialConversion;
    },
  });

  const trialStats = useMemo(() => {
    if (!trialConversionData) return null;
    const current = trialConversionData[trialConversionData.length - 1].stats;
    const lastWeek = trialConversionData[trialConversionData.length - 8].stats;
    const lastMonth = trialConversionData[trialConversionData.length - 1].statsLastMonth;
    const currentPercent = current.trials === 0 ? 0 : (current.conversions / current.trials) * 100;
    const lastWeekPercent = lastWeek.trials === 0 ? 0 : (lastWeek.conversions / lastWeek.trials) * 100;
    const lastMonthPercent = lastMonth.trials === 0 ? 0 : (lastMonth.conversions / lastMonth.trials) * 100;
    return {
      current: {
        trials: current.trials,
        conversions: current.conversions,
        percent: currentPercent,
      },
      lastWeek: {
        trials: lastWeek.trials,
        conversions: lastWeek.conversions,
        percent: lastWeekPercent,
      },
      lastMonth: {
        trials: lastMonth.trials,
        conversions: lastMonth.conversions,
        percent: lastMonthPercent,
      },
    };
  }, [trialConversionData]);

  const { data: churnData, isLoading: churnLoading } = useQuery({
    queryKey: ['admin-dashboards-churn', currentDate],
    queryFn: async () => {
      const response = await fetch(`${serverUri}/api/admin/dashboard/${currentDate}/churn`, {
        credentials: 'include',
      });

      const churn: ChurnData[] = (await response.json()) as ChurnData[];

      // Sort by date
      churn.sort((a, b) => (a.date > b.date ? 1 : -1));
      return churn;
    },
  });

  return (
    <>
      <DateWrapper>
        <p>Date for dashboards: </p>
        <input
          type="date"
          value={currentDate}
          onChange={(e) => {
            setCurrentDate(e.target.value);
          }}
        />
        <div>
          {
            // Display day of week
            new Date(currentDate).toLocaleDateString('en-US', {
              weekday: 'short',
            })
          }
        </div>
        <div>
          {/* Display relative date */}
          {getRelativeDate(currentDate)}
        </div>
      </DateWrapper>
      <SectionTitle>Active Subscribers</SectionTitle>
      <Notice>
        The number of currently active subscriptions.
        <br />
        Each date represents a month's worth of subscribers
        <br />
        You can select how to group them and whether to include trials and non-renewing subscriptions.
      </Notice>

      {activeSubsData && subStats && subStatDelta && (
        <>
          <StatsContainer>
            <StatColumn
              style={{
                width: '20%',
              }}
            >
              <h2>&nbsp;</h2>
              <p>Pro</p>
              <p>Indie</p>
              <p>
                <strong>Total</strong>
              </p>
            </StatColumn>
            <StatColumn>
              <h2>Today</h2>
              <p>{subStats.current.pro}</p>
              <p>{subStats.current.indie}</p>
              <p>
                <strong>{subStats.current.pro + subStats.current.indie}</strong>
              </p>
            </StatColumn>
            <StatColumn>
              <h2>Against Last Week</h2>
              {subStatDelta.lastWeek.pro > 0 ? (
                <p style={{ color: green500 }}>
                  ↑ {subStatDelta.lastWeek.pro} (+{subStatDelta.lastWeek.proPercent.toFixed(2)}%)
                </p>
              ) : (
                <p style={{ color: red500 }}>
                  ↓ {subStatDelta.lastWeek.pro} ({subStatDelta.lastWeek.proPercent.toFixed(2)}%)
                </p>
              )}
              {subStatDelta.lastWeek.indie > 0 ? (
                <p style={{ color: green500 }}>
                  ↑ {subStatDelta.lastWeek.indie} (+{subStatDelta.lastWeek.indiePercent.toFixed(2)}%)
                </p>
              ) : (
                <p style={{ color: red500 }}>
                  ↓ {subStatDelta.lastWeek.indie} ({subStatDelta.lastWeek.indiePercent.toFixed(2)}%)
                </p>
              )}
              {subStatDelta.lastWeek.total > 0 ? (
                <p style={{ color: green500 }}>
                  ↑ {subStatDelta.lastWeek.total} (+{subStatDelta.lastWeek.totalPercent.toFixed(2)}%)
                </p>
              ) : (
                <p style={{ color: red500 }}>
                  ↓ {subStatDelta.lastWeek.total} ({subStatDelta.lastWeek.totalPercent.toFixed(2)}%)
                </p>
              )}
            </StatColumn>
            <StatColumn>
              <h2>Against Last Month</h2>
              {subStatDelta.lastMonth.pro > 0 ? (
                <p style={{ color: green500 }}>
                  ↑ {subStatDelta.lastMonth.pro} (+{subStatDelta.lastMonth.proPercent.toFixed(2)}%)
                </p>
              ) : (
                <p style={{ color: red500 }}>
                  ↓ {subStatDelta.lastMonth.pro} ({subStatDelta.lastMonth.proPercent.toFixed(2)}%)
                </p>
              )}
              {subStatDelta.lastMonth.indie > 0 ? (
                <p style={{ color: green500 }}>
                  ↑ {subStatDelta.lastMonth.indie} (+{subStatDelta.lastMonth.indiePercent.toFixed(2)}%)
                </p>
              ) : (
                <p style={{ color: red500 }}>
                  ↓ {subStatDelta.lastMonth.indie} ({subStatDelta.lastMonth.indiePercent.toFixed(2)}%)
                </p>
              )}
              {subStatDelta.lastMonth.total > 0 ? (
                <p style={{ color: green500 }}>
                  ↑ {subStatDelta.lastMonth.total} (+{subStatDelta.lastMonth.totalPercent.toFixed(2)}%)
                </p>
              ) : (
                <p style={{ color: red500 }}>
                  ↓ {subStatDelta.lastMonth.total} ({subStatDelta.lastMonth.totalPercent.toFixed(2)}%)
                </p>
              )}
            </StatColumn>
          </StatsContainer>

          <LegendContainer>
            <Legend>
              <span style={{ backgroundColor: stripePrimary }} />
              <p>Pro - Stripe</p>
            </Legend>

            {showTrials && (
              <Legend>
                <span style={{ backgroundColor: stripeDark }} />
                <p>Pro Trial - Stripe</p>
              </Legend>
            )}
            <Legend>
              <span style={{ backgroundColor: stripeLight }} />
              <p>Indie - Stripe</p>
            </Legend>
            <Legend>
              <span style={{ backgroundColor: paddlePrimary }} />
              <p>Pro - Paddle</p>
            </Legend>
            {showTrials && (
              <Legend>
                <span style={{ backgroundColor: paddleDark }} />
                <p>Pro Trial - Paddle</p>
              </Legend>
            )}
            <Legend>
              <span style={{ backgroundColor: paddleLight }} />
              <p>Indie - Paddle</p>
            </Legend>
          </LegendContainer>
        </>
      )}
      <ButtonBar>
        <AdminButton
          style={{ backgroundColor: groupBy === SubscriberGroupBy.Tier ? lightPastelBlue : ash }}
          onClick={() => {
            setGroupBy(SubscriberGroupBy.Tier);
          }}
        >
          Group by Tier
        </AdminButton>
        <AdminButton
          style={{ backgroundColor: groupBy === SubscriberGroupBy.PaymentProvider ? lightPastelBlue : ash }}
          onClick={() => {
            setGroupBy(SubscriberGroupBy.PaymentProvider);
          }}
        >
          Group by Payment Provider
        </AdminButton>

        <AdminButton
          style={{ backgroundColor: showTrials ? lightPastelBlue : ash, marginLeft: '20px' }}
          onClick={() => {
            setShowTrials(true);
          }}
        >
          Show Trials
        </AdminButton>
        <AdminButton
          style={{ backgroundColor: !showTrials ? lightPastelBlue : ash }}
          onClick={() => {
            setShowTrials(false);
          }}
        >
          Hide Trials
        </AdminButton>
        <AdminButton
          style={{ backgroundColor: showNotRenewing ? lightPastelBlue : ash, marginLeft: '20px' }}
          onClick={() => {
            setShowNotRenewing(true);
          }}
        >
          Show Not Renewing
        </AdminButton>
        <AdminButton
          style={{ backgroundColor: !showNotRenewing ? lightPastelBlue : ash }}
          onClick={() => {
            setShowNotRenewing(false);
          }}
        >
          Hide Not Renewing
        </AdminButton>
      </ButtonBar>
      <ChartContainer>
        {activeSubsLoading && <p>Loading...</p>}
        {activeSubsData && (
          <Chart
            style={{ width: '100%' }}
            data={{
              labels: activeSubsData.map((row) => row.date),
              datasets: subDatasets,
            }}
            options={{
              responsive: true,
              interaction: {
                intersect: false,
                mode: 'index',
              },
              scales: {
                x: {
                  stacked: true,
                },
                y: {
                  stacked: true,
                  beginAtZero: true,
                  ticks: {
                    callback: function (value) {
                      return value;
                    },
                  },
                },
              },
              plugins: {
                tooltip: {
                  callbacks: {
                    footer: function (tooltipItems) {
                      let total = 0;
                      let totalLastMonth = 0;
                      tooltipItems.forEach((tooltipItem) => {
                        if (tooltipItem.dataset.label.includes('Last Month')) {
                          totalLastMonth += tooltipItem.raw as number;
                        } else total += tooltipItem.raw as number;
                      });
                      if (groupBy === SubscriberGroupBy.PaymentProvider) {
                        return `Total: ${total}`;
                      }
                      return `Total: ${total}\nLast Month: ${totalLastMonth}`;
                    },
                  },
                },
              },
            }}
            type={'bar'}
          />
        )}
      </ChartContainer>

      <SectionTitle>Churn Rate</SectionTitle>

      <Notice>
        The percentage of users who have cancelled their subscription.
        <br />
        Each date represents a month's worth of data.
        <br />
        Trials are not taken into account.
      </Notice>
      <ChartContainer>
        {churnLoading && <p>Loading...</p>}
        {churnData && (
          <Chart
            style={{ width: '100%' }}
            data={{
              labels: churnData.map((row) => row.date),
              datasets: [
                {
                  label: 'Churn Rate',
                  data: churnData.map((row) => {
                    if (row.existing === 0) return 0;
                    return Math.round((row.churned / (row.existing + row.new)) * 100);
                  }),
                  backgroundColor: newBlue,
                  yAxisID: 'y',
                  type: 'line',
                },
                {
                  label: 'Churned',
                  data: churnData.map((row) => -row.churned),
                  backgroundColor: red500,
                  yAxisID: 'y1',
                  type: 'bar',
                },
                {
                  label: 'New',
                  data: churnData.map((row) => row.new),
                  backgroundColor: green500,
                  yAxisID: 'y1',
                  type: 'bar',
                },
              ],
            }}
            options={{
              responsive: true,
              interaction: {
                intersect: false,
                mode: 'index',
              },
              scales: {
                x: {
                  stacked: true,
                },
                y: {
                  beginAtZero: true,
                  min: 0,
                  max: 100,
                  ticks: {
                    callback: function (value) {
                      return value + '%';
                    },
                  },
                },
                y1: {
                  beginAtZero: true,
                  position: 'right',
                  stacked: true,
                },
              },
              plugins: {
                tooltip: {
                  callbacks: {
                    title: function (tooltipItems) {
                      const date = tooltipItems[0].label;
                      const monthAgoDate = format(add(new Date(date), { months: -1 }), 'yyyy-MM-dd');
                      return `${monthAgoDate} to ${date}`;
                    },
                    label: function (context) {
                      let label = context.dataset.label || '';
                      if (label) {
                        label += ': ';
                      }

                      if (context.parsed.y !== null) {
                        if (label.includes('Rate')) {
                          label += context.parsed.y + '%';
                        } else {
                          label += context.parsed.y;
                        }
                      }
                      return label;
                    },
                  },
                },
              },
            }}
            type={'bar'}
          />
        )}
      </ChartContainer>

      <SectionTitle>
        Trial Conversion Rate{' '}
        <small
          style={{
            marginLeft: '10px',
            color: gray600,
            fontSize: '0.7em',
          }}
        >
          (7 day rolling window)
        </small>
      </SectionTitle>
      <Notice>
        The percentage of users who continue <strong>paying for at least 5 days</strong> after their trial is up.
        <br />
        Each date represents the conversion rate for all the trials started 7 days prior to that date.
        <br />
        Since trials are 14 days long, the latest date will be 14 days ago.
        <br />
        This only includes Pro subscriptions as Indie subscriptions do not have trials.
      </Notice>

      <StatsContainer>
        <StatColumn>
          <h2>Past 7 days</h2>
          <p>{trialStats?.current.trials} trials</p>
          <p>
            <strong>{Math.round(trialStats?.current.percent)}% conversion</strong>
          </p>
        </StatColumn>
        <StatColumn>
          <h2>Last Week (7 day total)</h2>
          <p>{trialStats?.lastWeek.trials} trials</p>
          {trialStats?.lastWeek.percent > trialStats?.current.percent ? (
            <p style={{ color: red500 }}>
              <strong>↓ {Math.round(trialStats?.lastWeek.percent)}% conversion</strong>
            </p>
          ) : (
            <p style={{ color: green500 }}>
              <strong>↑ {Math.round(trialStats?.lastWeek.percent)}% conversion</strong>
            </p>
          )}
        </StatColumn>
        <StatColumn>
          <h2>Last Month (7 day total)</h2>
          <p>{trialStats?.lastMonth.trials} trials</p>
          {trialStats?.lastMonth.percent > trialStats?.current.percent ? (
            <p style={{ color: red500 }}>
              <strong>↓ {Math.round(trialStats?.lastMonth.percent)}% conversion</strong>
            </p>
          ) : (
            <p style={{ color: green500 }}>
              <strong>↑ {Math.round(trialStats?.lastMonth.percent)}% conversion</strong>
            </p>
          )}
        </StatColumn>
      </StatsContainer>

      <ChartContainer>
        {trialConversionLoading && <p>Loading...</p>}
        {trialConversionData && (
          <Chart
            style={{ width: '100%' }}
            data={{
              labels: trialConversionData.map((row) => row.date),
              datasets: [
                {
                  label: 'Conversion Rate',
                  data: trialConversionData.map((row) => {
                    if (row.stats.trials === 0) return 0;
                    return Math.round((row.stats.conversions / row.stats.trials) * 100);
                  }),
                  borderColor: newBlue,
                  yAxisID: 'y',
                },
                {
                  label: 'Last Month Conversion Rate',
                  data: trialConversionData.map((row) => {
                    if (row.statsLastMonth.trials === 0) return 0;
                    return Math.round((row.statsLastMonth.conversions / row.statsLastMonth.trials) * 100);
                  }),
                  borderColor: ash,
                  yAxisID: 'y',
                },
                {
                  label: 'Converted',
                  data: trialConversionData.map((row) => row.stats.conversions),
                  backgroundColor: green500,
                  type: 'bar',
                  yAxisID: 'y1',
                },
                {
                  label: 'Cancelled',
                  data: trialConversionData.map((row) => row.stats.trials - row.stats.conversions),
                  backgroundColor: gray700,
                  type: 'bar',
                  yAxisID: 'y1',
                },
              ],
            }}
            options={{
              responsive: true,
              interaction: {
                intersect: false,
                mode: 'index',
              },
              scales: {
                x: {
                  stacked: true,
                },
                y: {
                  beginAtZero: true,
                  min: 0,
                  max: 100,
                  ticks: {
                    callback: function (value) {
                      return value + '%';
                    },
                  },
                },
                y1: {
                  beginAtZero: true,
                  position: 'right',
                  stacked: true,
                },
              },
              plugins: {
                tooltip: {
                  callbacks: {
                    title: function (tooltipItems) {
                      const date = tooltipItems[0].label;
                      const weekAgoDate = format(add(new Date(date), { days: -7 }), 'yyyy-MM-dd');
                      return `${weekAgoDate} to ${date}`;
                    },
                    label: function (context) {
                      let label = context.dataset.label || '';
                      if (label) {
                        label += ': ';
                      }

                      if (context.parsed.y !== null) {
                        if (label.includes('Rate')) {
                          label += context.parsed.y + '%';
                        } else {
                          label += context.parsed.y;
                        }
                      }
                      return label;
                    },
                  },
                },
              },
            }}
            type={'line'}
          />
        )}
      </ChartContainer>

      <SectionTitle>New Subscribers</SectionTitle>
      <Notice>
        This chart shows the number of subscriptions created per day in the past 20 days. This includes users who are
        still on trial, or have cancelled.
      </Notice>
      <ChartContainer>
        {signupLoading && <p>Loading...</p>}
        {signupData && (
          <Bar
            style={{ width: '100%' }}
            data={{
              labels: signupData.newSubs.map((row) => row.date),
              datasets: [
                {
                  label: 'Daily Signups',
                  data: signupData.newSubs.map((row) => row.count),
                  backgroundColor: lightPastelBlue,
                },
              ],
            }}
            options={{ responsive: true }}
          />
        )}
      </ChartContainer>

      <SectionTitle>New Account Signups</SectionTitle>
      <DashboardButtonWrapper>
        {[TimeSelection.Daily, TimeSelection.Weekly, TimeSelection.Monthly].map((time) => (
          <AdminButton disabled={time === timeSelection} onClick={() => setTimeSelection(time)}>
            {time}
          </AdminButton>
        ))}
      </DashboardButtonWrapper>

      {timeSelection === TimeSelection.Daily && (
        <Notice>This chart shows the number of new accounts created per day in the past 20 days</Notice>
      )}
      {timeSelection === TimeSelection.Weekly && (
        <Notice>This chart shows the number of new accounts created per week for the past 6 weeks</Notice>
      )}
      {timeSelection === TimeSelection.Monthly && (
        <Notice>This chart shows the number of new accounts created per month for the past 6 months</Notice>
      )}
      <ChartContainer key={timeSelection}>
        {signupData && <Bar style={{ width: '100%' }} data={data} options={{ responsive: true }} />}
      </ChartContainer>
    </>
  );
};

export default DashboardUsers;
