import styled from '@emotion/styled';
import { useMutation, useQuery } from '@tanstack/react-query';
import { Field, Form, Formik, useFormikContext } from 'formik';
import { usePathname, useSearchParams } from 'next/navigation';
import { useRouter } from 'next/router';
import React, { useCallback, useEffect, useState } from 'react';
import { MOOD_LIST } from '.';
import { NavbarPage, NavigationBar } from '../../../next-res/components/admin/NavBar';
import { AdminButton, AdminWrapper } from '../../../next-res/components/admin/common';
import { getDateString, getRelativeDate } from '../../../next-res/lib/date';

const FormWrapper = styled(Form)`
  display: flex;
  flex-direction: column;
  gap: 20px;
`;

const LabelWrapper = styled.div`
  display: flex;
  justify-content: space-between;
  align-items: center;
`;

const FieldWrapper = styled.div`
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 1.5rem;

  label {
    font-size: 1.4rem;
    font-weight: bold;
  }
  textarea {
    padding: 0.5rem;
    font-size: 1.2rem;
    font-family: 'Roboto', sans-serif;
    min-height: 200px;
  }
`;

const DateWrapper = styled.div`
  display: flex;
  gap: 0.5rem;

  input[type='date'] {
    padding: 0.5rem;
    font-size: 1.2rem;
    width: 170px;
    text-align: center;
  }
`;

const WorkingTitle = styled.h2`
  font-size: 1.4rem;
`;
const WorkingWrapper = styled.div`
  display: flex;
  gap: 0.5rem;
`;
const WorkingButton = styled(AdminButton)<{ selected: boolean; working: boolean }>`
  background-color: ${(props) => (props.selected ? (props.working ? '#c0fec0' : '#fec0c0') : '#fff')};
  border: 1px solid #f0f0f0;
  border-radius: 0.5rem;
  padding: 10px;
  width: 100%;
  font-size: 1.3rem;
  cursor: pointer;
  transition: background-color 0.2s;
  position: relative;
  transition: background-color 0.2s;

  &:hover {
    background-color: ${(props) => (props.selected ? (props.working ? '#b9f5b9' : '#f5b9b9') : '#f0f0f0')};
  }
`;

const MoodWrapper = styled.div`
  display: flex;
  gap: 0.5rem;

  button {
    padding: 20px;
    font-size: 2rem;
    cursor: pointer;
    background-color: #fff;
    border: 1px solid #f0f0f0;
    border-radius: 0.5rem;
    transition: background-color 0.2s;
    position: relative;

    span {
      font-size: 1.2rem;
      position: absolute;
      bottom: 0;
      left: 50%;
      transform: translateX(-50%) translateY(100%);
      opacity: 0;
      transition: opacity 0.2s;
    }

    &:hover {
      background-color: #f0f0f0;

      span {
        opacity: 1;
      }
    }
    &.selected {
      background-color: #c0fec0;
    }
  }
`;

const LoggedInWrapper = styled.div`
  display: flex;
  gap: 0.8rem;
  margin-bottom: 1.5rem;
  font-size: 1.2rem;
  border: 1px solid #f0f0f0;
  padding: 0.5rem;
  border-radius: 0.5rem;
`;

const PreviousStandupWrapper = styled.div`
  display: flex;
  flex-direction: column;
  border: 1px solid #f0f0f0;
  border-radius: 0.5rem;
  padding: 1rem;
  cursor: pointer;
  transition: background-color 0.2s;
  margin-bottom: 1.5rem;
  background-color: #fdfdf2;

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

  h1 {
    font-size: 1.3rem;
    font-weight: bold;
  }

  p {
    margin: 0;
    white-space: pre-wrap;
  }

  .hider {
    overflow: hidden;
    transition: max-height 500ms ease-in-out;
    max-height: 0;
    display: flex;
    flex-direction: row;
  }

  .row {
    display: flex;
    gap: 0.5rem;
    width: 100%;
  }

  .col {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    width: 100%;
  }

  &.hide {
    .hider {
      max-height: 0;
    }
  }

  &.show {
    .hider {
      max-height: 3000px;
    }
  }
`;

const AutoRedirectSetting = styled.span`
  padding: 0.5rem;
  align-items: center;
  font-size: 1rem;
  display: flex;

  * {
    cursor: pointer;
    &:hover {
      text-decoration: underline;
    }
  }
  input {
    margin-right: 1rem;
    width: 1.2rem;
    height: 1.2rem;
  }
`;

// handle when form values change
const FormikOnChange = ({ onChange }) => {
  const { values } = useFormikContext();

  useEffect(() => {
    onChange(values);
  }, [values]);

  return null;
};

const StandupCrupdateForm = ({
  serverUri,
  user,
}: {
  serverUri: string;
  user: {
    id: string;
    name: string;
    email: string;
    role: string;
  };
}) => {
  const formRef = React.useRef(null);
  // Check for date param
  const searchParams = useSearchParams();
  const router = useRouter();
  const pathname = usePathname();

  const [savedStandup, setSavedStandup] = useState(false);
  const [unsavedChanges, setUnsavedChanges] = useState(false);

  const [autoRedirect, setAutoRedirect] = useState(true);

  const [previousStandupPlaceholder, setPreviousStandupPlaceholder] = useState(null);

  const [currentStandupData, setCurrentStandupData] = useState(null);

  const [formValues, setFormValues] = useState(null);

  const [showPreviousStandup, setShowPreviousStandup] = useState(false);

  useEffect(() => {
    autosaveChanges(formValues);
  }, [formValues]);

  useEffect(() => {
    window.addEventListener('keydown', (e) => {
      if (e.key === 's' && (e.ctrlKey || e.metaKey)) {
        e.preventDefault();
        const form = formRef.current;
        if (form) {
          form.submitForm();
        }
      }
    });

    return () => {
      window.removeEventListener('keydown', () => {});
    };
  }, []);

  useEffect(() => {
    const date = searchParams.get('date');
    if (!date) {
      router.replace('/admin/standup/crupdate?date=' + getDateString());
    } else {
      const form = formRef.current;
      if (form && !form.values.date) {
        form.setFieldValue('date', date);
      }
    }
  }, [searchParams]);

  const {
    data: standupData,
    isLoading: standupIsLoading,
    isError: standupIsError,
  } = useQuery({
    queryKey: ['standup', user.id, searchParams.get('date')],
    queryFn: async () => {
      const response = await fetch(`${serverUri}/api/admin/standup/${user.id}/${searchParams.get('date')}`, {
        credentials: 'include',
      });
      const data = await response.json();

      return data;
    },
  });

  useEffect(() => {
    if (standupData?.data?.currentStandup) {
      setCurrentStandupData(standupData.data.currentStandup);
      const form = formRef.current;
      if (form) {
        const currentStandup = standupData.data.currentStandup;
        form.setValues({
          date: searchParams.get('date'),
          working: currentStandup.is_working ? 'true' : 'false',
          standup_done: currentStandup.standup_done,
          standup_doing: currentStandup.standup_doing,
          standup_blockers: currentStandup.standup_blockers,
          standup_mood: currentStandup.standup_mood,
        });
      }
    } else {
      setCurrentStandupData(null);
      const form = formRef.current;
      if (form) {
        form.setValues({
          date: searchParams.get('date'),
          working: 'true',
          standup_done: '',
          standup_doing: '',
          standup_blockers: '',
          standup_mood: 'none',
        });
      }
    }
  }, [standupData]);

  const autosaveChanges = useCallback(
    (values) => {
      let thisUnsavedChanges = true;
      // Check if the values are the same as the saved data
      if (currentStandupData) {
        if (
          currentStandupData.standup_done === values.standup_done &&
          currentStandupData.standup_doing === values.standup_doing &&
          currentStandupData.standup_blockers === values.standup_blockers &&
          currentStandupData.standup_mood === values.standup_mood &&
          currentStandupData.working === values.working
        ) {
          thisUnsavedChanges = false;
        }
      }
      // Check if working is same
      // Check if the values are empty
      if (values?.working === 'true' && !values?.standup_done && !values?.standup_doing && !values?.standup_blockers) {
        thisUnsavedChanges = false;
      }

      if (unsavedChanges !== thisUnsavedChanges) {
        setUnsavedChanges(() => thisUnsavedChanges);
      }
    },
    [currentStandupData, unsavedChanges]
  );

  const {
    mutate: upsertStandupMutation,
    isLoading: upsertStandupIsLoading,
    isError: upsertStandupIsError,
    isSuccess: upsertStandupIsSuccess,
    reset: upsertStandupReset,
  } = useMutation(
    useCallback(
      async (values: {
        date: string;
        standup_done: string;
        standup_doing: string;
        standup_blockers: string;
        standup_mood: string;
        working: string;
      }) => {
        const response = await fetch(`${serverUri}/api/admin/standup`, {
          credentials: 'include',
          method: 'POST',
          body: JSON.stringify({
            userId: user.id,
            date: values.date,
            standup_done: values.standup_done,
            standup_doing: values.standup_doing,
            standup_blockers: values.standup_blockers,
            standup_mood: values.standup_mood,
            is_working: values.working === 'true',
          }),
          headers: {
            'Content-Type': 'application/json',
          },
        });
        if (!response.ok) {
          throw new Error('Error upserting standup');
        }

        setSavedStandup(true);
        setUnsavedChanges(false);
        setCurrentStandupData({
          standup_done: values.standup_done,
          standup_doing: values.standup_doing,
          standup_blockers: values.standup_blockers,
          standup_mood: values.standup_mood,
          working: values.working,
        });
        setTimeout(() => {
          setSavedStandup(false);
        }, 3000);

        if (autoRedirect) {
          router.push('/admin/standup');
        }

        const data = await response.json();
        return data;
      },
      [user.id, autoRedirect]
    )
  );

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

      <div
        style={{
          display: 'flex',
          justifyContent: 'left',
          gap: '2rem',
          alignItems: 'center',
        }}
      >
        <AdminButton
          onClick={() => {
            router.push('/admin/standup');
          }}
        >
          ← Back to Standup Home
        </AdminButton>
        <AutoRedirectSetting>
          <input id="autoRedirect" type="checkbox" checked={autoRedirect} onClick={() => setAutoRedirect((a) => !a)} />
          <label htmlFor="autoRedirect">Auto redirect after save</label>
        </AutoRedirectSetting>
      </div>

      <div
        style={{
          display: 'flex',
          gap: '1rem',
          alignItems: 'center',
        }}
      >
        <h2>Create / Update Entry</h2>{' '}
        {unsavedChanges && (
          <span
            style={{
              color: 'red',
              marginLeft: '1rem',
            }}
          >
            Unsaved changes
          </span>
        )}
      </div>

      <LoggedInWrapper>
        <div>Logged in as:</div>
        <div>
          {user.name} ({user.id})
        </div>
        <div>{user.email}</div>
        {!user.email.includes('@wavtool.com') && (
          <div
            style={{
              color: 'red',
              fontSize: '1.2rem',
            }}
          >
            Please use your wavtool email
          </div>
        )}
      </LoggedInWrapper>

      <Formik
        innerRef={formRef}
        initialValues={{
          date: '',
          working: 'true',
          standup_done: '',
          standup_doing: '',
          standup_blockers: '',
          standup_mood: 'none',
        }}
        onSubmit={(values) => {
          console.log('submitting', values);
          upsertStandupMutation(values);
        }}
      >
        {({ values, handleChange }) => {
          return (
            <FormWrapper>
              <FormikOnChange onChange={setFormValues} />
              {standupIsLoading && <p>Loading...</p>}

              {standupIsError && <p>Error</p>}

              {!standupIsLoading && (
                <>
                  <FieldWrapper>
                    <LabelWrapper>
                      <label htmlFor="date">Date</label>
                    </LabelWrapper>
                    <DateWrapper>
                      <AdminButton
                        type="button"
                        onClick={() => {
                          const dateString = getDateString(-2);
                          handleChange('date')(dateString);
                          router.replace(pathname + '?date=' + dateString);
                        }}
                      >
                        2 days ago
                      </AdminButton>
                      <AdminButton
                        type="button"
                        onClick={() => {
                          const dateString = getDateString(-1);
                          handleChange('date')(dateString);
                          router.replace(pathname + '?date=' + dateString);
                        }}
                      >
                        Yesterday
                      </AdminButton>
                      <AdminButton
                        type="button"
                        onClick={() => {
                          const dateString = getDateString();
                          handleChange('date')(dateString);
                          router.replace(pathname + '?date=' + dateString);
                        }}
                      >
                        Today
                      </AdminButton>

                      <input
                        name="date"
                        placeholder="Date"
                        type="date"
                        value={values.date}
                        onChange={(e) => {
                          handleChange('date')(e.target.value);
                          router.replace(pathname + '?date=' + e.target.value);
                        }}
                        style={{
                          marginLeft: '2rem',
                        }}
                      />
                      <div
                        style={{
                          display: 'flex',
                          alignItems: 'center',
                          fontSize: '1.5rem',
                          marginRight: '0.5rem',
                        }}
                      >
                        {
                          // Display day of week
                          new Date(values.date).toLocaleDateString('en-US', {
                            weekday: 'short',
                          })
                        }
                      </div>
                      <div
                        style={{
                          display: 'flex',
                          alignItems: 'center',
                          fontSize: '1.2rem',
                        }}
                      >
                        {/* Display relative date */}
                        {getRelativeDate(values.date)}
                      </div>
                    </DateWrapper>
                  </FieldWrapper>

                  <PreviousStandupWrapper
                    className={showPreviousStandup ? 'show' : 'hide'}
                    onClick={() => {
                      setShowPreviousStandup((s) => !s);
                    }}
                  >
                    <div className="row">
                      <h1>Previous Standup:</h1>{' '}
                      {standupData?.data?.previousStandup ? (
                        <>
                          <h1>
                            {standupData.data.previousStandup.date}{' '}
                            {MOOD_LIST.find((m) => m.mood === standupData.data.previousStandup.standup_mood)?.emoji}
                          </h1>
                          <h1>({getRelativeDate(standupData.data.previousStandup.date)})</h1>
                        </>
                      ) : (
                        <h1>None</h1>
                      )}
                    </div>

                    {standupData?.data?.previousStandup && (
                      <div className="hider">
                        <div className="row">
                          <div className="col">
                            <strong>What I got done since last standup</strong>
                            <p>{standupData.data.previousStandup.standup_done}</p>
                          </div>
                          <div className="col">
                            <strong>What I'm getting done today</strong>
                            <p>{standupData.data.previousStandup.standup_doing}</p>
                          </div>
                          <div className="col">
                            <strong>Things that could block me</strong>
                            <p>{standupData.data.previousStandup.standup_blockers}</p>
                          </div>
                        </div>
                      </div>
                    )}
                  </PreviousStandupWrapper>

                  <WorkingTitle>Are you working?</WorkingTitle>
                  <WorkingWrapper>
                    <WorkingButton
                      onClick={(e) => {
                        handleChange('working')('true');
                        e.preventDefault(); // Prevent auto submitting on button click
                      }}
                      selected={values.working === 'true'}
                      working={true}
                    >
                      Yes
                    </WorkingButton>
                    <WorkingButton
                      onClick={(e) => {
                        handleChange('working')('false');
                        e.preventDefault(); // Prevent auto submitting on button click
                      }}
                      selected={values.working === 'false'}
                      working={false}
                    >
                      No
                    </WorkingButton>
                  </WorkingWrapper>
                  <FieldWrapper>
                    <LabelWrapper>
                      <label htmlFor="standup_done">What I got done since last standup</label>
                      {
                        // If standup is empty, show button to copy from previous day
                        values.standup_done === '' && standupData?.data?.previousStandup && (
                          <AdminButton
                            type="button"
                            onClick={() => {
                              const previousStandup = standupData.data.previousStandup;
                              handleChange('standup_done')(previousStandup.standup_doing);
                            }}
                            onMouseEnter={() => {
                              const previousStandup = standupData.data.previousStandup;
                              setPreviousStandupPlaceholder(previousStandup.standup_doing);
                            }}
                            onMouseLeave={() => {
                              setPreviousStandupPlaceholder(null);
                            }}
                          >
                            Copy from previous standup
                          </AdminButton>
                        )
                      }
                    </LabelWrapper>

                    <Field
                      name="standup_done"
                      disabled={values.working === 'false'}
                      placeholder={
                        previousStandupPlaceholder || 'What did you work on yesterday, or the past time period.'
                      }
                      onChange={(e) => {
                        handleChange('standup_done')(e.target.value);
                      }}
                      as="textarea"
                    />
                  </FieldWrapper>

                  <FieldWrapper>
                    <LabelWrapper>
                      <label htmlFor="standup_doing">What I'm getting done today</label>
                    </LabelWrapper>
                    <Field
                      name="standup_doing"
                      disabled={values.working === 'false'}
                      placeholder="What do you plan on working on next?"
                      as="textarea"
                      onChange={(e) => {
                        handleChange('standup_doing')(e.target.value);
                      }}
                    />
                  </FieldWrapper>

                  <FieldWrapper>
                    <LabelWrapper>
                      <label htmlFor="standup_blockers">Things that could block me</label>
                    </LabelWrapper>
                    <Field
                      name="standup_blockers"
                      disabled={values.working === 'false'}
                      placeholder="Leave this blank if you have no blockers."
                      as="textarea"
                      onChange={(e) => {
                        handleChange('standup_blockers')(e.target.value);
                      }}
                    />
                  </FieldWrapper>
                  <FieldWrapper>
                    <LabelWrapper>
                      <label htmlFor="standup_mood">Mood</label>
                    </LabelWrapper>
                    <MoodWrapper>
                      {MOOD_LIST.map((mood) => (
                        <button
                          key={mood.mood}
                          type="button"
                          disabled={values.working === 'false'}
                          className={values.standup_mood === mood.mood ? 'selected' : ''}
                          title={mood.mood}
                          onClick={() => {
                            handleChange('standup_mood')(mood.mood);
                          }}
                        >
                          {mood.emoji}

                          <span>{mood.mood}</span>
                        </button>
                      ))}
                    </MoodWrapper>
                  </FieldWrapper>

                  <div
                    style={{
                      display: 'flex',
                      justifyContent: 'left',
                      gap: '2rem',
                      alignItems: 'center',
                    }}
                  >
                    <AdminButton
                      type="submit"
                      style={{
                        marginRight: '1rem',
                        width: '200px',
                      }}
                      disabled={!values.date || !unsavedChanges || upsertStandupIsLoading}
                    >
                      {upsertStandupIsLoading ? 'Saving...' : 'Save'}
                    </AdminButton>
                    <AutoRedirectSetting>
                      <input
                        id="autoRedirect"
                        type="checkbox"
                        checked={autoRedirect}
                        onClick={() => setAutoRedirect((a) => !a)}
                      />
                      <label htmlFor="autoRedirect">Auto redirect after save</label>
                    </AutoRedirectSetting>
                    {savedStandup && (
                      <span
                        style={{
                          color: 'green',
                          marginLeft: '1rem',
                        }}
                      >
                        Saved
                      </span>
                    )}
                    {unsavedChanges && (
                      <span
                        style={{
                          color: 'red',
                          marginLeft: '1rem',
                        }}
                      >
                        Unsaved changes
                      </span>
                    )}
                  </div>
                </>
              )}
            </FormWrapper>
          );
        }}
      </Formik>
    </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 StandupCrupdateForm;
