import fs from "node:fs";
import { HourChart } from "./(charts)/hour";
import { DayChart } from "./(charts)/day";
import { MinuteChart } from "./(charts)/minute";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";

import {
  Card,
  CardContent,
  CardFooter,
  CardHeader,
} from "@/components/ui/card";

export const dynamic = "force-dynamic";

export default async function Home() {
  const file = await fs.promises.readFile("./output.txt");

  const lines = file.toString().split("\n");

  const data = lines.map((line) => {
    const [timestamp, , value] = line.split(",");
    return {
      timestamp: Math.round(parseFloat(timestamp) * 1000),
      foldtime: parseFloat(value),
    };
  });

  const thisMonthData = convertDataToThisMonthPerDay(data);
  const thisHourData = convertDataToThisHourPerMinute(data);
  const todayData = convertDataToTodayPerHour(data);

  return (
    <main className="flex-grow w-full flex flex-col justify-center gap-4 items-center p-4">
      <div className="p-4 w-full bg-accent max-w-[1200px] rounded-xl flex justify-start gap-4">
        <div className="flex flex-col gap-2 items-start p-4">
          <span className="text-muted-foreground">This Month</span>
          <h2 className="text-2xl font-bold">
            {thisMonthData.reduce((acc) => {
              return acc + 1;
            }, 0)}
            {" Towel(s)"}
          </h2>
          <span className="text-muted-foreground">
            Avg Fold Time (s):{" "}
            {thisMonthData.reduce((acc, curr) => {
              return acc + curr.foldtime;
            }, 0) / thisMonthData.length || 0}
          </span>
        </div>
        <div className="flex flex-col gap-2 items-start p-4">
          <span className="text-muted-foreground">Today</span>
          <h2 className="text-2xl font-bold">
            {todayData.reduce((acc) => {
              return acc + 1;
            }, 0)}
            {" Towel(s)"}
          </h2>
          <span className="text-muted-foreground">
            Avg Fold Time (s):{" "}
            {todayData.reduce((acc, curr) => {
              return acc + curr.foldtime;
            }, 0) / todayData.length || 0}
          </span>
        </div>
        <div className="flex flex-col gap-2 items-start p-4">
          <span className="text-muted-foreground">This Month</span>
          <h2 className="text-2xl font-bold">
            {thisMonthData.reduce((acc) => {
              return acc + 1;
            }, 0)}
            {" Towel(s)"}
          </h2>
          <span className="text-muted-foreground">
            Avg Fold Time (s):{" "}
            {thisHourData.reduce((acc, curr) => {
              return acc + curr.foldtime;
            }, 0) / thisHourData.length || 0}
          </span>
        </div>
      </div>

      <Card className="w-full max-w-[1200px]">
        <Tabs defaultValue="month" className="w-full">
          <CardHeader>
            <TabsList className="w-full">
              <TabsTrigger className="w-full" value="month">
                Month
              </TabsTrigger>
              <TabsTrigger className="w-full" value="day">
                Day
              </TabsTrigger>
              <TabsTrigger className="w-full" value="hour">
                Hour
              </TabsTrigger>
            </TabsList>
          </CardHeader>
          <CardContent>
            <TabsContent value="month">
              <DayChart
                chartData={convertDataToThisMonthPerDayChartData(thisMonthData)}
              />
            </TabsContent>
            <TabsContent value="day">
              <HourChart
                chartData={convertDataToTodayPerHourChartData(todayData)}
              />
            </TabsContent>
            <TabsContent value="hour">
              <MinuteChart
                chartData={convertDataToThisHourPerMinuteChartData(
                  thisHourData
                )}
              />
            </TabsContent>
          </CardContent>
          <CardFooter></CardFooter>
        </Tabs>
      </Card>
    </main>
  );
}

const convertDataToThisMonthPerDay = (
  data: { timestamp: number; foldtime: number }[]
) => {
  const thisMonthTimestamp = new Date();
  thisMonthTimestamp.setHours(0, 0, 0, 0);
  thisMonthTimestamp.setDate(1);
  const nextMonthTimestamp = new Date();
  nextMonthTimestamp.setHours(0, 0, 0, 0);
  nextMonthTimestamp.setDate(1);
  nextMonthTimestamp.setMonth(nextMonthTimestamp.getMonth() + 1);

  const thisMonthData = data.filter(
    (data) =>
      data.timestamp >= thisMonthTimestamp.getTime() &&
      data.timestamp < nextMonthTimestamp.getTime()
  );

  return thisMonthData;
};

const convertDataToThisMonthPerDayChartData = (
  data: { timestamp: number; foldtime: number }[]
) => {
  const todayDataPerHour = data.reduce((acc, data) => {
    const day = new Date(data.timestamp).getDate();
    if (!acc[day]) {
      acc[day] = {
        count: 0,
        foldTime: 0,
      };
    }
    acc[day].count += 1;
    acc[day].foldTime += data.foldtime;
    return acc;
  }, {} as Record<number, { count: number; foldTime: number }>);

  const thisMonthDays = new Date();
  thisMonthDays.setMonth(thisMonthDays.getMonth() + 1);
  thisMonthDays.setDate(1);
  thisMonthDays.setDate(thisMonthDays.getDate() - 1);

  const chartData = new Array(thisMonthDays.getDate()).fill(0).map((_, i) => {
    const day = i + 1;
    if (!todayDataPerHour[day])
      return { day: "Day " + day, value: 0, foldtime: 0 };
    return {
      day: "Day " + day,
      value: todayDataPerHour[day].count,
      foldtime:
        todayDataPerHour[day].foldTime / todayDataPerHour[day].count || 0,
    };
  });

  return chartData;
};

const convertDataToThisHourPerMinute = (
  data: { timestamp: number; foldtime: number }[]
) => {
  const thisHourTimestamp = new Date();
  thisHourTimestamp.setMinutes(0, 0, 0);
  const nextHourTimestamp = new Date();
  nextHourTimestamp.setHours(nextHourTimestamp.getHours() + 1);
  nextHourTimestamp.setMinutes(0, 0, 0);

  const todayData = data.filter(
    (data) =>
      data.timestamp >= thisHourTimestamp.getTime() &&
      data.timestamp < nextHourTimestamp.getTime()
  );

  return todayData;
};

const convertDataToThisHourPerMinuteChartData = (
  data: { timestamp: number; foldtime: number }[]
) => {
  const todayDataPerHour = data.reduce((acc, data) => {
    const hour = new Date(data.timestamp).getMinutes();
    if (!acc[hour]) {
      acc[hour] = {
        count: 0,
        foldTime: 0,
      };
    }
    acc[hour].count += 1;
    acc[hour].foldTime += data.foldtime;
    return acc;
  }, {} as Record<number, { count: number; foldTime: number }>);

  const chartData = new Array(60).fill(0).map((_, i) => {
    if (!todayDataPerHour[i])
      return { minute: "Minute " + i, value: 0, foldtime: 0 };
    return {
      minute: "Minute " + i,
      value: todayDataPerHour[i].count,
      foldtime: todayDataPerHour[i].foldTime / todayDataPerHour[i].count || 0,
    };
  });

  return chartData;
};

const convertDataToTodayPerHour = (
  data: { timestamp: number; foldtime: number }[]
) => {
  const todayTimestamp = new Date();
  todayTimestamp.setHours(0, 0, 0, 0);
  const tomorrowTimestamp = new Date();
  tomorrowTimestamp.setHours(0, 0, 0, 0);
  tomorrowTimestamp.setDate(tomorrowTimestamp.getDate() + 1);

  const todayData = data.filter(
    (data) =>
      data.timestamp >= todayTimestamp.getTime() &&
      data.timestamp < tomorrowTimestamp.getTime()
  );

  return todayData;
};

const convertDataToTodayPerHourChartData = (
  data: { timestamp: number; foldtime: number }[]
) => {
  const todayDataPerHour = data.reduce((acc, data) => {
    const hour = new Date(data.timestamp).getHours();
    if (!acc[hour]) {
      acc[hour] = {
        count: 0,
        foldTime: 0,
      };
    }
    acc[hour].count += 1;
    acc[hour].foldTime += data.foldtime;
    return acc;
  }, {} as Record<number, { count: number; foldTime: number }>);

  const chartData = new Array(24).fill(0).map((_, i) => {
    if (!todayDataPerHour[i])
      return { hour: i + 1 + ":00", value: 0, foldtime: 0 };
    return {
      hour: i + 1 + ":00",
      value: todayDataPerHour[i].count,
      foldtime: todayDataPerHour[i].foldTime / todayDataPerHour[i].count || 0,
    };
  });

  return chartData;
};
