import styled from '@emotion/styled';
import { useMutation, useQuery } from '@tanstack/react-query';
import { addDays, differenceInCalendarWeeks, getDay } from 'date-fns';
import { usePathname, useSearchParams } from 'next/navigation';
import { useRouter } from 'next/router';
import { useCallback, useEffect, useState } from 'react';
import { NavbarPage, NavigationBar } from '../../../next-res/components/admin/NavBar';
import { AdminButton, AdminWrapper } from '../../../next-res/components/admin/common';
import { dateToString, getDateString } from '../../../next-res/lib/date';

const NUMBER_OF_EMPLOYEES = 6;

const StandupPersonEntryWrapper = styled.div<{ currentUser: boolean; working: boolean }>`
  display: flex;
  flex-direction: column;
  gap: 15px;
  padding: 10px;
  position: relative;
  border-radius: 5px;
  border: ${(props) => (props.currentUser ? '2px solid #9C9' : '1px solid #ddd')};
  overflow: hidden;
  background-color: ${(props) => (props.working ? '#fff' : '#fee')};
`;

const PersonHeader = styled.div`
  display: flex;
  gap: 5px;
  font-weight: bold;
  font-size: 1.2rem;
`;

const PersonColumns = styled.div`
  display: flex;
  gap: 20px;
  justify-content: space-between;
`;
const StandupColumn = styled.div`
  display: flex;
  flex-grow: 1;
  flex-basis: 1;
  flex-direction: column;
  gap: 5px;
  width: 100%;
  white-space: pre-wrap;
`;

const StandupPersonEntry = ({
  standup,
  keyProp,
  currentUser,
}: {
  standup: any;
  keyProp: string;
  currentUser: boolean;
}) => {
  const router = useRouter();
  const mood = MOOD_LIST.find((m) => m.mood === standup.standup_mood);
  return (
    <StandupPersonEntryWrapper key={keyProp} currentUser={currentUser} working={standup.is_working}>
      {currentUser && (
        <AdminButton
          style={{
            position: 'absolute',
            right: '0px',
            top: '0px',
          }}
          onClick={() => {
            router.push(`/admin/standup/crupdate?date=${standup.date}`);
          }}
        >
          Edit
        </AdminButton>
      )}
      {standup.is_working ? (
        <>
          <PersonHeader>
            <div>{standup.name}</div>
            <div>{mood.emoji}</div>
          </PersonHeader>
          <PersonColumns>
            <StandupColumn>
              <strong>What I got done since last standup</strong>
              {standup.standup_done}
            </StandupColumn>
            <StandupColumn>
              <strong>What I'm getting done today</strong>
              {standup.standup_doing}
            </StandupColumn>
            <StandupColumn>
              <strong>Things that could block me</strong>
              {standup.standup_blockers}
            </StandupColumn>
          </PersonColumns>
        </>
      ) : (
        <PersonHeader>
          <div>{standup.name}</div>
          <div>- Not working</div>
        </PersonHeader>
      )}
    </StandupPersonEntryWrapper>
  );
};

const StandupWeekSummaryHeader = styled.div`
  display: flex;
  flex-direction: column;
  padding: 15px;
  border: 1px solid #ddd;
  border-radius: 5px;
  background-color: #f9f9f9;

  div.header {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    align-items: center;
    height: 40px;
    h1 {
      font-size: 1.3rem;
      font-weight: bold;
    }
    p {
      cursor: pointer;
      color: #0070f3;
      text-decoration: underline;
      &:hover {
        text-decoration: none;
      }
    }
  }
`;

const StandupWeekSummaryTable = styled.div`
  display: grid;
  grid-template-columns: repeat(8, 1fr);

  div {
    display: flex;
    padding: 8px;
    transition: background-color 0.3s;
    align-items: center;
    justify-content: center;
    cursor: pointer;

    &.weekday {
      font-weight: bold;
    }

    &.highlighted {
      background-color: #f1e0f1;
    }

    &.selected {
      background-color: #f1c0f1;
    }
  }
`;

const StandupWeekSummary = ({
  standupData,
  setFilters,
}: {
  standupData: any;
  setFilters: (date: string | null, employee: string | null) => void;
}) => {
  const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];

  const dates = standupData.data.map((s: any) => s.date);
  // Reverse the dates so that the most recent is at the top
  dates.reverse();

  const employees = new Set();
  standupData.data.forEach((standup: any) => {
    standup.standups.forEach((s: any) => {
      employees.add(s.name);
    });
  });

  const [highlightedEmployee, setHighlightedEmployee] = useState<string | null>(null);
  const [highlightedDate, setHighlightedDate] = useState<string | null>(null);
  const [highlightedCell, setHighlightedCell] = useState<string | null>(null);

  const [selectedEmployee, setSelectedEmployee] = useState<string | null>(null);
  const [selectedDate, setSelectedDate] = useState<string | null>(null);
  const [selectedCell, setSelectedCell] = useState<string | null>(null);

  return (
    <StandupWeekSummaryHeader>
      <div className="header" key="header">
        <h1>Week of {standupData.data[standupData.data.length - 1].date}</h1>
        {(selectedEmployee || selectedDate || selectedCell) && (
          <p
            onClick={() => {
              setSelectedEmployee(null);
              setSelectedDate(null);
              setSelectedCell(null);
              setFilters(null, null);
            }}
          >
            Clear Filters
          </p>
        )}
      </div>
      <StandupWeekSummaryTable
        key="table"
        onMouseLeave={() => {
          setHighlightedDate(null);
          setHighlightedEmployee(null);
          setHighlightedCell(null);
        }}
      >
        <div key="blank"></div>

        {dates.map((date, i) => {
          const day = days[i];
          return (
            <div
              key={date}
              onMouseEnter={() => {
                setHighlightedDate(date);
                setHighlightedEmployee(null);
                setHighlightedCell(null);
              }}
              onClick={() => {
                setSelectedDate(date);
                setSelectedEmployee(null);
                setSelectedCell(null);
                setFilters(date, null);
              }}
              className={[
                'weekday',
                highlightedDate === date ? 'highlighted' : '',
                selectedDate === date ? 'selected' : '',
              ].join(' ')}
            >
              {day}
            </div>
          );
        })}

        {Array.from(employees).map((employeeName: string) => {
          return (
            <>
              <div
                key={employeeName}
                className={[
                  highlightedEmployee === employeeName ? 'highlighted' : '',
                  selectedEmployee === employeeName ? 'selected' : '',
                ].join(' ')}
                onMouseEnter={() => {
                  setHighlightedEmployee(employeeName);
                  setHighlightedDate(null);
                  setHighlightedCell(null);
                }}
                onClick={() => {
                  setSelectedEmployee(employeeName);
                  setSelectedDate(null);
                  setSelectedCell(null);
                  setFilters(null, employeeName);
                }}
              >
                <strong>{employeeName}</strong>
              </div>
              {dates.map((date, i) => {
                const standup = standupData.data.find((s: any) => s.date === date);
                const person = standup.standups.find((s: any) => s.name === employeeName);
                if (!standup || !person)
                  return (
                    <div
                      key={date + employeeName}
                      onMouseEnter={() => {
                        setHighlightedCell(date + employeeName);
                        setHighlightedEmployee(employeeName);
                        setHighlightedDate(date);
                      }}
                      className={[
                        highlightedEmployee === employeeName ||
                        highlightedDate === date ||
                        highlightedCell === date + employeeName
                          ? 'highlighted'
                          : '',
                        selectedEmployee === employeeName || selectedDate === date ? 'selected' : '',
                      ].join(' ')}
                    >
                      -
                    </div>
                  );

                return (
                  <div
                    key={date + employeeName}
                    onMouseEnter={() => {
                      setHighlightedCell(date + employeeName);
                      setHighlightedEmployee(employeeName);
                      setHighlightedDate(date);
                    }}
                    onClick={() => {
                      setSelectedCell(date + employeeName);
                      setSelectedEmployee(null);
                      setSelectedDate(null);
                      setFilters(date, employeeName);
                    }}
                    className={[
                      highlightedEmployee === employeeName ||
                      highlightedDate === date ||
                      highlightedCell === date + employeeName
                        ? 'highlighted'
                        : '',
                      selectedEmployee === employeeName || selectedDate === date || selectedCell === date + employeeName
                        ? 'selected'
                        : '',
                    ].join(' ')}
                  >
                    {person.is_working ? '✅' : '❌'}
                  </div>
                );
              })}
            </>
          );
        })}
      </StandupWeekSummaryTable>
    </StandupWeekSummaryHeader>
  );
};

const StandupListWrapper = styled.div`
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding: 20px;
`;

const DayWrapper = styled.div`
  display: flex;
  flex-direction: column;
  gap: 10px;
`;

const DayHeader = styled.div`
  display: flex;
  gap: 20px;
  align-items: baseline;
`;

const StandupHider = styled.div`
  display: flex;
  flex-direction: column;
  gap: 20px;
`;

const StandupList = ({
  standupData,
  filterDate,
  filterEmployee,
  userId,
}: {
  standupData: any;
  filterDate: string | null;
  filterEmployee: string | null;
  userId: string;
}) => {
  return (
    <StandupListWrapper>
      {standupData.data.map((standup: any) => {
        const date = new Date(standup.date);
        // Get day of week
        const day = date.toLocaleDateString('en-US', { weekday: 'long' });
        // Count standups with blockers
        const blocked = standup.standups.filter((s: any) => s.standup_blockers).length;

        if (filterDate && filterDate !== standup.date) return null;

        return (
          <DayWrapper key={standup.date}>
            <DayHeader>
              <h2>
                {standup.date} {day}
              </h2>
              <h3>
                Completed {standup.standups.length}/{NUMBER_OF_EMPLOYEES}
              </h3>
              <h3>
                Blocked {blocked}/{standup.standups.length}
              </h3>
            </DayHeader>
            <StandupHider>
              {standup.standups.map((s: any) => {
                if (filterEmployee && filterEmployee !== s.name) return null;
                return <StandupPersonEntry keyProp={s.id} standup={s} currentUser={s.user_id === userId} />;
              })}
            </StandupHider>
          </DayWrapper>
        );
      })}
    </StandupListWrapper>
  );
};

export const MOOD_LIST = [
  {
    mood: 'none',
    emoji: '❓',
  },
  {
    mood: 'happy',
    emoji: '😃',
  },
  {
    mood: 'sad',
    emoji: '😢',
  },
  {
    mood: 'neutral',
    emoji: '😐',
  },
  {
    mood: 'angry',
    emoji: '😡',
  },
  {
    mood: 'excited',
    emoji: '😁',
  },
  {
    mood: 'tired',
    emoji: '😴',
  },
  {
    mood: 'stressed',
    emoji: '😫',
  },
  {
    mood: 'confused',
    emoji: '😕',
  },
  {
    mood: 'relaxed',
    emoji: '😌',
  },
  {
    mood: 'awkward',
    emoji: '🥲',
  },
  {
    mood: 'skeptical',
    emoji: '🤨',
  },
  {
    mood: 'nerdy',
    emoji: '🤓',
  },
  {
    mood: 'partying',
    emoji: '🥳',
  },
  {
    mood: 'disguised',
    emoji: '🥸',
  },
  {
    mood: 'anxious',
    emoji: '🫣',
  },
  {
    mood: 'shocked',
    emoji: '😱',
  },
  {
    mood: 'mind_blown',
    emoji: '🤯',
  },
  {
    mood: 'saluting',
    emoji: '🫡',
  },
  {
    mood: 'cowboy',
    emoji: '🤠',
  },
  {
    mood: 'clown',
    emoji: '🤡',
  },
  {
    mood: 'poop',
    emoji: '💩',
  },
  {
    mood: 'dead',
    emoji: '💀',
  },
  {
    mood: 'rock_on',
    emoji: '🤟',
  },
  {
    mood: 'angry_cat',
    emoji: '😾',
  },
  {
    mood: 'curious',
    emoji: '👀',
  },
  {
    mood: 'heartbroken',
    emoji: '💔',
  },
  {
    mood: 'okay',
    emoji: '🆗',
  },
  {
    mood: 'red_flag',
    emoji: '🚩',
  },
];

const StandupWrapper = styled.div`
  display: flex;
  flex-direction: column;
  gap: 20px;
`;

const StandupTabWrapper = styled.div`
  display: flex;
  flex-direction: column;
  border: 1px solid #ddd;
  border-radius: 5px;
`;

const StandupTabs = styled.div`
  display: flex;
  justify-content: fill;

  button {
    width: 100%;
    padding: 10px 20px;
    background-color: #eee;
    color: black;
    border: none;
    cursor: pointer;
    transition: background-color 0.3s;

    &:hover {
      background-color: #ddd;
    }

    &.active {
      background-color: #fff;
      cursor: default;
    }
  }
`;

const StandupHeader = styled.div`
  display: flex;
  margin-bottom: 20px;
  justify-content: space-between;
`;

const DateWrapper = styled.div`
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: left;
  input {
    height: 40px;
    padding: 10px;
    font-size: 1rem;
  }
`;

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

const DateFootnote = styled.div`
  font-size: 1rem;
  color: #666;
`;

const StandupHomePage = ({
  serverUri,
  user,
}: {
  serverUri: string;
  user: {
    id: string;
    name: string;
    email: string;
    role: string;
  };
}) => {
  const router = useRouter();
  const searchParams = useSearchParams();
  const pathname = usePathname();

  const [selectedDate, setSelectedDateState] = useState<string>('');

  const [filterDate, setFilterDate] = useState<string | null>(null);
  const [filterEmployee, setFilterEmployee] = useState<string | null>(null);

  const [activeTab, setActiveTab] = useState<'list' | 'summary'>('list');

  const setFilters = (date: string | null, employee: string | null) => {
    setFilterDate(date);
    setFilterEmployee(employee);
  };

  const getStartOfWeek = (date: Date) => {
    return addDays(date, getDay(date) * -1);
  };
  const setSelectedDate = (date: string | Date) => {
    let dateObj;
    if (typeof date === 'string') {
      dateObj = new Date(date);
    } else {
      dateObj = date;
    }
    // Set the date to the sunday of the week
    dateObj = getStartOfWeek(dateObj);
    const newDateString = dateToString(dateObj);
    setSelectedDateState(newDateString);
    // const paramDateString = searchParams.get('date');
    // if (paramDateString !== newDateString) router.replace(`${pathname}?date=${newDateString}`);

    setFilters(null, null);
  };

  useEffect(() => {
    const date = searchParams.get('date');
    if (!date) {
      setSelectedDate(getDateString());
    } else {
      if (date !== selectedDate) setSelectedDate(date);
    }
  }, [searchParams]);

  const {
    data: standupData,
    isLoading: standupLoading,
    isError: standupError,
  } = useQuery({
    queryKey: ['standup', selectedDate],
    queryFn: async () => {
      const response = await fetch(`${serverUri}/api/admin/standup/week/${selectedDate}`, { credentials: 'include' });
      const data = await response.json();
      return data;
    },
  });

  const {
    data: standupSummaryData,
    isLoading: standupSummaryLoading,
    isError: standupSummaryError,
    refetch: refetchStandupSummary,
  } = useQuery({
    queryKey: ['standup-summary', selectedDate],
    queryFn: async () => {
      const response = await fetch(`${serverUri}/api/admin/standup/summary/${selectedDate}`, {
        credentials: 'include',
      });
      const data = await response.json();
      return data?.data;
    },
  });

  const { mutate: generateStandup, isLoading: generateStandupLoading } = useMutation(
    useCallback(async (date: string) => {
      const result = await fetch(`${serverUri}/api/admin/standup/summary/${date}/generate`, {
        credentials: 'include',
        method: 'POST',
      });

      if (!result.ok) {
        throw new Error('Failed to generate standup summary');
      }
      // Refetch the standup data
      refetchStandupSummary();
    }, [])
  );

  const getRelativeWeek = useCallback(() => {
    const date = new Date(selectedDate);
    const today = new Date();
    const currentWeek = getStartOfWeek(today);
    const week = getStartOfWeek(date);

    const weeks = differenceInCalendarWeeks(week, currentWeek);
    if (weeks === 0) {
      return 'This week';
    } else if (weeks === -1) {
      return 'Last week';
    } else if (weeks === 1) {
      return 'Next week';
    } else if (weeks < 0) {
      return `${Math.abs(weeks)} weeks ago`;
    } else {
      return `In ${weeks} weeks`;
    }
  }, [selectedDate]);

  return (
    <AdminWrapper>
      <h1>Standup Home</h1>
      <NavigationBar currentPage={NavbarPage.Standup} />

      <StandupHeader>
        <DateWrapper>
          <DateControlWrapper>
            <AdminButton
              onClick={() => {
                const date = new Date(selectedDate);
                setSelectedDate(addDays(date, -7));
              }}
            >
              -1 Week
            </AdminButton>
            <AdminButton
              onClick={() => {
                setSelectedDate(getDateString());
              }}
            >
              This Week
            </AdminButton>
            <AdminButton
              onClick={() => {
                const date = new Date(selectedDate);
                setSelectedDate(addDays(date, 7));
              }}
            >
              +1 Week
            </AdminButton>
            <input
              type="date"
              value={selectedDate}
              onChange={(e) => {
                setSelectedDate(e.target.value);
              }}
            />
            <div>{getRelativeWeek()}</div>
          </DateControlWrapper>
          <DateFootnote>
            Weeks start on Sunday to account for the weird timezones we work. Any date selected will snap to Sunday.
          </DateFootnote>
        </DateWrapper>

        <AdminButton
          onClick={() => {
            router.push('/admin/standup/crupdate');
          }}
          style={{
            fontSize: '1.2rem',
            fontWeight: 'bold',
            padding: '10px 20px',
          }}
        >
          New / Edit Standup
        </AdminButton>
      </StandupHeader>

      {standupLoading && <p>Loading...</p>}
      {standupError && <p>Error loading standups</p>}
      {standupData?.data && (
        <StandupWrapper>
          <StandupWeekSummary standupData={standupData} setFilters={setFilters} />

          <StandupTabWrapper>
            <StandupTabs>
              <button
                onClick={() => {
                  setActiveTab('list');
                }}
                className={activeTab === 'list' ? 'active' : ''}
              >
                Standup List
              </button>
              <button
                onClick={() => {
                  setActiveTab('summary');
                }}
                className={activeTab === 'summary' ? 'active' : ''}
              >
                AI Generated Summary
              </button>
            </StandupTabs>

            {activeTab === 'list' && (
              <StandupList
                standupData={standupData}
                filterDate={filterDate}
                filterEmployee={filterEmployee}
                userId={user.id}
              />
            )}

            {activeTab === 'summary' && (
              <>
                <div>
                  {standupSummaryLoading && <p>Loading...</p>}
                  {standupSummaryError && <p>Error loading standup summary</p>}
                  {!standupSummaryLoading && !standupSummaryError && standupSummaryData && (
                    <div
                      style={{
                        whiteSpace: 'pre-wrap',
                        padding: '20px',
                      }}
                    >
                      {standupSummaryData}
                    </div>
                  )}

                  {!standupSummaryLoading && !standupSummaryError && !standupSummaryData && (
                    <p>No standup summary available</p>
                  )}
                </div>

                <AdminButton
                  onClick={() => {
                    generateStandup(selectedDate);
                  }}
                  disabled={generateStandupLoading}
                >
                  {generateStandupLoading
                    ? 'Doing AI Stuff...'
                    : standupSummaryData
                    ? 'Regenerate Standup Summary'
                    : 'Generate Standup Summary'}
                </AdminButton>
              </>
            )}
          </StandupTabWrapper>
        </StandupWrapper>
      )}
    </AdminWrapper>
  );
};

export async function getServerSideProps(context: any) {
  const serverUri = process.env.SERVER_URI || 'http://localhost:3001';

  // Get the user's session based on the request
  if (context?.req?.user?.role !== 'admin') {
    context.res.statusCode = 404;
    context.res.end();
  }

  return {
    props: {
      serverUri,
      user: {
        id: context.req.user.id,
        name: context.req.user.username,
        email: context.req.user.email,
        role: context.req.user.role,
      },
    },
  };
}

export default StandupHomePage;
