import { useDeleteChallengeActionMutation } from '@/hooks/mutations/useChallengeMutation'
import { useGameRepairMutation } from '@/hooks/mutations/useGameMutation'
import { useDeleteTrainMutation } from '@/hooks/mutations/useTrainMutation'
import { useAuth } from '@/hooks/useAuth'
import { useChallengeActions } from '@/hooks/useChallengeActions'
import { useChallenges } from '@/hooks/useChallenges'
import { useMoneyUpdates } from '@/hooks/useMoneyUpdates'
import { useTrain } from '@/hooks/useTrain'
import { MoneyUpdate } from '@/utils/features/moneyUpdates/moneyUpdatesSlice'
import { FontAwesome6 } from '@expo/vector-icons'
import { useQueryClient } from '@tanstack/react-query'
import { useMemo, useState } from 'react'
import { FlatList } from 'react-native'
import { Button, Dialog, Divider, List, MD3Colors, Portal, Snackbar, Surface, Text } from 'react-native-paper'

export default function HistoryScreen() {
  const auth = useAuth()
  const queryClient = useQueryClient()
  const moneyUpdates = useMoneyUpdates()
  const [deletingMoneyUpdate, setDeletingMoneyUpdate] = useState<MoneyUpdate | null>(null)

  const [successVisible, setSuccessVisible] = useState(false)
  const [successMessage, setSuccessMessage] = useState("")
  const [errorVisible, setErrorVisible] = useState(false)
  const [error, setError] = useState([200, ""])

  const deleteTrainMutation = useDeleteTrainMutation({
    auth,
    onPostSuccess: () => {
      setDeletingMoneyUpdate(null)
      setSuccessVisible(true)
      setSuccessMessage("Train supprimé")
      gameRepairMutation.mutate()
      queryClient.invalidateQueries({ predicate: (query) => query.queryKey[0] === 'get-money-updates' || query.queryKey[0] === 'get-trains' })
    },
    onError: ({ response, error }) => {
      setErrorVisible(true)
      if (response)
        setError([response.statusCode, response.message])
      else if (error)
        setError([400, error.message])
    },
  })
  const deleteChallengeActionMutation = useDeleteChallengeActionMutation({
    auth,
    onPostSuccess: () => {
      setDeletingMoneyUpdate(null)
      setSuccessVisible(true)
      setSuccessMessage("Réalisation du défi supprimée")
      gameRepairMutation.mutate()
      queryClient.invalidateQueries({ predicate: (query) => query.queryKey[0] === 'get-money-updates' || query.queryKey[0] === 'get-challenges' })
    },
    onError: ({ response, error }) => {
      setErrorVisible(true)
      if (response)
        setError([response.statusCode, response.message])
      else if (error)
        setError([400, error.message])
    },
  })
  const gameRepairMutation = useGameRepairMutation({
    auth,
    onPostSuccess: () => {
      queryClient.invalidateQueries({ predicate: (query) => query.queryKey[0] === 'get-player' })
    },
    onError: ({ response, error }) => {
      setErrorVisible(true)
      if (response)
        setError([response.statusCode, response.message])
      else if (error)
        setError([400, error.message])
    },
  })

  function deleteMoneyUpdate(): void {
    if (!deletingMoneyUpdate)
      return
    switch (deletingMoneyUpdate.reason) {
      case 'BUY_TRAIN':
        if (!deletingMoneyUpdate.tripId) return
        deleteTrainMutation.mutate(deletingMoneyUpdate.tripId)
        break
      case 'CHALLENGE':
        if (!deletingMoneyUpdate.actionId) return
        deleteChallengeActionMutation.mutate(deletingMoneyUpdate.actionId)
        break
    }
    setDeletingMoneyUpdate(null)
  }

  return (
    <Surface style={{ flex :1 }}>
      <FlatList
        data={moneyUpdates}
        keyExtractor={(moneyUpdate) => `money-update-list-item-${moneyUpdate.id}`}
        ItemSeparatorComponent={() => <Divider />}
        renderItem={(item) => 
          <MoneyUpdateListItem moneyUpdate={item.item}
                               onDelete={['START', 'NEW_RUN'].includes(item.item.reason) ? undefined : () => setDeletingMoneyUpdate(item.item)} />} />
      <Snackbar
          key='success-snackbar'
          visible={successVisible}
          icon={'close'}
          onDismiss={() => setSuccessVisible(false)}
          onIconPress={() => setSuccessVisible(false)}>
        <Text variant='bodyMedium' style={{ color: MD3Colors.secondary0 }}>
          {successMessage}
        </Text>
      </Snackbar>
      <Snackbar
          key='error-snackbar'
          visible={errorVisible}
          icon={'close'}
          onDismiss={() => setErrorVisible(false)}
          onIconPress={() => setErrorVisible(false)}>
        <Text variant='bodyMedium' style={{ color: MD3Colors.secondary0 }}>
          Erreur {error[0]} : {error[1]}
        </Text>
      </Snackbar>
      <Portal>
        <Dialog visible={deletingMoneyUpdate !== null} onDismiss={() => setDeletingMoneyUpdate(null)}>
          <Dialog.Title>Êtes-vous sûre ?</Dialog.Title>
          <Dialog.Content>
            <Text>Voulez-vous vraiment supprimer ce mouvement de fonds ?</Text>
            {deletingMoneyUpdate && <MoneyUpdateListItem moneyUpdate={deletingMoneyUpdate} />}
          </Dialog.Content>
          <Dialog.Actions>
            <Button onPress={() => setDeletingMoneyUpdate(null)}>Annuler</Button>
            <Button onPress={() => deleteMoneyUpdate()}>Confirmer</Button>
          </Dialog.Actions>
        </Dialog>
      </Portal>
    </Surface>
  )
}

function MoneyUpdateListItem({ moneyUpdate, onDelete }: { moneyUpdate: MoneyUpdate, onDelete?: () => void }) {
  const trains = useTrain()
  const challengeActions = useChallengeActions()
  const challenges = useChallenges()

  const icon = useMemo(() => {
    switch (moneyUpdate.reason) {
      case 'START': return 'star'
      case 'NEW_RUN': return 'run'
      case 'BUY_TRAIN': return 'train'
      case 'CHALLENGE': return 'cards'
    }
  }, [moneyUpdate.reason])

  const title = useMemo(() => {
    switch (moneyUpdate.reason) {
      case 'START':
        return "Début de la partie"
      case 'NEW_RUN':
        return "Nouvelle tentative"
      case 'BUY_TRAIN':
        const train = trains.find((train) => train.id === moneyUpdate.tripId)
        if (!train) return "Train"
        const depDateTime = new Date(train.departureTime)
        const depTime = depDateTime.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' })
        const arrDateTime = new Date(train.arrivalTime)
        const arrTime = arrDateTime.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' })
        return `${train.from} ${depTime} => ${train.to} ${arrTime}`
      case 'CHALLENGE':
        const challengeAction = challengeActions.find((challengeAction) => challengeAction.id === moneyUpdate.actionId)
        if (!challengeAction) return "Défi"
        const challenge = challenges.find((challenge) => challenge.id === challengeAction.challengeId)
        if (!challenge) return "Défi"
        return challenge.title
    }
  }, [moneyUpdate.reason, moneyUpdate.tripId, moneyUpdate.actionId])

  const description = useMemo(() => {
    const earnDate = new Date(moneyUpdate.timestamp).toLocaleDateString(undefined, { day: '2-digit', month: '2-digit' })
    const earnTime = new Date(moneyUpdate.timestamp).toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' })
    const verb = moneyUpdate.amount >= 0 ? "Gagné" : "Dépensé"
    return <Text>
      {verb} {Math.abs(moneyUpdate.amount)} <FontAwesome6 name='coins' /> le {earnDate} à {earnTime}
    </Text>
  }, [moneyUpdate.amount])

  return (
    <List.Item
        left={(props) => <List.Icon {...props} icon={icon} />}
        title={title}
        description={description}
        onLongPress={onDelete} />
  )
}
