import { useState, useEffect } from 'react';
import {
  Request,
  RequestTableData,
  getRequests,
  transformRequests,
} from '../../api/Requests';
import ContentCard from '../shared/ContentCard';
import { useAuth } from '../../auth/AuthProvider';
import SupplierRequestChart from '../charts/HorizontalBarChart';
import { ResponsiveContainer } from 'recharts';
import { Link } from 'react-router-dom';
import {
  getNotifications,
  getReadNotifications,
} from '../../api/Notifications';
import SummaryMetrics from './SummaryMetrics';
import { getStudents } from '../../api/Users';
import { getOrders } from '../../api/Orders';
import ChartDropdown from '../charts/ChartDropdown';

export default function InstructorDashboard() {
  const { user } = useAuth();
  const [incomingRequests, setIncomingRequests] = useState<RequestTableData[]>(
    []
  );
  const [allRequests, setAllRequests] = useState<Request[]>([]);
  const [incomingRequestSupplierData, setIncomingRequestSupplierData] =
    useState<{ name: string; count: number }[]>([]);
  const [allRequestConfigurableData, setAllRequestConfigurableData] = useState<
    { name: string; count: number }[]
  >([]);
  const [oldestRequestAge, setOldestRequestAge] = useState<string>('');
  const [unreadCount, setUnreadCount] = useState<number>(0);
  const [metricsData, setMetricsData] = useState<[string, string][]>([]);
  const [selectedKey, setSelectedKey] = useState<keyof Request>('status');

  const getAndSetOldestIncomingRequestAge = (
    transformedIncomingRequests: RequestTableData[]
  ) => {
    if (transformedIncomingRequests.length === 0) return null;

    const oldestRequest = transformedIncomingRequests.reduce(
      (oldest, current) =>
        new Date(oldest.request_timestamp as string) <
        new Date(current.request_timestamp as string)
          ? oldest
          : current
    );

    const currentTime = new Date();
    const oldestRequestTime = new Date(
      oldestRequest.request_timestamp as string
    );

    const timeDifference = currentTime.getTime() - oldestRequestTime.getTime();
    const totalDays = timeDifference / (1000 * 3600 * 24);

    const days = Math.floor(totalDays);
    const hours = Math.round((totalDays - days) * 24);

    const formattedAge = `${days} day${days !== 1 ? 's' : ''}${
      hours > 0 ? `, ${hours} hour${hours !== 1 ? 's' : ''}` : ''
    } ago`;

    setOldestRequestAge(formattedAge);
  };

  function getChartData<T>(
    data: T[],
    category: keyof T
  ): { name: string; count: number }[] {
    const counts: Record<string, number> = {};

    data.forEach((item) => {
      const key = item[category];
      if (key != null) {
        const keyStr = String(key);
        counts[keyStr] = (counts[keyStr] || 0) + 1;
      }
    });

    return Object.entries(counts).map(([name, count]) => ({ name, count }));
  }

  const retrieveBaseData = async () => {
    if (!allRequests.length) {
      return;
    }

    const incomingRequests = allRequests.filter(
      (request) =>
        request.order_id === null &&
        ['requested', 'approved', 'reordered'].includes(request.status)
    );

    const transformed = await transformRequests(incomingRequests);
    setIncomingRequests(transformed);

    const supplierCounts = transformed.reduce(
      (acc, req) => {
        if (req.supplier_id != null) {
          acc[req.supplier_id as number] =
            (acc[req.supplier_id as number] || 0) + 1;
        }
        return acc;
      },
      {} as Record<number, number>
    );

    const incomingRequestSupplierResult = Object.entries(supplierCounts).map(
      ([supplierId, count]) => ({
        name: `${supplierId}`,
        count,
      })
    );
    setIncomingRequestSupplierData(incomingRequestSupplierResult);

    const statusCounts = allRequests.reduce(
      (acc, req) => {
        if (req.status != null) {
          acc[req.status] = (acc[req.status] || 0) + 1;
        }
        return acc;
      },
      {} as Record<string, number>
    );

    getAndSetOldestIncomingRequestAge(transformed);

    // ***** GET METRICS DATA below ***** //
    const students = await getStudents();
    const totalRequested = allRequests
      .reduce((sum, request) => sum + (request.subtotal || 0), 0)
      .toFixed(2);

    const allOrders = await getOrders();

    const totalOrdered = allOrders
      .reduce((sum, order) => sum + (order.total || 0), 0)
      .toFixed(2);

    const transformedAllRequests = await transformRequests(allRequests);

    const supplierCount: { [key: string]: number } = {};
    transformedAllRequests.forEach((request) => {
      const supplier = request.supplier_id;
      supplierCount[supplier] = (supplierCount[supplier] || 0) + 1;
    });
    let topSupplier = '';
    let maxRequests = 0;
    for (const supplier in supplierCount) {
      if (supplierCount[supplier] > maxRequests) {
        topSupplier = supplier;
        maxRequests = supplierCount[supplier];
      }
    }

    const newMetrics: [string, string][] = [
      ['# of Students', students.length.toString()],
      ['# of Requests', allRequests.length.toString()],
      [
        'Total Requested',
        new Intl.NumberFormat('en-US', {
          style: 'currency',
          currency: 'USD',
        }).format(Number(totalRequested)),
      ],
      ['# of Orders', allOrders.length.toString()],
      [
        'Total Ordered',
        new Intl.NumberFormat('en-US', {
          style: 'currency',
          currency: 'USD',
        }).format(Number(totalOrdered)),
      ],
      // ['Top Supplier', topSupplier]
      // Add more metrics here as needed
    ];

    setMetricsData(newMetrics);
    // ***** GET METRICS DATA above ***** //
  };

  const setAllRequestsChart = (yaxis: string) => {
    const allRequestConfigurableResult = getChartData(
      allRequests,
      yaxis as keyof Request
    );
    setAllRequestConfigurableData(allRequestConfigurableResult);
  };

  useEffect(() => {
    const getAndSetNotifications = async () => {
      let notis;
      if (user?.team_id) {
        notis = await getNotifications(user.team_id);
      } else {
        notis = (await getNotifications()).filter(
          (noti) => noti.for_instructor
        ); // getting as instructor
      }

      const readResult = await getReadNotifications(user?.user_id as number);

      const unreadCount = notis.filter(
        (notification) =>
          !readResult.some(
            (read) => read.notification_id === notification.notification_id
          )
      ).length;
      setUnreadCount(unreadCount);
    };

    const getAndSetAllRequests = async () => {
      const result = await getRequests();
      setAllRequests(result);
    };

    getAndSetNotifications();
    getAndSetAllRequests();
  }, []);

  useEffect(() => {
    setAllRequestsChart('status');
    retrieveBaseData();
  }, [allRequests]);

  return (
    <>
      <div className='row'>
        <div className='col-md-6 mb-3'>
          {user?.ta_id ? null : (
            <div className='mb-3'>
              <ContentCard
                title='Unread Notifications'
                description='You will receive a notification each time a student creates a request.'
              >
                You have{' '}
                <strong>
                  {unreadCount} unread notification
                  {unreadCount !== 1 ? 's' : null}
                </strong>
                .{' '}
                <Link to='/notifications'>
                  Click here see all notifications.
                </Link>
              </ContentCard>
            </div>
          )}
          <ContentCard
            title='Incoming Requests'
            description='An incoming request is defined of having a status of either requested, approved, or reordered.'
          >
            {incomingRequests.length == 0 && (
              <div>
                There are <strong>0 incoming requests</strong>.{' '}
                <Link to='/instructor/requests'>
                  Click here to view all requests.
                </Link>
              </div>
            )}

            {incomingRequests.length > 0 && (
              <>
                <div>
                  There are{' '}
                  <strong>
                    {incomingRequests.length} incoming request
                    {incomingRequests.length !== 1 && 's'}{' '}
                  </strong>{' '}
                  that {incomingRequests.length === 1 ? 'has' : 'have'} not yet
                  been ordered. The oldest incoming request was made{' '}
                  <strong>{oldestRequestAge}</strong>.{' '}
                  <Link to='/orders'>
                    Click here to view incoming requests.
                  </Link>
                </div>
                <hr />
                <div
                  className='w-100'
                  style={{ height: '400px', marginBottom: '1rem' }}
                >
                  <h4 style={{ textAlign: 'center', marginTop: '20px' }}>
                    Incoming Requests by Supplier
                  </h4>
                  <ResponsiveContainer width='100%' height='100%'>
                    <SupplierRequestChart
                      data={incomingRequestSupplierData}
                      xlabel={'Number of Requests'}
                      ylabel={'Supplier'}
                    />
                  </ResponsiveContainer>
                </div>
              </>
            )}
          </ContentCard>
        </div>
        <div className='col-md-6'>
          <ContentCard title='Summary Metrics'>
            {metricsData.length ? (
              <>
                <SummaryMetrics metrics={metricsData} />
                <hr />
                <div
                  className='w-100'
                  style={{ height: '650px', marginBottom: '1rem' }}
                >
                  <div className='d-flex justify-content-center align-items-center my-3 gap-3'>
                    <h4 className='mb-0'>All Requests by</h4>
                    <ChartDropdown
                      selectedKey={selectedKey}
                      setSelectedKey={setSelectedKey}
                      setAllRequestsChart={setAllRequestsChart}
                    />
                  </div>
                  <ResponsiveContainer width='100%' height='100%'>
                    <SupplierRequestChart
                      data={allRequestConfigurableData}
                      xlabel={'Number of Requests'}
                      ylabel={selectedKey}
                    />
                  </ResponsiveContainer>
                </div>
              </>
            ) : (
              <div className='d-flex justify-content-center align-items-center'>
                There are no metrics to display.
              </div>
            )}
          </ContentCard>
        </div>
      </div>
    </>
  );
}
