'use client';

import { UserContext } from '@/context/user';
import { useGroups } from '@/lib/hooks/use-groups';
import { usePuzzles } from '@/lib/hooks/use-puzzles';
import type { Chapter, Puzzle, Tag } from '@/lib/puzzles';
import { cn } from '@/lib/utils';
import { useContext, useState } from 'react';
import { useForm } from 'react-hook-form';
import AppLink from './AppLink';
import Button from './Button';
import Dialog from './Dialog';
import Icon from './Icon';
import Input from './Input';
import Select from './Select';
import { useRouter } from 'next/navigation';

export default function Puzzles({ token }: { token: string }) {
  const { data: me } = useContext(UserContext);
  const { data, isLoading } = usePuzzles({ token });

  const [isOpen, setIsOpen] = useState<boolean[]>([]);

  function handleClick(index: number) {
    setIsOpen((prevState) => {
      const newState = [...prevState];
      newState[index] = !newState[index];
      return newState;
    });
  }

  function isInEventGroup(chapter: Chapter) {
    return (
      chapter.startDate &&
      chapter.endDate &&
      me?.groups?.some((group) => group.chapter && group.chapter === chapter.id)
    );
  }

  return (
    <>
      {(!isLoading &&
        data?.map((chapter) => (
          <div key={chapter.id} className="flex flex-col space-y-4">
            <div className="flex flex-col justify-between lg:flex-row lg:items-center">
              <div className="flex items-center gap-x-2">
                <h3 className="text-xl font-semibold sm:text-2xl">
                  Chapitre {chapter.id} - {chapter.name}{' '}
                </h3>
                {!isInEventGroup(chapter) && (
                  <Dialog
                    key={chapter.id}
                    title={chapter.name}
                    tooltip="Select Hogwarts Level"
                    open={isOpen[chapter.id]}
                    onOpenChange={() => handleClick(chapter.id)}
                    trigger={
                      <button className="flex items-center gap-x-2 text-sm font-semibold text-muted hover:text-brand">
                        <Icon name="group-line" />
                        Rejoindre un groupe
                      </button>
                    }
                    className="right-96 p-4"
                  >
                    <GroupForm chapter={chapter} token={token} />
                  </Dialog>
                )}
              </div>
              {chapter.startDate && chapter.endDate ? (
                <div className="flex items-center gap-x-2">
                  <Icon name="calendar-line" className="text-sm text-muted" />
                  <span className="text-sm text-muted">
                    {new Date(chapter.startDate).toLocaleDateString('fr-FR', {
                      day: 'numeric',
                      month: 'long',
                      year: 'numeric',
                      hour: 'numeric'
                    })}{' '}
                    -{' '}
                    {new Date(chapter.endDate).toLocaleDateString('fr-FR', {
                      day: 'numeric',
                      month: 'long',
                      year: 'numeric',
                      hour: 'numeric'
                    })}
                  </span>
                </div>
              ) : (
                <div className="h-1 w-1/4 rounded-lg bg-gray-200">
                  <div className="h-1 w-1/2 rounded-lg bg-gradient-to-tl from-brand to-brand-accent" />
                </div>
              )}
            </div>
            {isInEventGroup(chapter) && (
              <ul className="flex flex-col space-y-4">
                {chapter.puzzles &&
                  chapter.puzzles
                    .sort((p1, p2) => {
                      if (p1.tags == undefined) return 1;
                      if (p2.tags == undefined) return -1;
                      const e1 = p1.tags.findIndex((tag) => tag.name === 'easy') >= 0;
                      const e2 = p2.tags.findIndex((tag) => tag.name === 'easy') >= 0;
                      if (e1 && e2) return p1.tags.length - p2.tags.length;
                      if (e1) return -1;
                      if (e2) return 1;
                      const m1 = p1.tags.findIndex((tag) => tag.name === 'medium') >= 0;
                      const m2 = p2.tags.findIndex((tag) => tag.name === 'medium') >= 0;
                      if (m1 && m2) return p1.tags.length - p2.tags.length;
                      if (m1) return -1;
                      if (m2) return 1;
                      const h1 = p1.tags.findIndex((tag) => tag.name === 'hard') >= 0;
                      const h2 = p2.tags.findIndex((tag) => tag.name === 'hard') >= 0;
                      if (h1 && h2) return p1.tags.length - p2.tags.length;
                      if (h1) return -1;
                      if (h2) return 1;
                      return p1.tags.length - p2.tags.length;
                    })
                    .map((puzzle) => (
                      <PuzzleProp key={puzzle.id} puzzle={puzzle} chapter={chapter} />
                    ))}
              </ul>
            )}
          </div>
        ))) || (
        <div className="flex flex-col space-y-6">
          {[...Array(3).keys()].map((i) => (
            <div key={i} className="flex flex-col space-y-4">
              <div className="flex items-center justify-between">
                <span className="inline-block h-8 w-1/2 rounded-lg bg-primary-600" />
                <span
                  className="inline-block h-1 w-1/4 animate-pulse rounded-lg bg-primary-600"
                  style={{
                    animationDelay: `${i * 0.05}s`,
                    animationDuration: '1s'
                  }}
                />
              </div>
              <ul className="flex flex-col space-y-4">
                {[...Array(6).keys()].map((j) => (
                  <span
                    key={j}
                    className="inline-block h-14 animate-pulse rounded-lg bg-primary-600"
                    style={{
                      animationDelay: `${j * 0.05}s`,
                      animationDuration: '1s'
                    }}
                  />
                ))}
              </ul>
            </div>
          ))}
        </div>
      )}
    </>
  );
}

function PuzzleProp({ puzzle, chapter }: { puzzle: Puzzle; chapter: Chapter }) {
  const isPuzzleAvailable = (chapter: Chapter) => {
    const today = new Date();
    const startDate = new Date(chapter.startDate!);
    const endDate = new Date(chapter.endDate!);
    return (
      (chapter.startDate && chapter.endDate && today >= startDate && today <= endDate) ||
      (!chapter.startDate && !chapter.endDate)
    );
  };
  return (
    <li
      className={cn(
        'group relative flex h-full w-full rounded-md border-2 bg-primary-700 font-code hover:bg-primary-600',
        {
          'border-green-600/30': puzzle.tags?.map((tag) => tag.name.toLowerCase()).includes('easy'),
          'border-yellow-600/30': puzzle.tags
            ?.map((tag) => tag.name.toLowerCase())
            .includes('medium'),
          'border-red-600/30': puzzle.tags?.map((tag) => tag.name.toLowerCase()).includes('hard'),
          'border-highlight-primary': !puzzle.tags?.length,
          'cursor-not-allowed': !isPuzzleAvailable(chapter)
        }
      )}
    >
      {isPuzzleAvailable(chapter) ? (
        <AppLink
          className="flex h-full w-full items-center justify-between p-4"
          key={puzzle.id}
          href={`/dashboard/puzzles/${puzzle.id}`}
        >
          <div className="flex gap-x-2">
            <span className="text-base font-semibold">{puzzle.name}</span>
            {puzzle.tags?.length && (
              <div className="flex gap-x-2 text-sm text-muted">
                {puzzle.tags
                  .filter((tag) => !['easy', 'medium', 'hard'].includes(tag.name))
                  .map((tag, i) => (
                    <span
                      key={i}
                      className={cn('inline-block rounded-md bg-primary-900 px-2 py-1')}
                    >
                      {tag.name}
                    </span>
                  ))}
              </div>
            )}
          </div>
          <Icon
            className="-translate-x-2 transform-gpu duration-300 group-hover:translate-x-0"
            name="arrow-right-line"
          />
        </AppLink>
      ) : (
        <div className="flex h-full w-full items-center justify-between p-4 opacity-50">
          <div className="flex gap-x-2">
            <span className="text-base font-semibold">{puzzle.name}</span>
            {puzzle.tags?.length && (
              <div className="flex gap-x-2 text-sm text-muted">
                {puzzle.tags
                  .filter((tag) => !['easy', 'medium', 'hard'].includes(tag.name))
                  .map((tag, i) => (
                    <span
                      key={i}
                      className={cn('inline-block rounded-md bg-primary-900 px-2 py-1')}
                    >
                      {tag.name}
                    </span>
                  ))}
              </div>
            )}
          </div>
        </div>
      )}
    </li>
  );
}

type GroupData = {
  name?: string;
  chapter?: number;
  puzzle?: number;
};

function GroupForm({ chapter, token }: { chapter: Chapter; token: string }) {
  const [isJoining, setIsJoining] = useState(false);
  const router = useRouter();

  const { data: groups } = useGroups({ token });

  const {
    register,
    handleSubmit,
    formState: { errors },
    setError,
    reset
  } = useForm<GroupData>({
    defaultValues: {
      name: undefined,
      chapter: chapter.id,
      puzzle: undefined
    }
  });

  async function onSubmit(data: GroupData) {
    const res = await fetch(
      `${process.env.NEXT_PUBLIC_API_URL}/${isJoining ? 'groupJoin' : 'groupCreate'}`,
      {
        method: 'POST',
        body: JSON.stringify(data),
        headers: {
          Authorization: `Bearer ${token}`
        }
      }
    );
    // TODO: handle errors
    if (res.ok) {
      router.refresh();
    }
  }

  return (
    <div className="flex flex-col">
      <div className="flex justify-between">
        <button
          onClick={() => {
            setIsJoining(false);
            reset();
          }}
          className={cn('rounded-lg p-2 font-semibold', {
            'bg-primary-500': !isJoining
          })}
        >
          Créer un groupe
        </button>
        <button
          onClick={() => {
            setIsJoining(true);
            reset();
          }}
          className={cn('rounded-lg p-2 font-semibold', {
            'bg-primary-500': isJoining
          })}
        >
          Rejoindre un groupe
        </button>
      </div>
      <div className="px-2 py-4">
        <hr className="border-primary-600" />
      </div>
      <form
        className="flex w-full flex-col justify-between"
        onSubmit={handleSubmit(onSubmit)}
        encType="multipart/form-data"
      >
        <div className="flex w-56 flex-col space-y-4">
          {!isJoining ? (
            <>
              <div className="flex flex-col">
                <Input
                  className="w-full"
                  label="Nom du groupe"
                  type="text"
                  placeholder="Terre en vue mon capitaine !"
                  required
                  {...register('name')}
                />
              </div>
            </>
          ) : (
            <>
              <Select
                className="w-full"
                label="Groupes"
                required
                {...register('name')}
                options={
                  groups
                    ?.filter((group) => group.chapter === chapter.id)
                    .map((group) => ({
                      title: group.name,
                      value: group.name
                    })) || []
                }
              />
            </>
          )}
          <Button kind="brand" type="submit">
            {isJoining ? 'Rejoindre' : 'Créer'}
          </Button>
        </div>
      </form>
    </div>
  );
}
