import styled from '@emotion/styled';
import { useMutation, useQuery } from '@tanstack/react-query';
import { Field, Form, Formik } from 'formik';
import { useEffect, useState } from 'react';
import { gray400, gray800, green300 } from '../../next-res/colors';
import { AdminWrapper, InteractiveDate, JSONDisplay } from '../../next-res/components/admin/common';
import { FormFieldError } from './planOverrides';
import { NavbarPage, NavigationBar } from '../../next-res/components/admin/NavBar';

const Wrapper = styled(AdminWrapper)`
  button.light {
    cursor: pointer;
    color: black;
    backgroundcolor: white;
    border: 1px solid #ddd;
    minwidth: 70px;
    padding: 0 5px;
    margin: 0 5px;
    display: inline-block;
  }
`;

const Table = styled.table`
  width: 100%;
  tbody {
    tr:nth-of-type(odd) {
      background-color: #f9f9f9;
    }
    td.clickable {
      cursor: pointer;
      transition: background-color 0.3s;
    }
    td.clickable:hover {
      background-color: #f1f1f1;
    }
  }
  td,
  th {
    padding: 5px 10px;
  }
`;

const FormikForm = styled(Form)`
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  button {
    height: 40px;
    padding: 10px 15px;
    background-color: #0070f3;
    color: white;
    border: none;
    cursor: pointer;
  }
`;
const FormikField = styled(Field)`
  padding: 10px;
  margin: 10px 0;
  width: 100%;
`;

const FormikLabel = styled.label`
  display: flex;
  align-items: left;
  flex-direction: column;
  gap: 5px;
  width: 100%;
  margin: 10px 0;

  span.labelArea {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
  }
`;

const HideShowFormButton = styled.button`
  width: 100%;
  padding: 7px 20px;
  border: none;
  background-color: #eee;
  cursor: pointer;
  transition: background-color 0.3s ease;
  &:hover {
    background-color: #ddd;
  }
  margin-bottom: 20px;
`;

const MyURLsHider = styled.div`
  transition: all 0.4s ease;
  overflow: hidden;
`;

const CopyLinkButton = ({ text, toBeCopied }: { text: string; toBeCopied }) => {
  const [copied, setCopied] = useState(false);
  return (
    <button
      className="light"
      onClick={(e) => {
        e.preventDefault();
        navigator.clipboard.writeText(toBeCopied);
        setCopied(true);
        setTimeout(() => {
          setCopied(false);
        }, 2000);
      }}
    >
      {copied ? (
        <span
          style={{
            color: green300,
          }}
        >
          copied!
        </span>
      ) : (
        <>
          {' '}
          <svg
            style={{
              marginTop: '2px',
              marginRight: '5px',
            }}
            width="10"
            height="10"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
            stroke-linecap="round"
            stroke-linejoin="round"
          >
            <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
            <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
          </svg>
          {text}
        </>
      )}
    </button>
  );
};
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,
    },
  };
}

interface ShortenUrlFormValues {
  url: string;
  shortcode?: string;
}

const UrlShortener = ({ serverUri }: { serverUri: string }) => {
  const [showMyURLs, setShowMyURLs] = useState(true);
  const [currentShortcode, setCurrentShortcode] = useState('');
  const [selectedClick, setSelectedClick] = useState(null);

  useEffect(() => {
    // Needed to set the cookies
    async function getWhoami() {
      await fetch(`${serverUri}/auth/whoami`, { credentials: 'include' });
    }
    getWhoami();
  }, []);

  const { data: userShortUrls, refetch: refetchShortUrls } = useQuery({
    queryKey: ['shortUrls'],
    queryFn: async () => {
      const response = await fetch(`${serverUri}/api/admin/shortUrls`, {
        credentials: 'include',
      });
      const data = await response.json();
      return data;
    },
  });

  const { mutate: shortenUrlMutation } = useMutation(async (values: ShortenUrlFormValues) => {
    const response = await fetch(`${serverUri}/api/admin/urlShorten`, {
      method: 'POST',
      credentials: 'include',
      body: JSON.stringify({
        url: values.url.trim(),
        shortcode: values.shortcode?.trim(),
      }),
      headers: {
        'Content-Type': 'application/json',
      },
    });

    const data = await response.json();
    if (response.ok) {
      refetchShortUrls();
    } else {
      console.error('Error:', data);
      alert(data.error);
    }
  }, {});

  const { data: shortUrlData } = useQuery({
    queryKey: ['shortUrlClicks', currentShortcode],
    queryFn: async ({ queryKey }) => {
      const [, shortcode] = queryKey;
      const response = await fetch(`${serverUri}/api/admin/shortUrl/${shortcode}`, {
        credentials: 'include',
      });
      const data = await response.json();
      return data;
    },
  });

  return (
    <Wrapper>
      <h1
        style={{
          marginBottom: '20px',
        }}
      >
        URL Shortener Control Panel
      </h1>

      <NavigationBar currentPage={NavbarPage.ShortUrls} />

      <HideShowFormButton
        onClick={() => {
          setShowMyURLs((showMyURLs) => !showMyURLs);
        }}
      >
        {showMyURLs ? 'Hide My URLs' : 'Show My URLs'}
      </HideShowFormButton>

      <MyURLsHider
        style={{
          maxHeight: showMyURLs ? '500px' : '0',
          opacity: showMyURLs ? 1 : 0,
          overflow: 'auto',
        }}
      >
        <Formik
          initialValues={{
            url: '',
            shortcode: '',
          }}
          onSubmit={async (values) => {
            await shortenUrlMutation(values);
          }}
          validate={(values) => {
            const errors: any = {};
            if (!values.url.trim()) {
              errors.url = 'Required';
            }
            // Valid URL is valid
            try {
              new URL(values.url.trim());
            } catch (error) {
              errors.url = 'Invalid URL';
            }

            if (values.shortcode.trim()) {
              // Shortcode must be between 3 and 10 characters
              if (values.shortcode.trim().length < 3 || values.shortcode.trim().length > 20) {
                errors.shortcode = '3 <= code.length <= 20 ';
              }
              // Cannot contain spaces
              if (values.shortcode.includes(' ')) {
                errors.shortcode = 'Cannot contain spaces';
              }
            }
            return errors;
          }}
        >
          {({ isSubmitting }) => (
            <FormikForm>
              <div
                style={{
                  display: 'flex',
                  flexDirection: 'column',
                  width: '100%',
                  padding: '10px 20px',
                  border: `1px solid ${gray800}`,
                  borderRadius: '5px',
                  marginBottom: '20px',
                }}
              >
                <div
                  style={{
                    width: '100%',
                    display: 'flex',
                    flexDirection: 'row',
                    justifyContent: 'space-between',
                    alignItems: 'end',
                    gap: '10px',
                  }}
                >
                  <FormikLabel htmlFor="url">
                    <span className="labelArea">
                      <span>URL</span>
                      <FormFieldError name="url" component="div" />
                    </span>

                    <FormikField type="text" name="url" id="url" placeholder="https://example.com/something" />
                  </FormikLabel>

                  <FormikLabel
                    htmlFor="shortcode"
                    style={{
                      flexBasis: '35%',
                    }}
                  >
                    <span className="labelArea">
                      <span>Code</span>
                      <FormFieldError name="shortcode" component="div" />
                    </span>
                    <FormikField type="text" name="shortcode" id="shortcode" placeholder="Optional" />
                  </FormikLabel>
                  <button
                    type="submit"
                    disabled={isSubmitting}
                    style={{
                      marginBottom: '20px',
                    }}
                  >
                    Add
                  </button>
                </div>
              </div>
            </FormikForm>
          )}
        </Formik>
        {userShortUrls && userShortUrls?.length === 0 ? (
          <p>No URLs found</p>
        ) : (
          <Table
            style={{
              marginBottom: '20px',
            }}
          >
            <thead>
              <tr>
                <th>Long URL</th>
                <th>Short Code</th>
                <th>Clicks (30d)</th>
                <th>Created</th>
              </tr>
            </thead>
            <tbody>
              {userShortUrls?.map((short: any) => (
                <tr key={short.short_code}>
                  <td
                    style={{
                      maxWidth: '300px',
                      display: 'flex',
                      alignItems: 'center',
                    }}
                  >
                    <CopyLinkButton text="url" toBeCopied={short.long_url} />
                    <span
                      style={{
                        marginLeft: '10px',
                        display: 'inline-block',
                        overflow: 'hidden',
                        textOverflow: 'ellipsis',
                        whiteSpace: 'nowrap',
                      }}
                      title={short.long_url}
                    >
                      {short.long_url}
                    </span>
                  </td>
                  <td>
                    <CopyLinkButton text="code" toBeCopied={short.short_code} />
                    <CopyLinkButton text="url" toBeCopied={short.short_url} />
                    <span
                      style={{
                        marginLeft: '10px',
                        fontWeight: 'bold',
                      }}
                    >
                      {short.short_code}
                    </span>
                  </td>
                  <td>
                    <div
                      style={{
                        display: 'flex',
                        justifyContent: 'space-between',
                        width: '100%',
                        minWidth: '100px',
                      }}
                    >
                      <div
                        style={{
                          marginRight: '10px',
                        }}
                      >
                        {short.clicks}
                      </div>
                      <button
                        className="light"
                        onClick={() => {
                          setCurrentShortcode(short.short_code);
                        }}
                      >
                        Analytics
                      </button>
                    </div>
                  </td>
                  <td>
                    <InteractiveDate date={short.created_at} />
                  </td>
                </tr>
              ))}
            </tbody>
          </Table>
        )}
      </MyURLsHider>

      <hr />
      <div
        style={{
          margin: '20px 0',
          display: 'flex',
          justifyContent: 'space-between',
          alignItems: 'center',
        }}
      >
        <div
          style={{
            display: 'flex',
            marginRight: '20px',
            flexBasis: '50%',
            flexDirection: 'column',
            alignContent: 'center',
          }}
        >
          <span style={{ margin: '0 0 5px 0', fontSize: '28px' }}>Analytics</span>
          <span style={{ margin: '0', fontSize: '12px', color: gray400 }}>Get click analytics for any shortcode</span>
        </div>
        <Formik
          initialValues={{ shortcode: '' }}
          onSubmit={async (values) => {
            setCurrentShortcode(values.shortcode);
          }}
        >
          {({ isSubmitting }) => (
            <FormikForm>
              <div
                style={{
                  display: 'flex',
                  justifyContent: 'space-between',
                  alignItems: 'center',
                  width: '100%',
                  gap: '10px',
                }}
              >
                <FormikField type="text" name="shortcode" placeholder="shortcode" />
                <button type="submit" disabled={isSubmitting}>
                  Search
                </button>
              </div>
            </FormikForm>
          )}
        </Formik>
      </div>

      {currentShortcode && currentShortcode.length > 0 && (
        <>
          {shortUrlData?.error && (
            <>
              <p>Invalid Shortcode</p>
            </>
          )}
          {!shortUrlData?.error && (
            <>
              <div
                style={{
                  display: 'flex',
                  flexDirection: 'column',
                  justifyContent: 'left',
                  alignItems: 'baseline',
                  marginBottom: '20px',
                  gap: '5px',
                }}
              >
                <div>
                  <strong>Shortcode:</strong> {shortUrlData?.shortCode}
                  <CopyLinkButton text="copy" toBeCopied={`${serverUri}/s/${shortUrlData?.shortCode}`} />
                </div>
                <div>
                  <strong>Short URL:</strong> {shortUrlData?.shortUrl}
                  <CopyLinkButton text="copy" toBeCopied={shortUrlData?.shortUrl} />
                </div>
                <div>
                  <strong>Long URL:</strong> {shortUrlData?.longUrl}
                  <CopyLinkButton text="copy" toBeCopied={shortUrlData?.longUrl} />
                </div>
                <div>
                  <strong>Clicks (30d):</strong> {shortUrlData?.clickCount30Days}
                </div>
                <div>
                  <strong>Clicks (lifetime):</strong> {shortUrlData?.clickCountLifetime}
                </div>
                <div>
                  <strong>Created:</strong> <InteractiveDate date={shortUrlData?.createdAt} />
                </div>
              </div>

              <div
                style={{
                  display: 'flex',
                  justifyContent: 'left',
                  alignItems: 'baseline',
                  gap: '20px',
                  marginBottom: '20px',
                }}
              >
                <h2>Clicks</h2>
                <small>Only last 100 clicks are shown</small>
              </div>
              <Table>
                <tbody>
                  {shortUrlData?.clicks.map((click: any) => (
                    <tr key={click.created_at}>
                      <td
                        className="clickable"
                        onClick={() => {
                          if (selectedClick === click.created_at) {
                            setSelectedClick(null);
                          } else {
                            setSelectedClick(click.created_at);
                          }
                        }}
                      >
                        <InteractiveDate date={click.created_at} />
                        <JSONDisplay
                          style={{
                            maxHeight: selectedClick === click.created_at ? '500px' : '30px',
                          }}
                          json={click.request_information}
                        />
                      </td>
                    </tr>
                  ))}
                </tbody>
              </Table>
            </>
          )}
        </>
      )}
    </Wrapper>
  );
};

export default UrlShortener;
