import { useState } from 'react';
import { Alert, Linking, Text, View } from 'react-native';
import { Link, Stack, useLocalSearchParams } from 'expo-router';
import { useMutation, useQuery } from 'convex/react';

import type { Id } from '@spoon/backend/convex/_generated/dataModel.js';
import { api } from '@spoon/backend/convex/_generated/api.js';

import { ThreadMessageList } from '~/components/threads/thread-message-list';
import { ThreadStatusBadge } from '~/components/threads/thread-status-badge';
import { AppScreen } from '~/components/ui/app-screen';
import { Badge } from '~/components/ui/badge';
import { Button } from '~/components/ui/button';
import { Card } from '~/components/ui/card';
import { ConfirmButton } from '~/components/ui/confirm-button';
import { Field } from '~/components/ui/field';
import { formatDateTime, titleize } from '~/utils/format';

const ThreadDetailRoute = () => {
  const { threadId: rawThreadId } = useLocalSearchParams<{
    threadId: string;
  }>();
  const threadId = rawThreadId as Id<'threads'>;
  const details = useQuery(api.threads.get, { threadId });
  const messages = useQuery(api.threads.listMessages, { threadId }) ?? [];
  const appendMessage = useMutation(api.threads.appendUserMessage);
  const markResolved = useMutation(api.threads.markResolved);
  const cancel = useMutation(api.threads.cancel);
  const [message, setMessage] = useState('');
  const [pending, setPending] = useState<string | undefined>();
  const [refreshing, setRefreshing] = useState(false);

  const send = async () => {
    if (!message.trim()) return;
    setPending('send');
    try {
      await appendMessage({ threadId, content: message });
      setMessage('');
    } catch (error) {
      console.error(error);
      Alert.alert('Could not send message.');
    } finally {
      setPending(undefined);
    }
  };

  const softRefresh = () => {
    setRefreshing(true);
    setTimeout(() => setRefreshing(false), 600);
  };

  const resolveThread = async () => {
    setPending('resolve');
    try {
      await markResolved({ threadId });
    } catch (error) {
      console.error(error);
      Alert.alert('Could not resolve thread.');
    } finally {
      setPending(undefined);
    }
  };

  const cancelThread = async () => {
    setPending('cancel');
    try {
      await cancel({ threadId });
    } catch (error) {
      console.error(error);
      Alert.alert('Could not cancel thread.');
    } finally {
      setPending(undefined);
    }
  };

  if (!details) {
    return (
      <AppScreen>
        <Stack.Screen options={{ title: 'Thread' }} />
        <Text className='text-muted-foreground'>Loading thread...</Text>
      </AppScreen>
    );
  }

  const { thread, spoon, latestJob } = details;
  const pullRequestUrl = latestJob?.pullRequestUrl;
  const completed = ['resolved', 'ignored', 'failed', 'cancelled'].includes(
    thread.status,
  );

  return (
    <AppScreen onRefresh={softRefresh} refreshing={refreshing}>
      <Stack.Screen options={{ title: thread.title }} />
      <View className='gap-2'>
        <Text className='text-foreground text-3xl font-bold'>
          {thread.title}
        </Text>
        <View className='flex-row flex-wrap gap-2'>
          <ThreadStatusBadge status={thread.status} />
          <Badge label={titleize(thread.source)} />
          {thread.maintenanceOutcome ? (
            <Badge label={titleize(thread.maintenanceOutcome)} tone='primary' />
          ) : null}
        </View>
        <Text className='text-muted-foreground text-sm'>
          Updated {formatDateTime(thread.updatedAt)}
        </Text>
      </View>

      {spoon ? (
        <Card>
          <Text className='text-muted-foreground text-xs'>Spoon</Text>
          <Text className='text-foreground mt-1 font-semibold'>
            {spoon.name}
          </Text>
          <Link href={`/spoons/${spoon._id}`} asChild>
            <Button variant='outline'>Open Spoon</Button>
          </Link>
        </Card>
      ) : null}

      {latestJob ? (
        <Card className='gap-3'>
          <Text className='text-foreground font-semibold'>Latest job</Text>
          <Text className='text-muted-foreground text-sm'>
            {titleize(latestJob.status)} · {titleize(latestJob.workspaceStatus)}
          </Text>
          <Text className='text-muted-foreground text-sm'>
            Branch: {latestJob.workBranch}
          </Text>
          <Link href={`/workspace/${latestJob._id}`} asChild>
            <Button variant='outline'>Open workspace review</Button>
          </Link>
          {pullRequestUrl ? (
            <Button onPress={() => void Linking.openURL(pullRequestUrl)}>
              Open draft PR
            </Button>
          ) : null}
        </Card>
      ) : null}

      <ThreadMessageList messages={messages} />

      <Card className='gap-3'>
        <Text className='text-foreground font-semibold'>Reply</Text>
        <Field
          label='Message'
          multiline
          value={message}
          onChangeText={setMessage}
        />
        <Button
          disabled={completed || pending === 'send'}
          onPress={() => void send()}
        >
          {pending === 'send' ? 'Sending...' : 'Send message'}
        </Button>
      </Card>

      <View className='flex-row gap-3'>
        <Button
          disabled={completed || pending === 'resolve'}
          variant='outline'
          onPress={() => void resolveThread()}
        >
          {pending === 'resolve' ? 'Resolving...' : 'Resolve'}
        </Button>
        <ConfirmButton
          confirmLabel='Cancel thread'
          destructive
          disabled={completed || pending === 'cancel'}
          message='Cancel this thread?'
          title='Cancel thread'
          onConfirm={() => void cancelThread()}
        >
          {pending === 'cancel' ? 'Cancelling...' : 'Cancel'}
        </ConfirmButton>
      </View>
    </AppScreen>
  );
};

export default ThreadDetailRoute;
