import { headers }              from 'next/headers';
import { auth }                 from "@/auth";
import { trades }               from '@/lib/journal/trades';
import { tradingActivity }      from '@/lib/journal/trading-activity';
import { wallets }              from '@/lib/journal/wallets';
import { transactions }         from '@/lib/journal/transactions';
import { countTrades }          from '@/lib/journal/count-trades';
import { countTradingAccounts } from '@/lib/journal/count-trading-accounts';
import { brokers }              from '@/lib/journal/brokers';
import { tradeStats }           from '@/lib/journal/trade-stats';
import mostActiveAccount        from '@/lib/journal/most-active-account';
import { BalanceCard }          from "@/components/dashboard/balance-card";
import { RecentTransactions }   from "@/components/dashboard/recent-transactions";
import { Heatmap }              from "@/components/dashboard/heatmap";
import { Overview }             from "@/components/dashboard/overview";
import { Activity }             from '@/components/dashboard/activity';
import { DateSelector }         from '@/components/dashboard/date-selector';
import { MostActiveAccount }    from '@/components/dashboard/most-active-account';

const isValidDateString = (date: any): date is string =>
  typeof date === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(date)
  && !isNaN(new Date(date + 'T00:00:00').getTime());

const isValidRange = (from: Date, to: Date) => {
  const dFrom = from;
  const dTo = to;

  return (
    dFrom.getFullYear() === dTo.getFullYear() &&
    dFrom.getMonth() === dTo.getMonth() &&
    dTo.getTime() > dFrom.getTime() &&
    dFrom.getDate() === 1 &&
    dTo.getDate() === new Date(
      dTo.getFullYear(), dTo.getMonth() + 1, 0
    ).getDate()
  );
};

export default async function Page({
  searchParams
}: {
  searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}) {
  const { from, to } = await searchParams;
  const session = await auth.api.getSession({ headers: await headers() });
  const userId = session?.user.id;
  const thisYear = new Date().getFullYear();

  let year = isValidDateString(to)
    ? parseInt(to.split('-')[0], 10) : undefined;
 
  const hmData = (await trades({
    userId: session?.user.id,
    from: year ? new Date(year, 0, 1) : (() => {
      const d = new Date();
      d.setFullYear(new Date().getFullYear() - 1);
      return d;
    })(),
    to: year ? new Date(year, 11, 31, 23, 59, 59, 999) : undefined,
  })).reduce((acc, t) => {
    const date = t.executions[0].executionDate.toISOString().split('T')[0];
    const existing = acc
    .find((d: { date: string; value: number; }) => d.date === date);

    if (existing) {
      existing.value += 1;
    } else {
      acc.push({ date, value: 1 });
    }
    return acc;
  }, [] as { date: string; value: number }[]);

  const dateCheck = isValidDateString(from) && isValidDateString(to)
  && isValidRange(
    new Date(from + 'T00:00:00'), new Date(to + 'T00:00:00')
  );

  const activity = dateCheck && session?.user.id
    ? (await tradingActivity({
      userId: session?.user.id,
      from: new Date(from + 'T00:00:00'),
      to: new Date(to + 'T00:00:00'),
    })) : {};

  const balances = (session?.user.id ? await wallets({ userId: session?.user.id })
    : []).reduce((acc, wallet) => {
    const existing = acc.find(b => b.currency === wallet.currency);
    if (existing) {
      existing.amount += wallet.currentBalance;
    } else {
      acc.push({ currency: wallet.currency, amount: wallet.currentBalance });
    };
    return acc;
  }, [] as { currency: string; amount: number }[]);

  const selectorYears = (() => {
    const currentYear = new Date().getFullYear();
    const registeredYear = session?.user?.createdAt
      ? new Date(session.user.createdAt).getFullYear()
      : currentYear;

    const startYear = registeredYear - 1;
    const years = [];

    for (let y = currentYear; y >= startYear; y--) {
      years.push(y);
    }

    return years;
  })();

  const recentTransactions = (session?.user.id ? await transactions({
    userId: session.user.id,
    limit: 3,
    order: 'desc',
  }) : []).map(txn => ({
    date: txn.transactionAt,
    type: txn.type,
    amount: txn.amount,
    currency: txn.wallet.currency,
  }));

  const [
    openTradesCount,
    closedTradesCount,
    allTradesCount,
    accountsCount,
    brokersCount,
  ] = await Promise.all([
    userId ? countTrades({ userId, status: 'open' }) : 0,
    userId ? countTrades({ userId, status: 'closed' }) : 0,
    userId ? countTrades({ userId }) : 0,
    userId ? countTradingAccounts({ userId }) : 0,
    userId ? brokers({ userId }).then(b => b.length) : 0,
  ]);
/* when a user selects delete account, we should show a confirmation dialog and if yes, delete the account. then for edit account, we should switch the content of existing modal/drawer from account view to edit which will contain the form fields the user can edit. implement the edit function too. */
  const overview = [
    { count: openTradesCount, title: "Open Trades", url: '/trades?status=open' },
    { count: closedTradesCount, title: "Closed Trades", url: '/trades?status=closed' },
    { count: allTradesCount, title: "All Trades", url: '/trades' },
    { count: accountsCount, title: "Accounts", url: '/accounts' },
    { count: brokersCount, title: "Brokers", url: '/accounts' },
  ];

  const mostActive = userId ? await mostActiveAccount({
    userId,
    from: new Date(thisYear, 0, 1),
    to: new Date(thisYear, 11, 31, 23, 59, 59, 999),
  }) : undefined;

  const mostActiveStats = userId && mostActive 
    ? await tradeStats({
      userId,
      tradingAccountId: mostActive.id,
      from: new Date(thisYear, 0, 1),
      to: new Date(thisYear, 11, 31, 23, 59, 59, 999),
    }) : {};

  return <div className="grid gap-7">
    <div className="grid md:grid-cols-2 gap-7">
      <div className="grid gap-7">
        <BalanceCard balances={balances} />
        <RecentTransactions transactions={recentTransactions} />
      </div>

      <div className="grid gap-7">
        <Overview stats={overview} />
        <MostActiveAccount
          account={mostActive}
          stats={mostActiveStats}
          year={thisYear}
        />
      </div>
    </div>

    <div className="grid md:grid-cols-12 gap-7">
      <div className="col-span-12 lg:col-span-10 min-w-0">
        <Heatmap
          data={hmData}
          startDate={year ? new Date(year, 0, 1) : undefined}
          endDate={year ? new Date(year, 11, 31, 23, 59, 59, 999) : undefined}
        />

        <div className="mt-7">
          <Activity activity={activity} />
        </div>
      </div>

      <div className="col-span-2 hidden lg:block pt-5">
        <DateSelector years={selectorYears} />
      </div>
    </div>
  </div>
}
