import { MaterialCommunityIcons } from "@expo/vector-icons";
import {
  ActivityIndicator,
  Image,
  Text,
  TouchableOpacity,
  View,
} from "react-native";

import { SERVICES } from "@/constants/services";
import { driverPhotoUri } from "@/lib/driver-photo";
import { useT } from "@/lib/i18n";
import type { RideOffer } from "@/types/type";

// The drivers who have volunteered for a request, and the rider's choice
// between them.
//
// Dispatch broadcasts the job and this is what comes back: several drivers,
// none of them assigned, each waiting to be picked. So every row has to carry
// what a person actually decides on — how far away they are, how they're
// rated, what they drive — and picking one has to be a single deliberate tap,
// because that tap is what commits the rider and releases everyone else.

// Rough road-speed assumption for turning a straight-line distance into
// minutes. A per-offer Directions call would be more accurate and would also
// mean one billed request per driver per poll; this is honest to within a
// couple of minutes in city traffic, which is the precision a rider comparing
// three drivers is actually using.
const URBAN_KMH = 22;
// Streets aren't straight. Multiplying the great-circle distance gets closer
// to the distance a car really drives.
const ROAD_FACTOR = 1.3;

const etaMinutes = (meters: number | null): number | null => {
  if (meters === null || !Number.isFinite(meters)) return null;
  return Math.max(
    1,
    Math.round(((meters * ROAD_FACTOR) / 1000 / URBAN_KMH) * 60),
  );
};

const distanceLabel = (meters: number | null): string | null => {
  if (meters === null || !Number.isFinite(meters)) return null;
  return meters < 1000
    ? `${Math.round(meters / 50) * 50} m`
    : `${(meters / 1000).toFixed(1)} km`;
};

type Props = {
  offers: RideOffer[];
  /** Offer currently being taken, so only that row shows a spinner. */
  pendingOfferId: number | null;
  busy: boolean;
  onPick: (offer: RideOffer) => void;
};

export const OfferList = ({ offers, pendingOfferId, busy, onPick }: Props) => {
  const t = useT();

  // What the rider is getting into. A driver who never filled in their car
  // model would otherwise leave the vehicle line blank on the one screen where
  // the rider is choosing between cars, so the service they drive for stands
  // in — "Car · 4 seats" is thin, but it isn't nothing.
  const vehicle = (offer: RideOffer): string => {
    const service = SERVICES.find((s) => s.id === offer.service);
    const label = offer.car_model ?? (service ? t(service.labelKey) : null);
    const seats = offer.car_seats
      ? t("bookRide.offers.seats", undefined, offer.car_seats)
      : null;

    return [label, seats].filter(Boolean).join(" · ");
  };

  return (
    <View className="mt-2">
      <View className="flex-row items-center justify-between mb-2">
        <Text className="text-base font-JakartaBold text-black dark:text-white">
          {t("bookRide.offers.title")}
        </Text>
        <Text className="text-xs text-general-200 dark:text-neutral-400">
          {t("bookRide.offers.count", undefined, offers.length)}
        </Text>
      </View>

      {offers.map((offer) => {
        const name = [offer.first_name, offer.last_name]
          .filter(Boolean)
          .join(" ");
        const distance = offer.pickup_distance_m ?? null;
        const eta = etaMinutes(distance);
        const taking = pendingOfferId === offer.offer_id;
        // The face the rider is choosing between. This is the screen the
        // driver's photo exists for, so it leads the row.
        const photo = driverPhotoUri(offer.profile_image_url);

        return (
          <View
            key={offer.offer_id}
            className="bg-white dark:bg-neutral-900 rounded-2xl p-3 mb-2 flex-row items-center"
          >
            {photo ? (
              <Image
                source={{ uri: photo }}
                className="w-12 h-12 rounded-full"
              />
            ) : (
              <View className="w-12 h-12 rounded-full bg-neutral-200 dark:bg-neutral-800 items-center justify-center">
                <MaterialCommunityIcons
                  name="account"
                  size={22}
                  color="#9ca3af"
                />
              </View>
            )}

            <View className="ml-3 flex-1">
              <Text
                className="font-JakartaSemiBold text-black dark:text-white"
                numberOfLines={1}
              >
                {name || t("bookRide.match.driverFallback")}
              </Text>

              <View className="flex-row items-center gap-x-2 mt-0.5">
                <View className="flex-row items-center gap-x-1">
                  <MaterialCommunityIcons
                    name="star"
                    size={13}
                    color="#f59e0b"
                  />
                  <Text className="text-xs text-general-200 dark:text-neutral-400">
                    {offer.rating != null
                      ? Number(offer.rating).toFixed(1)
                      : t("bookRide.ratingFallback")}
                  </Text>
                </View>
                {vehicle(offer) ? (
                  <Text
                    className="text-xs text-general-200 dark:text-neutral-400 flex-1"
                    numberOfLines={1}
                  >
                    {vehicle(offer)}
                  </Text>
                ) : null}
              </View>

              {eta !== null ? (
                <Text className="text-xs font-JakartaMedium text-primary-500 mt-0.5">
                  {t("bookRide.offers.away", {
                    eta,
                    distance: distanceLabel(distance) ?? "",
                  })}
                </Text>
              ) : null}
            </View>

            <TouchableOpacity
              onPress={() => onPick(offer)}
              disabled={busy}
              className={`rounded-full px-5 py-2.5 ml-2 ${
                busy && !taking ? "bg-emerald-500/40" : "bg-emerald-500"
              }`}
            >
              {taking ? (
                <ActivityIndicator size="small" color="#ffffff" />
              ) : (
                <Text className="text-white font-JakartaBold text-xs">
                  {t("bookRide.offers.pick")}
                </Text>
              )}
            </TouchableOpacity>
          </View>
        );
      })}
    </View>
  );
};
