import { ActionIcon, Card, Flex, Text, Stack, Indicator } from "@mantine/core";
import { PlayIcon, PencilIcon, SpeakerHighIcon } from "@phosphor-icons/react";
import React, { useCallback, useMemo } from "react";
import { MatchSlot } from "./match-slot";
import { Match } from "@/features/matches/types";
import { useSheet } from "@/hooks/use-sheet";
import { MatchForm } from "./match-form";
import Sheet from "@/components/sheet/sheet";
import { useServerMutation } from "@/lib/tanstack-query/hooks";
import { endMatch, startMatch } from "@/features/matches/server";
import { tournamentKeys } from "@/features/tournaments/queries";
import { useQueryClient } from "@tanstack/react-query";

interface MatchCardProps {
  match: Match;
  orders: Record<number, number>;
  showControls?: boolean;
}

export const MatchCard: React.FC<MatchCardProps> = ({
  match,
  orders,
  showControls,
}) => {
  const queryClient = useQueryClient();
  const editSheet = useSheet();
  const homeSlot = useMemo(
    () => ({
      from: orders[match.home_from_lid],
      from_loser: match.home_from_loser,
      team: match.home,
      seed: match.home_seed,
      cups: match.status === "ended" ? match.home_cups : undefined,
      isWinner:
        match.status === "ended" &&
        match.home_cups !== undefined &&
        match.away_cups !== undefined &&
        match.home_cups > match.away_cups,
    }),
    [match]
  );
  const awaySlot = useMemo(
    () => ({
      from: orders[match.away_from_lid],
      from_loser: match.away_from_loser,
      team: match.away,
      seed: match.away_seed,
      cups: match.status === "ended" ? match.away_cups : undefined,
      isWinner:
        match.status === "ended" &&
        match.away_cups !== undefined &&
        match.home_cups !== undefined &&
        match.away_cups > match.home_cups,
    }),
    [match]
  );

  const showToolbar = useMemo(
    () => match.status === "ready" && showControls,
    [match.status, showControls]
  );

  const showEditButton = useMemo(
    () => showControls && match.status === "started",
    [showControls, match.status]
  );

  const start = useServerMutation({
    mutationFn: startMatch,
    successMessage: "Match started!",
    onSuccess: () => {
      queryClient.invalidateQueries({
        queryKey: tournamentKeys.details(match.tournament.id),
      });
    },
  });

  const end = useServerMutation({
    mutationFn: endMatch,
    onSuccess: () => {
      queryClient.invalidateQueries({
        queryKey: tournamentKeys.details(match.tournament.id),
      });
    },
  });

  const handleStart = useCallback(async () => {
    await start.mutate({
      data: match.id,
    });
  }, [match]);

  const handleFormSubmit = useCallback(
    async (data: {
      home_cups: number;
      away_cups: number;
      ot_count: number;
    }) => {
      await end.mutate({
        data: {
          ...data,
          matchId: match.id,
        },
      });
      editSheet.close();
    },
    [match.id, editSheet]
  );

  const handleSpeakerClick = useCallback(() => {
    if ("speechSynthesis" in window && match.home?.name && match.away?.name) {
      const utterance = new SpeechSynthesisUtterance(
        `${match.home.name} vs. ${match.away.name}`
      );

      const voices = window.speechSynthesis.getVoices();

      const preferredVoice =
        voices.find(
          (voice) =>
            voice.lang.startsWith("en") && voice.name.includes("Daniel")
        ) ||
        voices.find((voice) => voice.lang.startsWith("en") && voice.default);

      if (preferredVoice) {
        utterance.voice = preferredVoice;
      }

      utterance.rate = 0.9;
      utterance.volume = 0.8;
      utterance.pitch = 1.0;

      window.speechSynthesis.speak(utterance);
    }
  }, [match.home?.name, match.away?.name]);

  return (
    <Flex direction="row" align="center" justify="end" gap={8}>
      <Text c="dimmed" fw="bolder">
        {match.order}
      </Text>
      <Flex align="stretch">
        <Indicator
          inline
          processing={match.status === "started"}
          color="red"
          size={12}
          disabled={match.status !== "started" || showEditButton}
        >
          <Card
            w={showToolbar || showEditButton ? 200 : 220}
            withBorder
            pos="relative"
            style={{ overflow: "visible" }}
            data-match-lid={match.lid}
          >
            <Card.Section withBorder p={0}>
              <MatchSlot {...homeSlot} />
            </Card.Section>

            <Card.Section p={0} mb={-16}>
              <MatchSlot {...awaySlot} />
            </Card.Section>

            {match.reset && (
              <Text
                pos="absolute"
                top={-20}
                left={8}
                size="xs"
                c="dimmed"
                fw="bold"
              >
                * If necessary
              </Text>
            )}

            {showControls && (
              <ActionIcon
                pos="absolute"
                bottom={-2}
                left={-26}
                size="sm"
                variant="subtle"
                color="gray"
                onClick={handleSpeakerClick}
              >
                <SpeakerHighIcon size={12} />
              </ActionIcon>
            )}
          </Card>
        </Indicator>

        {showToolbar && (
          <Flex direction="column" justify="center" align="center">
            <ActionIcon
              color="green"
              onClick={handleStart}
              size="sm"
              h="100%"
              radius="sm"
              ml={-4}
              style={{
                borderTopLeftRadius: 0,
                borderBottomLeftRadius: 0,
              }}
            >
              <PlayIcon size={14} />
            </ActionIcon>
          </Flex>
        )}

        {showEditButton && (
          <Flex direction="column" justify="center" align="center">
            <ActionIcon
              color="blue"
              onClick={editSheet.open}
              size="sm"
              h="100%"
              radius="sm"
              ml={-4}
              style={{
                borderTopLeftRadius: 0,
                borderBottomLeftRadius: 0,
              }}
            >
              <PencilIcon size={14} />
            </ActionIcon>
          </Flex>
        )}
      </Flex>

      <Sheet title="Edit Match" {...editSheet.props}>
        <MatchForm
          match={match}
          onSubmit={handleFormSubmit}
          onCancel={editSheet.close}
        />
      </Sheet>
    </Flex>
  );
};
