import React, { Dispatch, SetStateAction, useState } from 'react';
import { View, Text, TouchableOpacity, Image, Linking } from 'react-native';
import { useNavigation } from '@react-navigation/native';
import moment from 'moment';

import { API_HOST } from 'src/constants';
import { Colors } from 'src/theme';
import { NAVIGATION_PAGES } from 'src/types';
import { styles } from './styles';
import { FixersData } from '../../utils/types';
import { Star } from '../Star';

interface FixerItemProps {
  item: FixersData;
  setSelectedFixer: Dispatch<SetStateAction<FixersData | null>>;
  country: { id: number; country: string; flag: string };
  setIsWarningModalVisible: Dispatch<SetStateAction<boolean>>;
}

const FixerItem = ({
  item,
  setSelectedFixer,
  country,
  setIsWarningModalVisible
}: FixerItemProps) => {
  const navigation = useNavigation();

  const formatDate = (month: number) => {
    const formatedMonth = moment(month, 'MM').format('MMMM');
    return `${item.year} ${formatedMonth}`;
  };

  const renderRatingStars = (ratings: { rate: string; name: string; comment: string }[]) => {
    const total = ratings.reduce((sum, rating) => sum + parseFloat(rating.rate), 0);
    const rating = (total / ratings.length).toFixed(4);
    const stars = [];

    for (let i = 0; i < 5; i++) {
      const filled = Math.min(Math.max(+rating - i, 0), 1);
      stars.push(<Star key={i} filled={filled} />);
    }
    return (
      <TouchableOpacity
        style={styles.ratingContainer}
        onPress={() =>
          navigation.navigate(
            ...([
              NAVIGATION_PAGES.FIXERS_COMMENTS,
              { comments: item.ratings, name: item.name }
            ] as never)
          )
        }
      >
        {stars}
        <Text style={styles.labelText}>({item.ratings.length})</Text>
      </TouchableOpacity>
    );
  };

  const parseTextWithLinks = (text?: string): React.ReactNode => {
    if (!text) return null;

    const urlRegex = /((https?:\/\/[^\s]+)|(?<!\w)(www\.[^\s]+))/g;

    const result: React.ReactNode[] = [];
    let lastIndex = 0;

    const matches = Array.from(text.matchAll(urlRegex));

    matches.forEach((match, index) => {
      const matchText = match[0];
      const matchIndex = match.index ?? 0;

      if (matchIndex > lastIndex) {
        const betweenText = text.slice(lastIndex, matchIndex);
        result.push(...processNonUrlText(betweenText, `before-${index}`));
      }

      let url = matchText.startsWith('http') ? matchText : `https://${matchText}`;
      result.push(
        <Text
          key={`link-${index}`}
          style={styles.linkText}
          onPress={async () => {
            const supported = await Linking.canOpenURL(url);
            if (supported) {
              Linking.openURL(url);
            }
          }}
          selectable
        >
          {matchText}
        </Text>
      );

      lastIndex = matchIndex + matchText.length;
    });

    if (lastIndex < text.length) {
      const remainingText = text.slice(lastIndex);
      result.push(...processNonUrlText(remainingText, 'text-end'));
    }

    return <Text>{result}</Text>;
  };

  const processNonUrlText = (text: string, keyPrefix: string): React.ReactNode[] => {
    const parts = text.split(/(\s+|,|;|\/)/);
    return parts.map((part, i) => {
      const trimmed = part.trim();
      const isSeparator = /^(\s+|,|;|\/)$/.test(part);
      const shouldBeLink = !isSeparator && trimmed.length > 3;

      if (shouldBeLink) {
        const url = trimmed.startsWith('http') ? trimmed : `https://${trimmed}`;
        return (
          <Text
            key={`${keyPrefix}-link-${i}`}
            style={styles.linkText}
            onPress={async () => {
              const supported = await Linking.canOpenURL(url);
              if (supported) {
                Linking.openURL(url);
              }
            }}
            selectable
          >
            {part}
          </Text>
        );
      }

      return (
        <Text key={`${keyPrefix}-text-${i}`} selectable>
          {part}
        </Text>
      );
    });
  };

  return (
    <View style={styles.fixerItemContainer}>
      <View style={styles.fixerHeaderContainer}>
        <View style={styles.fixerCountryContainer}>
          <Image source={{ uri: API_HOST + country.flag }} style={styles.flagIcon} />
          <Text style={styles.fixerCountryText}>{country.country}</Text>
        </View>
      </View>

      <View style={styles.divider} />

      <View style={styles.detailContainer}>
        {item.name && (
          <View style={styles.rowContent}>
            <Text style={styles.labelText}>Name:</Text>
            <Text style={styles.valueText}>{item.name}</Text>
          </View>
        )}

        <View style={styles.rowContent}>
          <Text style={styles.labelText}>Date:</Text>
          <Text style={[styles.valueText, { color: Colors.DARK_BLUE }]}>
            {formatDate(item.month)}
          </Text>
        </View>

        {item.email && (
          <View style={styles.rowContent}>
            <Text style={styles.labelText}>Email:</Text>
            <Text
              style={styles.valueText}
              onPress={() => Linking.openURL(`mailto:${item.email}`)}
              selectable
            >
              {item.email}
            </Text>
          </View>
        )}

        {item.phone && (
          <View style={styles.rowContent}>
            <Text style={styles.labelText}>Phone:</Text>
            <Text
              style={styles.valueText}
              onPress={() => {
                Linking.openURL(`tel:${item.phone}`);
              }}
              selectable
            >
              {item.phone}
            </Text>
          </View>
        )}

        {item.web && (
          <View style={styles.rowContent}>
            <Text style={styles.labelText}>Website:</Text>
            <View style={{ flex: 4 }}>{parseTextWithLinks(item.web)}</View>
          </View>
        )}

        {item.comment && <CommentText text={item.comment} />}

        {item.ratings.length ? (
          <View style={styles.rowContent}>
            <Text style={styles.labelText}>Rating:</Text>
            {renderRatingStars(item.ratings)}
          </View>
        ) : null}

        <View style={styles.rowContent}>
          <Text style={styles.labelText}>Added by:</Text>
          <TouchableOpacity
            onPress={() =>
              navigation.navigate(
                ...([NAVIGATION_PAGES.PUBLIC_PROFILE_VIEW, { userId: item.added_by_uid }] as never)
              )
            }
            disabled={item.added_by_uid === 0}
            style={{ flex: 4 }}
          >
            <Text style={[styles.valueText, { color: Colors.DARK_BLUE, flex: 0 }]}>
              {item.added_by_name}
            </Text>
          </TouchableOpacity>
        </View>
      </View>

      <View style={styles.divider} />

      <View style={{ justifyContent: 'flex-end', flexDirection: 'row', gap: 12 }}>
        <TouchableOpacity
          style={styles.rateButton}
          onPress={() => {
            if (item.can_rate) {
              setSelectedFixer(item);
            } else {
              setIsWarningModalVisible(true);
            }
          }}
        >
          <Text style={styles.rateButtonText}>Rate</Text>
        </TouchableOpacity>

        {item.can_edit ? (
          <TouchableOpacity
            style={styles.rateButton}
            onPress={() => {
              navigation.navigate(
                ...([NAVIGATION_PAGES.ADD_FIXER, { fixer: item, un_id: country.id }] as never)
              );
            }}
          >
            <Text style={styles.rateButtonText}>Edit</Text>
          </TouchableOpacity>
        ) : null}
      </View>
    </View>
  );
};

const CommentText = ({ text }: { text: string }) => {
  const [showFullComment, setShowFullComment] = useState(false);
  const [textMoreThanThreeLines, setTextMoreThanThreeLines] = useState(false);

  return (
    <View style={{ gap: 6 }}>
      <Text style={styles.labelText}>Comment:</Text>
      <View>
        <Text
          style={[styles.valueText, { color: Colors.DARK_BLUE }]}
          numberOfLines={textMoreThanThreeLines && !showFullComment ? 3 : undefined}
          onTextLayout={(e) => {
            if (!textMoreThanThreeLines) {
              const { lines } = e.nativeEvent;
              if (lines.length > 3) {
                setTextMoreThanThreeLines(true);
              }
            }
          }}
        >
          {text}
        </Text>

        {textMoreThanThreeLines && (
          <TouchableOpacity onPress={() => setShowFullComment(!showFullComment)}>
            <Text style={styles.linkText}>{showFullComment ? 'Show less' : 'Show more'}</Text>
          </TouchableOpacity>
        )}
      </View>
    </View>
  );
};

export default FixerItem;
