(() => {
  const qs = (selector) => document.querySelector(selector);
  const qsa = (selector) => Array.from(document.querySelectorAll(selector));

  const state = {
    user: null,
    map: null,
    geocoder: null,
    directionsService: null,
    directionsRenderer: null,
    markers: [],
    driverMarker: null,
    origin: null,
    destination: null,
    stops: [],
    route: null,
    tariffs: null,
    selectedCategory: 'economica',
    selectedPayment: 'dinheiro_pix',
    activeRideId: null,
    pollTimer: null,
    rating: 0,
    chatOpen: false,
    chatTimer: null,
  };

  const categoryLabels = {
    economica: 'Economico',
    plus: 'Plus',
    pro: 'Pro',
  };

  const categoryIcons = {
    economica: '🚗',
    plus: '🚘',
    pro: '✪',
  };

  const paymentOptions = [
    { id: 'dinheiro_pix', label: 'Dinheiro/Pix', hint: 'Pague direto ao motorista', icon: '💵' },
    { id: 'pix_online', label: 'Pix Online', hint: 'Pago pelo app', icon: '▦' },
    { id: 'cartao_credito', label: 'Cartão de crédito', hint: 'Pago pelo app', icon: '▰' },
  ];

  function money(value) {
    return Number(value || 0).toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' });
  }

  function api(path, options = {}) {
    return fetch(path, {
      headers: { 'Content-Type': 'application/json', ...(options.headers || {}) },
      ...options,
    }).then(async (response) => {
      const data = await response.json().catch(() => ({}));
      if (!response.ok || data.success === false) {
        throw new Error(data.message || 'Não foi possível concluir a operação.');
      }
      return data;
    });
  }

  function toast(message, isError = false) {
    const el = qs('[data-toast]');
    if (!el) return;
    el.textContent = message;
    el.classList.toggle('error', isError);
    el.classList.add('show');
    clearTimeout(el._timer);
    el._timer = setTimeout(() => el.classList.remove('show'), 3800);
  }

  function setText(selector, value) {
    const el = qs(selector);
    if (el) el.textContent = value;
  }

  function setRideActive(active) {
    document.body.classList.toggle('ride-active', active);
  }

  function mediaUrl(value) {
    const raw = String(value || '').trim();
    if (!raw) return '';
    if (/^(https?:|data:|blob:)/i.test(raw)) return raw;
    if (raw.startsWith('/') || raw.startsWith('../') || raw.startsWith('./')) return raw;
    return `../${raw.replace(/^\/+/, '')}`;
  }

  function parseUser() {
    try {
      return JSON.parse(sessionStorage.getItem('bulo_user') || 'null');
    } catch (_) {
      return null;
    }
  }

  function firstName(user) {
    return (user?.primeiro_nome || user?.nome || 'passageiro').toString().trim().split(/\s+/)[0];
  }

  function updateUserShell(profile) {
    const user = profile || state.user || {};
    const name = firstName(user);
    setText('[data-user-name]', name);
    setText('[data-user-email]', user.email || 'Conta Bulo');
    setText('[data-greeting]', `Ola, ${name}`);

    const initial = name.charAt(0).toUpperCase() || 'P';
    const avatarUrl = mediaUrl(user.foto_url || user.foto || '');
    const avatarEls = [qs('[data-avatar]'), qs('[data-mobile-avatar]')].filter(Boolean);
    avatarEls.forEach((el) => {
      if (avatarUrl) {
        el.innerHTML = `<img src="${avatarUrl}" alt="">`;
      } else {
        el.textContent = initial;
      }
    });

    setText('[data-wallet]', money(user.saldo_carteira));
    setText('[data-rides]', String(user.total_corridas ?? '--'));
    setText('[data-profile-rating]', Number(user.nota_media || 5).toFixed(2));
  }

  function escapeHtml(value) {
    return String(value ?? '').replace(/[&<>"']/g, (char) => ({
      '&': '&amp;',
      '<': '&lt;',
      '>': '&gt;',
      '"': '&quot;',
      "'": '&#039;',
    }[char]));
  }

  async function loadProfile() {
    try {
      const data = await api(`../auth/passageiro_resumo.php?id_usuario=${encodeURIComponent(state.user.id)}`);
      if (data.passageiro) {
        state.user = { ...state.user, ...data.passageiro };
        sessionStorage.setItem('bulo_user', JSON.stringify(state.user));
        updateUserShell(state.user);
      }
    } catch (_) {
      updateUserShell(state.user);
    }
  }

  function ensureLogged() {
    state.user = parseUser();
    if (!state.user || !state.user.id) {
      window.location.href = './';
      return false;
    }
    updateUserShell(state.user);
    return true;
  }

  function latLngFrom(value) {
    if (!value) return null;
    if (value.lat && value.lng && typeof value.lat === 'function') return value;
    const lat = Number(value.lat ?? value.latitude);
    const lng = Number(value.lng ?? value.longitude);
    if (!Number.isFinite(lat) || !Number.isFinite(lng)) return null;
    return new google.maps.LatLng(lat, lng);
  }

  function clearMarkers() {
    state.markers.forEach((marker) => marker.setMap(null));
    state.markers = [];
  }

  function addMarker(position, label, color) {
    const marker = new google.maps.Marker({
      map: state.map,
      position,
      label: { text: label, color: '#fff', fontWeight: '800' },
      icon: {
        path: google.maps.SymbolPath.CIRCLE,
        fillColor: color,
        fillOpacity: 1,
        strokeColor: '#fff',
        strokeWeight: 3,
        scale: 10,
      },
    });
    state.markers.push(marker);
    return marker;
  }

  function setDriverMarker(position) {
    if (!position) return;
    if (!state.driverMarker) {
      state.driverMarker = new google.maps.Marker({
        map: state.map,
        icon: {
          path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW,
          fillColor: '#111827',
          fillOpacity: 1,
          strokeColor: '#fff',
          strokeWeight: 2,
          scale: 6,
        },
      });
    }
    state.driverMarker.setPosition(position);
    state.driverMarker.setMap(state.map);
  }

  function updateRouteMarkers() {
    clearMarkers();
    if (state.origin) addMarker(state.origin, 'O', '#18b86b');
    state.stops.forEach((stop, index) => {
      if (stop.location) addMarker(stop.location, String(index + 1), '#f59e0b');
    });
    if (state.destination) addMarker(state.destination, 'D', '#ef4444');
  }

  function bindAutocomplete(input, callback) {
    const autocomplete = new google.maps.places.Autocomplete(input, {
      componentRestrictions: { country: 'br' },
      fields: ['formatted_address', 'geometry', 'name'],
    });
    autocomplete.addListener('place_changed', () => {
      const place = autocomplete.getPlace();
      if (!place.geometry || !place.geometry.location) {
        toast('Selecione um endereço da lista de sugestões.', true);
        return;
      }
      const label = place.formatted_address || place.name || input.value;
      input.value = label;
      callback(place.geometry.location, label);
    });
    return autocomplete;
  }

  function reverseGeocode(position) {
    return new Promise((resolve) => {
      state.geocoder.geocode({ location: position }, (results, status) => {
        if (status === 'OK' && results && results[0]) {
          resolve(results[0].formatted_address);
        } else {
          resolve('Localização atual');
        }
      });
    });
  }

  async function setCurrentLocation() {
    const fallback = new google.maps.LatLng(-29.6842, -53.8069);
    const permissionBox = qs('[data-location-permission]');
    const apply = async (position) => {
      state.origin = position;
      state.map.setCenter(position);
      state.map.setZoom(15);
      qs('#originInput').value = await reverseGeocode(position);
      permissionBox?.classList.add('hidden');
      updateRouteMarkers();
      maybeBuildRoute();
    };

    if (!navigator.geolocation) {
      toast('Seu navegador não oferece localização automática. Informe o embarque manualmente.', true);
      await apply(fallback);
      return;
    }

    toast('Permita a localização para encontrarmos seu embarque.');
    navigator.geolocation.getCurrentPosition(
      async (pos) => {
        await apply(new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude));
      },
      async () => {
        state.origin = fallback;
        state.map.setCenter(fallback);
        state.map.setZoom(13);
        qs('#originInput').value = '';
        permissionBox?.classList.remove('hidden');
        toast('Não foi possível acessar sua localização. Você pode permitir ou preencher o embarque manualmente.', true);
        updateRouteMarkers();
      },
      { enableHighAccuracy: true, timeout: 8000, maximumAge: 30000 },
    );
  }

  function initMap() {
    state.geocoder = new google.maps.Geocoder();
    state.directionsService = new google.maps.DirectionsService();
    state.directionsRenderer = new google.maps.DirectionsRenderer({
      suppressMarkers: true,
      preserveViewport: false,
      polylineOptions: { strokeColor: '#0d6efd', strokeWeight: 5, strokeOpacity: 0.95 },
    });
    state.map = new google.maps.Map(qs('#map'), {
      center: { lat: -29.6842, lng: -53.8069 },
      zoom: 14,
      disableDefaultUI: true,
      zoomControl: false,
      streetViewControl: false,
      mapTypeControl: false,
      fullscreenControl: false,
    });
    state.directionsRenderer.setMap(state.map);
  }

  function addStopField() {
    if (state.stops.length >= 3) {
      toast('Você pode adicionar até 3 paradas.', true);
      return;
    }
    const index = state.stops.length;
    state.stops.push({ location: null, address: '' });
    const list = qs('[data-stops]');
    const row = document.createElement('label');
    row.className = 'address-field stop-field';
    row.innerHTML = `
      <span>Parada ${index + 1}</span>
      <input autocomplete="off" placeholder="Digite a parada">
      <button class="remove-stop" type="button" aria-label="Remover parada">×</button>
    `;
    const input = row.querySelector('input');
    row.querySelector('button').addEventListener('click', () => {
      state.stops.splice(index, 1);
      renderStops();
      maybeBuildRoute();
    });
    list.appendChild(row);
    bindAutocomplete(input, (location, address) => {
      state.stops[index] = { location, address };
      maybeBuildRoute();
    });
    input.focus();
  }

  function renderStops() {
    const old = [...state.stops];
    state.stops = [];
    qs('[data-stops]').innerHTML = '';
    old.forEach((stop) => {
      addStopField();
      const idx = state.stops.length - 1;
      state.stops[idx] = stop;
      const input = qsa('[data-stops] input')[idx];
      if (input) input.value = stop.address || '';
    });
  }

  function setRouteInfo(distanceKm, durationMin) {
    setText('[data-route-distance]', `${distanceKm.toLocaleString('pt-BR', { maximumFractionDigits: 2 })} km`);
    setText('[data-route-duration]', `${Math.round(durationMin)} min`);
    qs('[data-route-summary]')?.classList.remove('hidden');
  }

  async function loadTariffs() {
    const origin = state.origin;
    const lat = origin ? origin.lat() : '';
    const lng = origin ? origin.lng() : '';
    const data = await api(`../configuracoes/app.php?lat=${encodeURIComponent(lat)}&lng=${encodeURIComponent(lng)}`);
    state.tariffs = data;
    const region = data.regiao?.nome || 'Fora da área atendida';
    setText('[data-route-region]', data.disponivel ? `Tarifa: ${region}` : data.mensagem_indisponivel);
    return data;
  }

  function calculateFare(config, distanceKm, durationMin, stopsCount) {
    const base = Number(config.preco_base || 0);
    const byKm = Number(config.preco_por_km || 0);
    const byMin = Number(config.preco_por_minuto || 0);
    const fee = Number(config.taxa_servico || 0);
    const min = Number(config.valor_minimo || base);
    return Math.round((Math.max(min, base + distanceKm * byKm + durationMin * byMin + fee) + stopsCount) * 100) / 100;
  }

  function renderCategories() {
    const box = qs('[data-categories]');
    if (!box || !state.route || !state.tariffs) return;
    const categories = state.tariffs.categorias || {};
    const tariffs = state.tariffs.tarifas || { economica: state.tariffs.configuracoes || {} };
    box.innerHTML = '';
    ['economica', 'plus', 'pro'].forEach((id) => {
      const enabled = state.tariffs.disponivel !== false && categories[id] !== false;
      const fare = calculateFare(tariffs[id] || tariffs.economica || {}, state.route.distanceKm, state.route.durationMin, state.stops.length);
      const card = document.createElement('button');
      card.type = 'button';
      card.className = `option-card ${state.selectedCategory === id ? 'selected' : ''}`;
      card.disabled = !enabled;
      card.dataset.category = id;
      card.innerHTML = `<span>${categoryIcons[id]}</span><strong>${categoryLabels[id]}</strong><em>${enabled ? money(fare) : 'Indisponivel'}</em>`;
      card.addEventListener('click', () => {
        state.selectedCategory = id;
        renderCategories();
        updateConfirmButton();
      });
      box.appendChild(card);
    });
  }

  function renderPayments() {
    const box = qs('[data-payments]');
    if (!box) return;
    box.innerHTML = '';
    paymentOptions.forEach((payment) => {
      const card = document.createElement('button');
      card.type = 'button';
      card.className = `option-card ${state.selectedPayment === payment.id ? 'selected' : ''}`;
      card.innerHTML = `<span>${payment.icon}</span><strong>${payment.label}</strong><small>${payment.hint}</small>`;
      card.addEventListener('click', () => {
        state.selectedPayment = payment.id;
        renderPayments();
      });
      box.appendChild(card);
    });
  }

  function selectedFare() {
    const tariff = state.tariffs?.tarifas?.[state.selectedCategory] || state.tariffs?.configuracoes || {};
    return calculateFare(tariff, state.route?.distanceKm || 0, state.route?.durationMin || 0, state.stops.length);
  }

  function updateConfirmButton() {
    const button = qs('[data-request-ride]');
    if (!button || !state.route) return;
    button.textContent = `Confirmar ${categoryLabels[state.selectedCategory]} - ${money(selectedFare())}`;
  }

  function setRating(value) {
    state.rating = Number(value || 0);
    qsa('[data-rating-stars] button').forEach((button) => {
      const rating = Number(button.dataset.rating || 0);
      button.classList.toggle('selected', rating <= state.rating);
    });
    qs('[data-rating-good]')?.classList.toggle('hidden', state.rating !== 5);
    qs('[data-rating-bad]')?.classList.toggle('hidden', state.rating <= 0 || state.rating === 5);
  }

  async function maybeBuildRoute() {
    if (!state.origin || !state.destination) {
      updateRouteMarkers();
      return;
    }

    const waypoints = state.stops
      .filter((stop) => stop.location)
      .map((stop) => ({ location: stop.location, stopover: true }));

    state.directionsService.route(
      {
        origin: state.origin,
        destination: state.destination,
        waypoints,
        travelMode: google.maps.TravelMode.DRIVING,
        optimizeWaypoints: false,
      },
      async (result, status) => {
        if (status !== 'OK' || !result) {
          toast('Não foi possível calcular a rota.', true);
          return;
        }
        state.directionsRenderer.setDirections(result);
        updateRouteMarkers();
        const legs = result.routes[0].legs || [];
        const distanceM = legs.reduce((sum, leg) => sum + (leg.distance?.value || 0), 0);
        const durationS = legs.reduce((sum, leg) => sum + (leg.duration?.value || 0), 0);
        state.route = {
          distanceKm: Math.round((distanceM / 1000) * 100) / 100,
          durationMin: Math.max(1, Math.round(durationS / 60)),
        };
        setRouteInfo(state.route.distanceKm, state.route.durationMin);
        try {
          await loadTariffs();
          qs('[data-quote-box]')?.classList.remove('hidden');
          renderCategories();
          renderPayments();
          updateConfirmButton();
        } catch (error) {
          toast(error.message, true);
        }
      },
    );
  }

  function setDestination(location, address) {
    state.destination = location;
    qs('#destinationInput').value = address || '';
    maybeBuildRoute();
  }

  function renderAddressRows(selector, items, emptyText, clickHandler) {
    const box = qs(selector);
    if (!box) return;
    box.innerHTML = '';
    if (!items.length) {
      const empty = document.createElement('div');
      empty.className = 'quick-empty';
      empty.textContent = emptyText;
      box.appendChild(empty);
      return;
    }
    items.slice(0, 5).forEach((item) => {
      const button = document.createElement('button');
      button.type = 'button';
      button.className = 'quick-address';
      button.innerHTML = `<strong>${item.rotulo || item.tipo || 'Endereço'}</strong><span>${item.endereco || ''}</span>`;
      button.addEventListener('click', () => clickHandler(item));
      box.appendChild(button);
    });
  }

  async function loadAddresses() {
    try {
      const [saved, recent] = await Promise.all([
        api(`../auth/enderecos_passageiro.php?id_usuario=${state.user.id}`),
        api(`../auth/enderecos_recentes_passageiro.php?id_usuario=${state.user.id}`),
      ]);
      const savedItems = saved.enderecos || [];
      const recentItems = recent.enderecos || [];
      setText('[data-saved-count]', `${savedItems.length}/5`);
      setText('[data-recent-count]', `${recentItems.length}/5`);
      renderAddressRows('[data-saved-addresses]', savedItems, 'Salve endereços no painel da conta.', (item) => {
        const pos = latLngFrom(item);
        if (pos) setDestination(pos, item.endereco);
        else qs('#destinationInput').value = item.endereco || '';
      });
      renderAddressRows('[data-recent-addresses]', recentItems, 'Seus últimos destinos aparecem aqui.', (item) => {
        const pos = latLngFrom(item);
        if (pos) setDestination(pos, item.endereco);
        else qs('#destinationInput').value = item.endereco || '';
      });
    } catch (_) {
      renderAddressRows('[data-saved-addresses]', [], 'Não foi possível carregar endereços.', () => {});
      renderAddressRows('[data-recent-addresses]', [], 'Não foi possível carregar recentes.', () => {});
    }
  }

  async function saveRecent(kind, address, point) {
    if (!address || !point) return;
    try {
      await api('../auth/enderecos_recentes_passageiro.php', {
        method: 'POST',
        body: JSON.stringify({
          id_usuario: state.user.id,
          tipo: kind,
          endereco: address,
          latitude: point.lat(),
          longitude: point.lng(),
        }),
      });
    } catch (_) {
      // Recentes são conveniência. Não bloqueia a corrida.
    }
  }

  async function requestRide() {
    if (!state.origin || !state.destination || !state.route) {
      toast('Informe origem e destino para continuar.', true);
      return;
    }
    if (state.tariffs?.disponivel === false) {
      toast(state.tariffs.mensagem_indisponivel || 'Ainda não atendemos essa região.', true);
      return;
    }
    const button = qs('[data-request-ride]');
    button.disabled = true;
    button.textContent = 'Chamando...';
    try {
      const originAddress = qs('#originInput').value;
      const destinationAddress = qs('#destinationInput').value;
      const payload = {
        id_passageiro: state.user.id,
        origem_lat: state.origin.lat(),
        origem_lng: state.origin.lng(),
        destino_lat: state.destination.lat(),
        destino_lng: state.destination.lng(),
        origem_endereco: originAddress,
        destino_endereco: destinationAddress,
        distancia: state.route.distanceKm,
        tempo_estimado: `${state.route.durationMin} min`,
        duracao_minutos: state.route.durationMin,
        valor: selectedFare(),
        categoria_veiculo: state.selectedCategory,
        forma_pagamento: state.selectedPayment === 'dinheiro_pix' ? 'dinheiro' : state.selectedPayment === 'pix_online' ? 'pix' : 'cartao',
        forma_pagamento_detalhe: state.selectedPayment,
        paradas: state.stops
          .filter((stop) => stop.location)
          .map((stop, index) => ({
            ordem: index + 1,
            lat: stop.location.lat(),
            lng: stop.location.lng(),
            endereco: stop.address,
          })),
      };
      const data = await api('../corridas/criar_corrida.php', {
        method: 'POST',
        body: JSON.stringify(payload),
      });
      state.activeRideId = data.id_corrida;
      await saveRecent('origem', originAddress, state.origin);
      await saveRecent('destino', destinationAddress, state.destination);
      await loadAddresses();
      qs('[data-quote-box]')?.classList.add('hidden');
      qs('[data-active-ride]')?.classList.remove('hidden');
      qs('[data-search-state]')?.classList.add('compact');
      setRideActive(true);
      toast('Corrida solicitada. Estamos buscando um motorista.');
      pollRide(true);
    } catch (error) {
      toast(error.message, true);
    } finally {
      button.disabled = false;
      updateConfirmButton();
    }
  }

  function paymentLabel(value) {
    if (value === 'cartao' || value === 'cartao_credito') return 'Cartão de crédito';
    if (value === 'pix' || value === 'pix_online') return 'Pix Online';
    return 'Dinheiro/Pix';
  }

  function rideStatusTitle(status) {
    if (status === 'aceita' || status === 'motorista_a_caminho') return 'Motorista a caminho';
    if (status === 'aguardando_embarque') return 'Motorista aguardando embarque';
    if (status === 'em_andamento') return 'Viagem em andamento';
    if (status === 'finalizada') return 'Corrida finalizada';
    if (status === 'cancelada') return 'Corrida cancelada';
    return 'Buscando motorista';
  }

  function updateActiveRide(corrida) {
    const status = corrida.status || 'pendente';
    const finalized = status === 'finalizada';
    const canceled = status === 'cancelada';
    const alreadyRated = corrida.avaliacao_motorista !== null
      && corrida.avaliacao_motorista !== undefined
      && String(corrida.avaliacao_motorista).trim() !== '';
    setText('[data-active-title]', rideStatusTitle(status));
    setText('[data-active-subtitle]', status === 'pendente'
      ? 'Estamos conectando você com um motorista disponível.'
      : `${paymentLabel(corrida.forma_pagamento_detalhe || corrida.forma_pagamento)} · ${money(corrida.valor)}`);
    setText('[data-active-message]', status === 'pendente'
      ? 'A busca esta em andamento.'
      : finalized
        ? 'Corrida finalizada. Avalie o motorista para concluir.'
        : `Ao final da corrida pague ao motorista o valor: ${money(corrida.valor)}`);

    const hasDriver = Boolean(corrida.motorista_id || corrida.id_motorista);
    qs('[data-driver-card]')?.classList.toggle('hidden', !hasDriver);
    qs('[data-ride-code-box]')?.classList.toggle('hidden', !hasDriver);
    if (hasDriver) {
      const driverCard = qs('[data-driver-card]');
      if (driverCard) {
        driverCard.dataset.driverId = corrida.motorista_id || corrida.id_motorista || '';
      }
      setText('[data-driver-name]', (corrida.motorista_nome || 'Motorista').split(' ')[0]);
      setText('[data-driver-rating]', `★ ${Number(corrida.motorista_nota_media || 5).toFixed(2)}`);
      const vehicle = [corrida.veiculo_modelo, corrida.veiculo_cor, corrida.veiculo_placa].filter(Boolean).join(' · ');
      setText('[data-driver-vehicle]', vehicle || 'Veículo');
      setText('[data-ride-code]', corrida.codigo_embarque || '----');
      const photo = qs('[data-driver-photo]');
      if (photo) {
        photo.src = mediaUrl(corrida.motorista_foto_url || corrida.motorista_foto || '') || '../assets/site/img/favicon.png';
      }
    }

    const driverPos = latLngFrom({ lat: corrida.motorista_lat, lng: corrida.motorista_lng });
    if (driverPos) setDriverMarker(driverPos);

    qs('[data-cancel-ride]')?.classList.toggle('hidden', finalized || canceled);
    qs('[data-ride-code-box]')?.classList.toggle('hidden', !hasDriver || finalized || canceled);
    qs('[data-rating-box]')?.classList.toggle('hidden', !finalized || alreadyRated);
    qs('[data-open-chat]')?.classList.toggle('hidden', !hasDriver || finalized || canceled || status === 'pendente');

    if (hasDriver && !finalized && !canceled && status !== 'pendente' && !state.chatOpen) {
      refreshChatBadge();
    }

    if (finalized && alreadyRated) {
      qs('[data-active-ride]')?.classList.add('hidden');
      setRideActive(false);
    }

    if (canceled) {
      resetCanceledRideUi();
      return;
    }

    if (finalized) {
      clearInterval(state.pollTimer);
      state.pollTimer = null;
      closeChat();
    }
  }

  async function openDriverProfile() {
    const idMotorista = Number(qs('[data-driver-card]')?.dataset.driverId || 0);
    if (!idMotorista) {
      toast('Perfil do motorista indisponível no momento.', true);
      return;
    }
    try {
      const data = await api(`../auth/perfil_motorista.php?id_motorista=${idMotorista}`);
      const perfil = data.perfil || {};
      const foto = mediaUrl(perfil.foto_url) || '../assets/site/img/favicon.png';
      const elogios = perfil.elogios || {};
      const comentarios = Array.isArray(perfil.comentarios) ? perfil.comentarios : [];
      const modal = qs('[data-driver-profile-modal]');
      if (!modal) return;
      modal.querySelector('[data-driver-profile-body]').innerHTML = `
        <div class="driver-profile-head">
          <img src="${escapeHtml(foto)}" alt="">
          <div>
            <strong>${escapeHtml((perfil.nome || 'Motorista').split(' ')[0])}</strong>
            <span>${escapeHtml([perfil.cidade, perfil.uf].filter(Boolean).join(' - ') || 'Cidade não informada')}</span>
          </div>
        </div>
        <div class="driver-profile-stats">
          <div><span>Nota</span><strong>${Number(perfil.nota_media || 0).toFixed(2)}</strong></div>
          <div><span>Viagens</span><strong>${Number(perfil.total_viagens || 0)}</strong></div>
          <div><span>Cadastro</span><strong>${escapeHtml(perfil.tempo_cadastro_texto || 'Recente')}</strong></div>
        </div>
        <div class="driver-profile-section">
          <strong>Elogios</strong>
          <div class="driver-profile-badges">
            <span>Bom condutor ${Number(elogios.bom_condutor || 0)}</span>
            <span>Simpático ${Number(elogios.simpatico || 0)}</span>
            <span>Veículo limpo ${Number(elogios.veiculo_limpo || 0)}</span>
            <span>Boa rota ${Number(elogios.boa_rota || 0)}</span>
            <span>Boa conversa ${Number(elogios.boa_conversa || 0)}</span>
          </div>
        </div>
        <div class="driver-profile-section">
          <strong>Comentários</strong>
          <div class="driver-profile-comments">
            ${comentarios.slice(0, 5).map((item) => `<p><b>★★★★★</b> ${escapeHtml(item.comentario || '')}</p>`).join('') || '<p>Nenhum comentário 5 estrelas ainda.</p>'}
          </div>
        </div>
      `;
      modal.classList.remove('hidden');
    } catch (error) {
      toast(error.message || 'Não foi possível carregar o perfil do motorista.', true);
    }
  }

  async function loadChat(markRead = false) {
    if (!state.activeRideId) return null;
    const params = new URLSearchParams({
      id_corrida: state.activeRideId,
      id_usuario: state.user.id,
      tipo_usuario: 'passageiro',
      marcar_lidas: markRead ? '1' : '0',
    });
    const data = await api(`../corridas/chat_corrida.php?${params.toString()}`);
    return data;
  }

  function renderChat(messages) {
    const list = qs('[data-chat-list]');
    if (!list) return;
    if (!messages || messages.length === 0) {
      list.innerHTML = '<div class="empty-chat">Nenhuma mensagem ainda.</div>';
      return;
    }
    list.innerHTML = messages.map((msg) => {
      const mine = msg.remetente_tipo === 'passageiro';
      const name = mine ? 'Você' : (msg.nome_remetente || 'Motorista');
      return `
        <div class="chat-message ${mine ? 'mine' : ''}">
          <strong>${escapeHtml(name)}</strong>
          <span>${escapeHtml(msg.mensagem || '')}</span>
        </div>
      `;
    }).join('');
    list.scrollTop = list.scrollHeight;
  }

  async function refreshChat(markRead = false) {
    try {
      const data = await loadChat(markRead);
      renderChat(data?.mensagens || []);
      const unread = Number(data?.nao_lidas || 0);
      const badge = qs('[data-chat-badge]');
      if (badge) {
        badge.textContent = unread > 9 ? '9+' : String(unread);
        badge.classList.toggle('hidden', unread <= 0);
      }
    } catch (error) {
      if (state.chatOpen) {
        renderChat([]);
        toast(error.message, true);
      }
    }
  }

  async function refreshChatBadge() {
    try {
      const data = await loadChat(false);
      const unread = Number(data?.nao_lidas || 0);
      const badge = qs('[data-chat-badge]');
      if (badge) {
        badge.textContent = unread > 9 ? '9+' : String(unread);
        badge.classList.toggle('hidden', unread <= 0);
      }
    } catch (_) {
      // Chat ainda indisponivel ou corrida sem motorista.
    }
  }

  async function openChat() {
    if (!state.activeRideId) return;
    state.chatOpen = true;
    qs('[data-chat-modal]')?.classList.remove('hidden');
    await refreshChat(true);
    clearInterval(state.chatTimer);
    state.chatTimer = setInterval(() => refreshChat(true), 3500);
  }

  function closeChat() {
    state.chatOpen = false;
    qs('[data-chat-modal]')?.classList.add('hidden');
    clearInterval(state.chatTimer);
    state.chatTimer = null;
  }

  async function sendChatMessage(event) {
    event.preventDefault();
    if (!state.activeRideId) return;
    const input = qs('[data-chat-input]');
    const message = (input?.value || '').trim();
    if (!message) return;
    try {
      await api('../corridas/chat_corrida.php', {
        method: 'POST',
        body: JSON.stringify({
          id_corrida: state.activeRideId,
          id_usuario: state.user.id,
          tipo_usuario: 'passageiro',
          mensagem: message,
        }),
      });
      input.value = '';
      await refreshChat(true);
    } catch (error) {
      toast(error.message, true);
    }
  }

  async function submitRating() {
    if (!state.activeRideId) return;
    if (state.rating < 1 || state.rating > 5) {
      toast('Escolha uma nota para continuar.', true);
      return;
    }

    const problems = qsa('[data-rating-bad] input:checked').map((input) => input.value);
    const comment = state.rating === 5
      ? (qs('[data-rating-comment-good]')?.value || '')
      : (qs('[data-rating-comment-bad]')?.value || '');
    if (state.rating < 5 && problems.length === 0 && comment.trim() === '') {
      toast('Informe pelo menos um motivo para a avaliação.', true);
      return;
    }

    const button = qs('[data-submit-rating]');
    button.disabled = true;
    button.textContent = 'Enviando...';
    try {
      await api('../corridas/avaliar_corrida.php', {
        method: 'POST',
        body: JSON.stringify({
          id_corrida: state.activeRideId,
          id_passageiro: state.user.id,
          nota: state.rating,
          comentario: comment,
          selo: state.rating === 5 ? (qs('[data-rating-seal]')?.value || '') : '',
          problemas: state.rating < 5 ? problems : [],
        }),
      });
      toast('Avaliação enviada. Obrigado!');
      qs('[data-active-ride]')?.classList.add('hidden');
      setRideActive(false);
      state.activeRideId = null;
      state.rating = 0;
      setRating(0);
      await loadProfile();
    } catch (error) {
      toast(error.message, true);
    } finally {
      button.disabled = false;
      button.textContent = 'Enviar avaliação';
    }
  }

  async function pollRide(immediate = false) {
    if (!state.activeRideId) return;
    const run = async () => {
      try {
        const data = await api(`../corridas/status_corrida.php?id_corrida=${state.activeRideId}`);
        if (data.corrida) updateActiveRide(data.corrida);
      } catch (_) {
        // Mantém o app tentando, pois pode ser oscilação momentânea.
      }
    };
    if (immediate) await run();
    clearInterval(state.pollTimer);
    state.pollTimer = setInterval(run, 4500);
  }

  async function loadActiveRide() {
    try {
      const data = await api(`../corridas/corrida_ativa_passageiro.php?id_passageiro=${state.user.id}`);
      if (data.corrida) {
        state.activeRideId = data.corrida.id;
        qs('[data-active-ride]')?.classList.remove('hidden');
        qs('[data-quote-box]')?.classList.add('hidden');
        qs('[data-search-state]')?.classList.add('compact');
        setRideActive(true);
        updateActiveRide(data.corrida);
        pollRide();
      }
    } catch (_) {
      // Sem corrida ativa.
    }
  }

  async function cancelRide() {
    if (!state.activeRideId) return;
    try {
      await api('../config/corridas/cancelar_corrida.php', {
        method: 'POST',
        body: JSON.stringify({
          id_corrida: state.activeRideId,
          id_passageiro: state.user.id,
          cancelada_por: 'passageiro',
          motivo: qs('[data-cancel-reason]')?.value || 'outro_motivo',
          observacao: qs('[data-cancel-note]')?.value || '',
        }),
      });
      resetCanceledRideUi();
      toast('Corrida cancelada.');
    } catch (error) {
      toast(error.message, true);
    }
  }

  function resetCanceledRideUi() {
    clearInterval(state.pollTimer);
    state.pollTimer = null;
    state.activeRideId = null;
    state.rating = 0;
    setRating(0);
    closeChat();
    qs('[data-cancel-modal]')?.classList.add('hidden');
    qs('[data-active-ride]')?.classList.add('hidden');
    qs('[data-search-state]')?.classList.remove('compact');
    qs('[data-rating-box]')?.classList.add('hidden');
    qs('[data-open-chat]')?.classList.add('hidden');
    setRideActive(false);
    if (state.driverMarker) state.driverMarker.setMap(null);
    clearRoute();
  }

  function clearRoute() {
    state.destination = null;
    state.stops = [];
    state.route = null;
    const destinationInput = qs('#destinationInput');
    if (destinationInput) destinationInput.value = '';
    const stops = qs('[data-stops]');
    if (stops) stops.innerHTML = '';
    qs('[data-quote-box]')?.classList.add('hidden');
    qs('[data-route-summary]')?.classList.add('hidden');
    state.directionsRenderer?.set('directions', null);
    updateRouteMarkers();
  }

  function openSidebar() {
    qs('[data-sidebar]')?.classList.add('open');
    qs('[data-sidebar-backdrop]')?.classList.add('open');
  }

  function closeSidebar() {
    qs('[data-sidebar]')?.classList.remove('open');
    qs('[data-sidebar-backdrop]')?.classList.remove('open');
  }

  function bindUi() {
    bindAutocomplete(qs('#originInput'), (location, address) => {
      state.origin = location;
      qs('#originInput').value = address;
      maybeBuildRoute();
    });
    bindAutocomplete(qs('#destinationInput'), (location, address) => setDestination(location, address));

    qs('[data-menu]')?.addEventListener('click', openSidebar);
    qs('[data-mobile-profile]')?.addEventListener('click', openSidebar);
    qs('[data-close-sidebar]')?.addEventListener('click', closeSidebar);
    qs('[data-sidebar-backdrop]')?.addEventListener('click', closeSidebar);
    qsa('[data-sidebar] a').forEach((link) => link.addEventListener('click', closeSidebar));
    qs('[data-logout]')?.addEventListener('click', () => {
      sessionStorage.removeItem('bulo_user');
      window.location.href = './';
    });
    qs('[data-center-map]')?.addEventListener('click', () => {
      if (state.origin) state.map.panTo(state.origin);
      else setCurrentLocation();
    });
    qs('[data-location-request]')?.addEventListener('click', setCurrentLocation);
    qs('[data-add-stop]')?.addEventListener('click', addStopField);
    qs('[data-clear-route]')?.addEventListener('click', clearRoute);
    qs('[data-request-ride]')?.addEventListener('click', requestRide);
    qs('[data-cancel-ride]')?.addEventListener('click', () => qs('[data-cancel-modal]')?.classList.remove('hidden'));
    qs('[data-close-cancel]')?.addEventListener('click', () => qs('[data-cancel-modal]')?.classList.add('hidden'));
    qs('[data-confirm-cancel]')?.addEventListener('click', cancelRide);
    qs('[data-active-toggle]')?.addEventListener('click', () => qs('[data-active-body]')?.classList.toggle('hidden'));
    qs('[data-open-driver-profile]')?.addEventListener('click', openDriverProfile);
    qs('[data-close-driver-profile]')?.addEventListener('click', () => qs('[data-driver-profile-modal]')?.classList.add('hidden'));
    qs('[data-driver-profile-modal]')?.addEventListener('click', (event) => {
      if (event.target === qs('[data-driver-profile-modal]')) {
        qs('[data-driver-profile-modal]')?.classList.add('hidden');
      }
    });
    qs('[data-open-chat]')?.addEventListener('click', openChat);
    qs('[data-close-chat]')?.addEventListener('click', closeChat);
    qs('[data-chat-form]')?.addEventListener('submit', sendChatMessage);
    qsa('[data-rating-stars] button').forEach((button) => {
      button.addEventListener('click', () => setRating(button.dataset.rating));
    });
    qs('[data-submit-rating]')?.addEventListener('click', submitRating);
  }

  window.initBuloPassengerWeb = async function initBuloPassengerWeb() {
    if (!ensureLogged()) return;
    initMap();
    bindUi();
    await Promise.allSettled([loadProfile(), loadAddresses(), setCurrentLocation()]);
    await loadActiveRide();
  };
})();
