import * as icon from '@mdi/js';
import axios from 'axios';
import Head from 'next/head';
import Link from 'next/link';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import BaseButton from '../BaseButton';
import BaseButtons from '../BaseButtons';
import BaseIcon from '../BaseIcon';
import CardBox from '../CardBox';
import SectionMain from '../SectionMain';
import SectionTitleLineWithButton from '../SectionTitleLineWithButton';
import { getPageTitle } from '../../config';
import { useAppSelector } from '../../stores/hooks';
import {
  defaultGeoSeekLocation,
  GeoSeekItem,
  GeoSeekItemType,
  geoSeekModules,
  GeoSeekModuleKey,
} from '../../data/geoseek';
import {
  createCartFromResults,
  createSmartDraft,
  currency,
  filterGeoSeekItems,
  getBusinessInsights,
  getCheckoutSummary,
  getDistancePriority,
  GeoSeekScoredItem,
  GeoSeekSmartDraft,
} from '../../data/geoseekAutomation';

type Props = {
  moduleKey?: string;
};

type GeoSeekActionHistory = {
  id: string;
  moduleKey: GeoSeekModuleKey;
  label: string;
  message: string;
  createdAt: string;
};

type QuickAction = {
  label: string;
  message: string;
  color: 'info' | 'success' | 'warning' | 'contrast';
  iconPath: string;
};

type GeoSeekLocationSource = 'browser' | 'demo';

type GeoSeekResolvedLocation = {
  label: string;
  latitude: number;
  longitude: number;
  source: GeoSeekLocationSource;
  accuracyMeters?: number;
};

type PublicPlaceOffering = {
  id?: string;
  name?: string;
  description?: string;
  offering_type?: string;
  price?: number | string | null;
  stock_status?: string;
  stock_label?: string;
  stock_quantity?: number | string | null;
  is_verified?: boolean;
};

type PublicPlaceRow = {
  id?: string;
  name?: string;
  short_description?: string;
  full_description?: string;
  address?: string;
  city?: string;
  province?: string;
  latitude?: number | string | null;
  longitude?: number | string | null;
  average_price?: number | string | null;
  rating_average?: number | string | null;
  rating_count?: number | string | null;
  is_verified?: boolean;
  distance_km?: number | string | null;
  geo_score?: number | string | null;
  category?: {
    name?: string;
    slug?: string;
    description?: string;
  } | null;
  offerings?: PublicPlaceOffering[];
  offerings_summary?: {
    products?: number;
    services?: number;
    total?: number;
    available?: number;
  };
  live_status?: {
    status?: string;
    label?: string;
  };
  external_source?: string;
};

type PublicPlacesResponse = {
  rows?: PublicPlaceRow[];
  count?: number;
  radius_km?: number | null;
  radius_zone?: {
    label?: string;
    range?: string;
    description?: string;
  } | null;
  filtered_by_radius?: boolean;
  expanded_for_nearest?: boolean;
  external_sources?: string[];
  external_source_errors?: string[];
  total_candidates?: number;
};

type GeoSeekApiMeta = {
  count: number;
  totalCandidates: number;
  radiusZoneLabel: string;
  externalSources: string[];
  externalSourceErrors: string[];
  filteredByRadius: boolean;
  expandedForNearest: boolean;
};

const typeLabels: Record<GeoSeekItemType, string> = {
  place: 'Tempat',
  product: 'Produk',
  service: 'Jasa',
  business: 'UMKM',
  culinary: 'Kuliner',
  health: 'Kesehatan',
  property: 'Properti',
  automotive: 'Otomotif',
  tourism: 'Wisata',
  event: 'Event',
  promo: 'Promo',
  courier: 'Kurir',
};

const backendDemoGeoSeekLocation: GeoSeekResolvedLocation = {
  label: 'Pekanbaru Data Demo',
  latitude: 0.5095,
  longitude: 101.4549,
  source: 'demo',
};

const emptyApiMeta: GeoSeekApiMeta = {
  count: 0,
  totalCandidates: 0,
  radiusZoneLabel: 'Radius aktif',
  externalSources: [],
  externalSourceErrors: [],
  filteredByRadius: false,
  expandedForNearest: false,
};

const radiusOptions = [1, 5, 10, 20];

const apiQueryByModule: Partial<Record<GeoSeekModuleKey, string>> = {
  home: 'produk jasa umkm lokal',
  search: 'produk jasa umkm lokal',
  map: '',
  products: 'produk stok toko',
  services: 'jasa servis booking',
  umkm: '',
  culinary: 'kuliner cafe warung',
  health: 'kesehatan apotek klinik',
  property: 'properti ruko rumah',
  automotive: 'bengkel otomotif servis',
  tourism: 'wisata hotel lokal',
  events: 'event bazar lokal',
  promos: 'promo diskon lokal',
  marketplace: 'produk marketplace lokal',
  booking: 'jasa booking lokal',
  courier: 'kurir antar lokal',
  'business-dashboard': '',
  profile: '',
};

const getApiQuery = (query: string, moduleKey: GeoSeekModuleKey) => query.trim() || apiQueryByModule[moduleKey] || '';

const toOptionalNumber = (value: unknown) => {
  if (value === null || value === undefined || value === '') return undefined;

  const number = Number(value);

  return Number.isFinite(number) ? number : undefined;
};

const normalizeTagText = (value: unknown) => String(value || '')
  .toLowerCase()
  .normalize('NFD')
  .replace(/[\u0300-\u036f]/g, '')
  .replace(/[^a-z0-9]+/g, ' ')
  .trim();

const createTags = (values: unknown[], fallbackTags: string[] = ['lokal', 'geoseek']) => {
  const tags = values
    .flatMap((value) => normalizeTagText(value).split(/\s+/))
    .filter((word) => word.length > 2 && !['dan', 'atau', 'yang', 'untuk', 'dari'].includes(word));

  return Array.from(new Set([...tags, ...fallbackTags])).slice(0, 8);
};

const getPublicPlaceArea = (place: PublicPlaceRow) => [place.city, place.province].filter(Boolean).join(', ') || 'Area sekitar';

const getPublicPlaceAddress = (place: PublicPlaceRow) => [place.address, place.city, place.province].filter(Boolean).join(', ') || 'Alamat mengikuti data lokasi';

const getPublicPlaceCategory = (place: PublicPlaceRow) => place.category?.name || 'UMKM Lokal';

const getPublicPlaceDescription = (place: PublicPlaceRow) => place.short_description || place.full_description || 'Bisnis lokal dari database GeoSeek.';

const getPublicPlaceType = (place: PublicPlaceRow): GeoSeekItemType => {
  const haystack = normalizeTagText([
    place.name,
    place.category?.name,
    place.category?.slug,
    place.category?.description,
    place.short_description,
    place.full_description,
  ].join(' '));

  if (/kuliner|cafe|kopi|restoran|warung|kedai|makan|food/.test(haystack)) return 'culinary';
  if (/kesehatan|apotek|klinik|herbal|obat|dokter|health/.test(haystack)) return 'health';
  if (/bengkel|otomotif|mobil|motor|servis|service|auto/.test(haystack)) return 'automotive';
  if (/properti|ruko|rumah|tanah|kios|property/.test(haystack)) return 'property';
  if (/wisata|hotel|travel|tour/.test(haystack)) return 'tourism';
  if (/event|bazar|agenda/.test(haystack)) return 'event';

  return 'business';
};

const getOfferingType = (offering: PublicPlaceOffering): GeoSeekItemType => (offering.offering_type === 'product' ? 'product' : 'service');

const getOfferingStock = (offering: PublicPlaceOffering) => {
  const quantity = toOptionalNumber(offering.stock_quantity);

  if (quantity !== undefined) return Math.round(quantity);
  if (offering.stock_status === 'limited') return 8;
  if (offering.stock_status === 'in_stock') return 24;

  return undefined;
};

const getApiActivityScore = (place: PublicPlaceRow, offering?: PublicPlaceOffering) => {
  const geoScore = toOptionalNumber(place.geo_score);
  const baseScore = geoScore ?? (place.is_verified ? 86 : 72);
  const verifiedBonus = offering?.is_verified ? 8 : 0;

  return Math.max(45, Math.min(100, Math.round(baseScore + verifiedBonus)));
};

const publicPlaceToGeoSeekItems = (place: PublicPlaceRow): GeoSeekItem[] => {
  const placeId = place.id || `place-${place.name || 'unknown'}`;
  const category = getPublicPlaceCategory(place);
  const distanceKm = toOptionalNumber(place.distance_km) ?? 0;
  const rating = toOptionalNumber(place.rating_average) ?? 4.2;
  const reviews = Math.round(toOptionalNumber(place.rating_count) ?? 0);
  const latitude = toOptionalNumber(place.latitude) ?? backendDemoGeoSeekLocation.latitude;
  const longitude = toOptionalNumber(place.longitude) ?? backendDemoGeoSeekLocation.longitude;
  const offerings = Array.isArray(place.offerings) ? place.offerings : [];
  const hasProducts = offerings.some((offering) => offering.offering_type === 'product');
  const hasServices = offerings.some((offering) => offering.offering_type === 'service');
  const open = place.live_status?.status !== 'closed';
  const baseTags = createTags([
    place.name,
    category,
    place.category?.slug,
    place.short_description,
    place.full_description,
    offerings.map((offering) => offering.name).join(' '),
  ], ['backend', 'umkm', 'lokal']);

  const businessItem: GeoSeekItem = {
    id: `api-place-${placeId}`,
    type: getPublicPlaceType(place),
    name: place.name || 'Bisnis Lokal GeoSeek',
    businessName: place.name || 'Bisnis Lokal GeoSeek',
    category,
    description: getPublicPlaceDescription(place),
    address: getPublicPlaceAddress(place),
    area: getPublicPlaceArea(place),
    latitude,
    longitude,
    distanceKm,
    price: toOptionalNumber(place.average_price),
    rating,
    reviews,
    activityScore: getApiActivityScore(place),
    tags: baseTags,
    open,
    promo: place.is_verified ? 'Bisnis terverifikasi di data GeoSeek' : undefined,
    etaMinutes: hasServices ? Math.max(12, Math.min(60, Math.round(distanceKm * 5 + 15))) : undefined,
    bookingAvailable: hasServices,
    deliveryAvailable: hasProducts,
  };

  const offeringItems = offerings.map((offering, index): GeoSeekItem => {
    const type = getOfferingType(offering);
    const stock = getOfferingStock(offering);
    const stockLabel = offering.stock_label || offering.stock_status || 'Info stok tersedia';

    return {
      id: `api-offering-${placeId}-${offering.id || index}`,
      type,
      name: offering.name || (type === 'product' ? 'Produk lokal' : 'Jasa lokal'),
      businessName: businessItem.businessName,
      category: `${typeLabels[type]} • ${category}`,
      description: offering.description || getPublicPlaceDescription(place),
      address: businessItem.address,
      area: businessItem.area,
      latitude,
      longitude,
      distanceKm,
      price: toOptionalNumber(offering.price) ?? toOptionalNumber(place.average_price),
      stock,
      rating,
      reviews,
      activityScore: getApiActivityScore(place, offering),
      tags: createTags([offering.name, offering.description, category, stockLabel, place.name], [type, 'backend', 'lokal']),
      open,
      promo: offering.stock_status === 'limited' ? `Stok terbatas: ${stockLabel}` : undefined,
      etaMinutes: type === 'service' ? Math.max(12, Math.min(60, Math.round(distanceKm * 5 + 15))) : undefined,
      bookingAvailable: type === 'service',
      deliveryAvailable: type === 'product',
    };
  });

  return [businessItem, ...offeringItems];
};

const normalizePublicPlaceItems = (rows: PublicPlaceRow[]) => {
  const seen = new Set<string>();

  return rows.flatMap(publicPlaceToGeoSeekItems).filter((item) => {
    if (seen.has(item.id)) return false;

    seen.add(item.id);
    return true;
  });
};

const moduleIconMap: Partial<Record<GeoSeekModuleKey, string>> = {
  home: icon.mdiViewDashboardOutline,
  search: icon.mdiMagnify,
  map: icon.mdiMapSearchOutline,
  products: icon.mdiShoppingOutline,
  services: icon.mdiBriefcaseSearchOutline,
  umkm: icon.mdiStore,
  culinary: icon.mdiFoodForkDrink,
  health: icon.mdiHospitalBoxOutline,
  property: icon.mdiHomeCityOutline,
  automotive: icon.mdiCarWrench,
  tourism: icon.mdiBeach,
  events: icon.mdiCalendar,
  promos: icon.mdiTicketPercentOutline,
  marketplace: icon.mdiCart,
  booking: icon.mdiCalendar,
  courier: icon.mdiTruck,
  'business-dashboard': icon.mdiFinance,
  profile: icon.mdiAccountCircle,
};

const moduleOptions = geoSeekModules.map((module) => ({
  href: module.key === 'home' ? '/geoseek' : `/geoseek/${module.key}`,
  key: module.key,
  label: module.menuLabel,
  iconPath: moduleIconMap[module.key] || icon.mdiTable,
}));

const quickPrompts = [
  'pupuk organik stok dekat pasar',
  'nasi goreng promo antar',
  'servis ac booking cepat',
  'tambal ban buka sekarang',
  'apotek vitamin 24 jam',
  'gratis ongkir radius 3 km',
];

const defaultQueryByModule: Partial<Record<GeoSeekModuleKey, string>> = {
  home: 'pupuk organik',
  search: 'pupuk organik',
  map: '',
  products: '',
  services: '',
  umkm: '',
  culinary: '',
  health: '',
  property: '',
  automotive: '',
  tourism: '',
  events: '',
  promos: '',
  marketplace: '',
  booking: '',
  courier: '',
  'business-dashboard': '',
  profile: '',
};

const getDefaultQuery = (moduleKey: GeoSeekModuleKey) => defaultQueryByModule[moduleKey] ?? '';

const localPublishedItemsKey = 'geoseek-pro-published-items';
const localActionHistoryKey = 'geoseek-pro-action-history';

const getActionTimestamp = () => new Intl.DateTimeFormat('id-ID', {
  dateStyle: 'medium',
  timeStyle: 'short',
}).format(new Date());

const getDraftItemType = (category: string, moduleKey: GeoSeekModuleKey): GeoSeekItemType => {
  const normalizedCategory = category.toLowerCase();

  if (moduleKey === 'map') return 'business';
  if (moduleKey === 'products' || /produk|pertanian|tani|stok/.test(normalizedCategory)) return 'product';
  if (moduleKey === 'culinary' || /kuliner|makan|minum|warung/.test(normalizedCategory)) return 'culinary';
  if (moduleKey === 'health' || /kesehatan|obat|klinik|apotek/.test(normalizedCategory)) return 'health';
  if (moduleKey === 'property' || /properti|ruko|rumah|tanah|kios/.test(normalizedCategory)) return 'property';
  if (moduleKey === 'automotive' || /otomotif|bengkel|mobil|motor/.test(normalizedCategory)) return 'automotive';
  if (moduleKey === 'tourism' || /wisata/.test(normalizedCategory)) return 'tourism';
  if (moduleKey === 'events' || /event|bazar|agenda/.test(normalizedCategory)) return 'event';
  if (moduleKey === 'promos' || /promo|diskon|voucher/.test(normalizedCategory)) return 'promo';
  if (moduleKey === 'courier' || /kurir|antar|kirim|ongkir/.test(normalizedCategory)) return 'courier';
  if (moduleKey === 'services' || moduleKey === 'booking' || /jasa|servis|booking/.test(normalizedCategory)) return 'service';

  return 'business';
};

const createPublishedItem = (
  input: string,
  draft: GeoSeekSmartDraft,
  moduleKey: GeoSeekModuleKey,
  origin: { latitude: number; longitude: number } = defaultGeoSeekLocation,
): GeoSeekItem => {
  const type = getDraftItemType(draft.category, moduleKey);
  const distanceKm = Math.min(2.8, Number((0.7 + (draft.itemName.length % 12) / 10).toFixed(1)));
  const supportsBooking = ['service', 'health', 'property', 'tourism', 'culinary'].includes(type);
  const supportsDelivery = ['product', 'culinary', 'promo', 'courier'].includes(type);

  return {
    id: `gsk-local-${Date.now()}`,
    type,
    name: draft.itemName || draft.businessName,
    businessName: draft.businessName,
    category: draft.category,
    description: `Item lokal dari Smart Input: ${input}`,
    address: draft.location,
    area: draft.location,
    latitude: origin.latitude + distanceKm / 1000,
    longitude: origin.longitude + distanceKm / 900,
    distanceKm,
    price: draft.price,
    stock: draft.stock,
    rating: 4.8,
    reviews: 1,
    activityScore: 95,
    tags: Array.from(new Set([...draft.tags, 'smart-input', 'lokal'])),
    open: draft.status !== 'Perlu review manual',
    promo: draft.promo.startsWith('Promo aktif') ? draft.promo : undefined,
    etaMinutes: supportsBooking || type === 'courier' ? 18 : undefined,
    bookingAvailable: supportsBooking,
    deliveryAvailable: supportsDelivery,
  };
};

const sampleSmartInputs = [
  'Warung Sari Rasa promo nasi goreng Rp15000 stok 42 dekat Alun-Alun buka sampai malam',
  'Toko Tani Makmur menjual pupuk organik Rp38000 stok 64 dekat Pasar Tani gratis antar radius 2 km',
  'Jaya Teknik buka jasa servis AC panggilan Rp85000 area Melati booking hari ini',
];

const getModule = (moduleKey?: string) => {
  const matchedModule = geoSeekModules.find((module) => module.key === moduleKey);

  return matchedModule || geoSeekModules[0];
};

const getActionSet = (moduleKey: GeoSeekModuleKey): QuickAction[] => {
  const baseActions: QuickAction[] = [
    {
      label: 'Hitung GeoScore',
      message: 'GeoScore otomatis dihitung ulang dari jarak, relevansi, rating, dan aktivitas.',
      color: 'info',
      iconPath: icon.mdiChartTimelineVariant,
    },
    {
      label: 'Buat Rute',
      message: 'Rute demo disiapkan dari lokasi pengguna ke hasil prioritas terdekat.',
      color: 'success',
      iconPath: icon.mdiMapMarker,
    },
  ];

  const moduleActions: Partial<Record<GeoSeekModuleKey, QuickAction[]>> = {
    products: [
      {
        label: 'Auto Restock',
        message: 'Sistem menandai produk stok rendah dan membuat rekomendasi restock.',
        color: 'warning',
        iconPath: icon.mdiPackageVariantClosed,
      },
    ],
    services: [
      {
        label: 'Booking Jasa',
        message: 'Draft booking jasa dibuat dengan ETA dan penyedia terdekat.',
        color: 'success',
        iconPath: icon.mdiCalendar,
      },
    ],
    marketplace: [
      {
        label: 'Checkout Otomatis',
        message: 'Keranjang, ongkir, diskon, dan metode bayar simulasi berhasil disiapkan.',
        color: 'success',
        iconPath: icon.mdiCart,
      },
    ],
    booking: [
      {
        label: 'Buat Jadwal',
        message: 'Slot booking demo dibuat berdasarkan kategori, jarak, dan status buka.',
        color: 'success',
        iconPath: icon.mdiClockOutline,
      },
    ],
    courier: [
      {
        label: 'Dispatch Kurir',
        message: 'Kurir terdekat dipilih otomatis dengan ETA dan estimasi ongkir.',
        color: 'success',
        iconPath: icon.mdiTruck,
      },
    ],
    promos: [
      {
        label: 'Sebar Promo',
        message: 'Promo siap dikirim ke pengguna dalam radius yang dipilih.',
        color: 'warning',
        iconPath: icon.mdiTicketPercentOutline,
      },
    ],
    'business-dashboard': [
      {
        label: 'Buat Insight',
        message: 'Insight stok, promo, booking, dan peluang bisnis berhasil diperbarui.',
        color: 'contrast',
        iconPath: icon.mdiFinance,
      },
    ],
  };

  return [...baseActions, ...(moduleActions[moduleKey] || [])];
};

const getItemActionLabel = (moduleKey: GeoSeekModuleKey, item: GeoSeekScoredItem) => {
  if (moduleKey === 'marketplace' || item.type === 'product' || item.type === 'culinary') return 'Tambah ke Keranjang';
  if (moduleKey === 'booking' || item.bookingAvailable) return 'Booking Otomatis';
  if (moduleKey === 'courier' || item.type === 'courier') return 'Pilih Kurir';
  if (moduleKey === 'map') return 'Buka Rute';
  if (moduleKey === 'promos' || item.type === 'promo') return 'Klaim Promo';

  return 'Aktifkan Otomasi';
};

const getMapPosition = (item: GeoSeekScoredItem, index: number, origin: { latitude: number; longitude: number } = defaultGeoSeekLocation) => {
  const left = Math.min(88, Math.max(8, 50 + (item.longitude - origin.longitude) * 1800 + index * 2));
  const top = Math.min(82, Math.max(10, 50 + (item.latitude - origin.latitude) * -1800 + index * 3));

  return { left: `${left}%`, top: `${top}%` };
};

const StatCard = ({ label, value, help, iconPath }: { label: string; value: string | number; help: string; iconPath: string }) => (
  <CardBox className="bg-white/80 dark:bg-dark-900">
    <div className="flex items-start justify-between gap-4">
      <div>
        <p className="text-sm text-gray-500 dark:text-gray-400">{label}</p>
        <p className="mt-2 text-3xl font-bold text-gray-900 dark:text-white">{value}</p>
        <p className="mt-1 text-xs text-gray-500 dark:text-gray-400">{help}</p>
      </div>
      <div className="rounded-2xl bg-blue-50 p-3 text-blue-600 dark:bg-blue-900/30 dark:text-blue-200">
        <BaseIcon path={iconPath} size={24} />
      </div>
    </div>
  </CardBox>
);

const ResultCard = ({
  item,
  moduleKey,
  onAction,
}: {
  item: GeoSeekScoredItem;
  moduleKey: GeoSeekModuleKey;
  onAction: (message: string) => void;
}) => (
  <CardBox isHoverable className="border border-gray-100 bg-white/90 dark:border-dark-700 dark:bg-dark-900">
    <div className="flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
      <div className="min-w-0 flex-1">
        <div className="mb-3 flex flex-wrap items-center gap-2">
          <span className="rounded-full bg-blue-100 px-3 py-1 text-xs font-semibold text-blue-700 dark:bg-blue-900/40 dark:text-blue-200">
            {typeLabels[item.type]}
          </span>
          <span className="rounded-full bg-emerald-100 px-3 py-1 text-xs font-semibold text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-200">
            GeoScore {item.geoScore}
          </span>
          <span className="rounded-full bg-amber-100 px-3 py-1 text-xs font-semibold text-amber-700 dark:bg-amber-900/40 dark:text-amber-200">
            {item.distanceKm.toFixed(1)} km • {item.distancePriority.label}
          </span>
          {item.open && (
            <span className="rounded-full bg-green-100 px-3 py-1 text-xs font-semibold text-green-700 dark:bg-green-900/40 dark:text-green-200">
              Buka
            </span>
          )}
        </div>
        <h3 className="text-xl font-bold text-gray-900 dark:text-white">{item.name}</h3>
        <p className="mt-1 text-sm font-medium text-gray-600 dark:text-gray-300">{item.businessName} • {item.category}</p>
        <p className="mt-3 text-sm leading-6 text-gray-600 dark:text-gray-300">{item.description}</p>
        <div className="mt-4 grid gap-3 text-sm text-gray-600 dark:text-gray-300 md:grid-cols-2">
          <div className="rounded-xl bg-gray-50 p-3 dark:bg-dark-800">
            <span className="font-semibold text-gray-900 dark:text-white">Lokasi:</span> {item.address}, {item.area}
          </div>
          <div className="rounded-xl bg-gray-50 p-3 dark:bg-dark-800">
            <span className="font-semibold text-gray-900 dark:text-white">Rating:</span> {item.rating.toFixed(1)} / 5 • {item.reviews} ulasan
          </div>
          <div className="rounded-xl bg-gray-50 p-3 dark:bg-dark-800">
            <span className="font-semibold text-gray-900 dark:text-white">Harga:</span> {currency(item.price)}
          </div>
          <div className="rounded-xl bg-gray-50 p-3 dark:bg-dark-800">
            <span className="font-semibold text-gray-900 dark:text-white">Stok/ETA:</span>{' '}
            {typeof item.stock === 'number' ? `${item.stock} tersedia` : item.etaMinutes ? `${item.etaMinutes} menit` : 'Tersedia sesuai permintaan'}
          </div>
        </div>
        {item.promo && (
          <div className="mt-4 rounded-2xl border border-orange-200 bg-orange-50 p-3 text-sm font-medium text-orange-700 dark:border-orange-900/60 dark:bg-orange-900/20 dark:text-orange-200">
            {item.promo}
          </div>
        )}
        <div className="mt-4 flex flex-wrap gap-2">
          {item.tags.slice(0, 6).map((tag) => (
            <span key={tag} className="rounded-full border border-gray-200 px-3 py-1 text-xs text-gray-500 dark:border-dark-700 dark:text-gray-300">
              #{tag}
            </span>
          ))}
        </div>
      </div>
      <div className="w-full rounded-2xl bg-slate-50 p-4 dark:bg-dark-800 lg:w-72">
        <p className="text-sm font-bold text-gray-900 dark:text-white">Rincian GeoScore</p>
        <div className="mt-3 space-y-2 text-xs text-gray-600 dark:text-gray-300">
          <div className="flex justify-between gap-3"><span>Prioritas jarak</span><span className="text-right">{item.distancePriority.label}</span></div>
          <div className="flex justify-between"><span>Jarak 60%</span><span>{item.distanceScore}</span></div>
          <div className="flex justify-between"><span>Relevansi 20%</span><span>{item.relevanceScore}</span></div>
          <div className="flex justify-between"><span>Rating 10%</span><span>{item.ratingScore}</span></div>
          <div className="flex justify-between"><span>Aktivitas 10%</span><span>{item.activityContribution}</span></div>
        </div>
        <div className="mt-4 space-y-2">
          {item.automationNotes.map((note) => (
            <div key={note} className="rounded-xl bg-white px-3 py-2 text-xs text-gray-600 shadow-sm dark:bg-dark-900 dark:text-gray-300">
              ✓ {note}
            </div>
          ))}
        </div>
        <BaseButton
          color="info"
          label={getItemActionLabel(moduleKey, item)}
          icon={icon.mdiRobot}
          className="mt-4 w-full"
          onClick={() => onAction(`${getItemActionLabel(moduleKey, item)} untuk “${item.name}” berhasil dibuat sebagai simulasi otomatis.`)}
        />
      </div>
    </div>
  </CardBox>
);

export default function GeoSeekProWorkspace({ moduleKey = 'home' }: Props) {
  const normalizedModuleKey = getModule(moduleKey).key;
  const activeModule = getModule(normalizedModuleKey);
  const [query, setQuery] = useState(getDefaultQuery(activeModule.key));
  const [radiusKm, setRadiusKm] = useState(5);
  const [smartInput, setSmartInput] = useState(sampleSmartInputs[0]);
  const [actionStatus, setActionStatus] = useState('Sistem otomasi siap digunakan. Pilih aksi cepat atau jalankan Smart Input.');
  const [publishedItems, setPublishedItems] = useState<GeoSeekItem[]>([]);
  const [actionHistory, setActionHistory] = useState<GeoSeekActionHistory[]>([]);
  const [isLocalStateReady, setIsLocalStateReady] = useState(false);
  const [resolvedLocation, setResolvedLocation] = useState<GeoSeekResolvedLocation>(backendDemoGeoSeekLocation);
  const [isResolvingLocation, setIsResolvingLocation] = useState(true);
  const [locationStatus, setLocationStatus] = useState('Mengambil lokasi browser untuk pencarian radius GeoSeek...');
  const [apiItems, setApiItems] = useState<GeoSeekItem[]>([]);
  const [isLoadingPlaces, setIsLoadingPlaces] = useState(false);
  const [apiError, setApiError] = useState('');
  const [apiMeta, setApiMeta] = useState<GeoSeekApiMeta>(emptyApiMeta);
  const [searchRequestVersion, setSearchRequestVersion] = useState(0);
  const { currentUser } = useAppSelector((state) => state.auth);
  const activeDistancePriority = useMemo(() => getDistancePriority(radiusKm), [radiusKm]);

  const hasBackendItemsForModule = useMemo(
    () => apiItems.some((item) => activeModule.includeTypes.includes(item.type)),
    [activeModule.includeTypes, apiItems],
  );

  const liveExtraItems = useMemo(() => [...apiItems, ...publishedItems], [apiItems, publishedItems]);

  const results = useMemo(
    () => filterGeoSeekItems({
      query,
      radiusKm,
      includeTypes: activeModule.includeTypes,
      moduleKey: activeModule.key,
      extraItems: liveExtraItems,
      baseItems: hasBackendItemsForModule ? [] : undefined,
    }),
    [activeModule.includeTypes, activeModule.key, hasBackendItemsForModule, liveExtraItems, query, radiusKm],
  );

  const allModuleResults = useMemo(
    () => filterGeoSeekItems({
      query: '',
      radiusKm: 20,
      includeTypes: activeModule.includeTypes,
      moduleKey: activeModule.key,
      extraItems: liveExtraItems,
      baseItems: hasBackendItemsForModule ? [] : undefined,
    }),
    [activeModule.includeTypes, activeModule.key, hasBackendItemsForModule, liveExtraItems],
  );

  const smartDraft = useMemo(() => createSmartDraft(smartInput), [smartInput]);
  const insight = useMemo(() => getBusinessInsights(allModuleResults), [allModuleResults]);
  const cartItems = useMemo(() => createCartFromResults(results), [results]);
  const checkout = useMemo(() => getCheckoutSummary(cartItems), [cartItems]);
  const actionSet = getActionSet(activeModule.key);
  const mapItems = (results.length ? results : allModuleResults).slice(0, 8);

  const requestCurrentLocation = useCallback(() => {
    setIsResolvingLocation(true);
    setLocationStatus('Mengambil lokasi browser untuk pencarian radius GeoSeek...');

    if (typeof navigator === 'undefined' || !navigator.geolocation) {
      setResolvedLocation(backendDemoGeoSeekLocation);
      setLocationStatus('Browser tidak mendukung GPS. GeoSeek memakai lokasi demo backend Pekanbaru.');
      setIsResolvingLocation(false);
      return;
    }

    navigator.geolocation.getCurrentPosition(
      (position) => {
        setResolvedLocation({
          label: 'Lokasi browser Anda',
          latitude: position.coords.latitude,
          longitude: position.coords.longitude,
          source: 'browser',
          accuracyMeters: Math.round(position.coords.accuracy),
        });
        setLocationStatus('GPS aktif. Hasil GeoSeek dihitung dari lokasi browser Anda.');
        setIsResolvingLocation(false);
      },
      (error) => {
        console.warn('GeoSeek tidak mendapat izin/lokasi browser, memakai fallback demo backend:', error);
        setResolvedLocation(backendDemoGeoSeekLocation);
        setLocationStatus('GPS belum diizinkan. GeoSeek memakai lokasi demo backend Pekanbaru agar data nyata tetap tampil.');
        setIsResolvingLocation(false);
      },
      {
        enableHighAccuracy: true,
        maximumAge: 60000,
        timeout: 8000,
      },
    );
  }, []);

  const recordAction = (message: string, label = activeModule.menuLabel) => {
    setActionStatus(message);
    setActionHistory((previousHistory) => [
      {
        id: `gsk-action-${Date.now()}`,
        moduleKey: activeModule.key,
        label,
        message,
        createdAt: getActionTimestamp(),
      },
      ...previousHistory,
    ].slice(0, 8));
  };

  const publishSmartDraft = () => {
    const newItem = createPublishedItem(smartInput, smartDraft, activeModule.key, resolvedLocation);

    setPublishedItems((previousItems) => [
      newItem,
      ...previousItems.filter((item) => item.name.toLowerCase() !== newItem.name.toLowerCase()),
    ].slice(0, 20));
    setQuery('');
    setRadiusKm((currentRadius) => Math.max(currentRadius, Math.ceil(newItem.distanceKm)));
    recordAction(`Draft “${newItem.name}” dipublikasikan sebagai ${typeLabels[newItem.type]} lokal dan langsung masuk hasil GeoSeek.`, 'Publikasi Smart Input');
  };

  useEffect(() => {
    try {
      const storedItems = window.localStorage.getItem(localPublishedItemsKey);
      const storedHistory = window.localStorage.getItem(localActionHistoryKey);

      if (storedItems) {
        const parsedItems = JSON.parse(storedItems);

        if (Array.isArray(parsedItems)) {
          setPublishedItems(parsedItems);
        } else {
          console.error('Data item lokal GeoSeek bukan array:', parsedItems);
          setActionStatus('Data item lokal tidak valid, data demo tetap digunakan.');
        }
      }

      if (storedHistory) {
        const parsedHistory = JSON.parse(storedHistory);

        if (Array.isArray(parsedHistory)) {
          setActionHistory(parsedHistory);
        } else {
          console.error('Data riwayat GeoSeek bukan array:', parsedHistory);
          setActionStatus('Data riwayat lokal tidak valid, riwayat baru tetap bisa dibuat.');
        }
      }
    } catch (error) {
      console.error('Gagal memuat data lokal GeoSeek:', error);
      setActionStatus('Gagal memuat data lokal GeoSeek. Data demo tetap bisa digunakan.');
    } finally {
      setIsLocalStateReady(true);
    }
  }, []);

  useEffect(() => {
    if (!isLocalStateReady) return;

    try {
      window.localStorage.setItem(localPublishedItemsKey, JSON.stringify(publishedItems));
      window.localStorage.setItem(localActionHistoryKey, JSON.stringify(actionHistory));
    } catch (error) {
      console.error('Gagal menyimpan data lokal GeoSeek:', error);
      setActionStatus('Gagal menyimpan data lokal GeoSeek di browser.');
    }
  }, [actionHistory, isLocalStateReady, publishedItems]);

  useEffect(() => {
    requestCurrentLocation();
  }, [requestCurrentLocation]);

  useEffect(() => {
    let isActive = true;

    const timeoutId = window.setTimeout(async () => {
      setIsLoadingPlaces(true);
      setApiError('');

      try {
        const apiQuery = getApiQuery(query, activeModule.key);
        const response = await axios.get<PublicPlacesResponse>('/public/places', {
          params: {
            q: apiQuery,
            lat: resolvedLocation.latitude,
            lng: resolvedLocation.longitude,
            radiusKm,
            limit: 36,
          },
        });

        if (!isActive) return;

        const rows = Array.isArray(response.data?.rows) ? response.data.rows : [];
        const externalSourceErrors = Array.isArray(response.data?.external_source_errors)
          ? response.data.external_source_errors
          : [];
        const radiusZoneParts = [response.data?.radius_zone?.label, response.data?.radius_zone?.range].filter(Boolean);

        setApiItems(normalizePublicPlaceItems(rows));
        setApiMeta({
          count: Number(response.data?.count || rows.length),
          totalCandidates: Number(response.data?.total_candidates || rows.length),
          radiusZoneLabel: radiusZoneParts.join(' • ') || 'Radius aktif',
          externalSources: Array.isArray(response.data?.external_sources) ? response.data.external_sources : [],
          externalSourceErrors,
          filteredByRadius: Boolean(response.data?.filtered_by_radius),
          expandedForNearest: Boolean(response.data?.expanded_for_nearest),
        });
        setApiError(externalSourceErrors.length ? externalSourceErrors.join(' ') : '');
      } catch (error) {
        if (!isActive) return;

        console.error('Gagal memuat data backend GeoSeek Pro:', error);
        setApiItems([]);
        setApiMeta(emptyApiMeta);
        setApiError('Data backend GeoSeek belum bisa dimuat. UI memakai fallback demo lokal.');
      } finally {
        if (isActive) {
          setIsLoadingPlaces(false);
        }
      }
    }, 350);

    return () => {
      isActive = false;
      window.clearTimeout(timeoutId);
    };
  }, [activeModule.key, query, radiusKm, resolvedLocation.latitude, resolvedLocation.longitude, searchRequestVersion]);

  useEffect(() => {
    setQuery(getDefaultQuery(activeModule.key));
    setRadiusKm(5);
    setActionStatus(`Menu ${activeModule.menuLabel} siap. GeoSeek memuat data backend nyata dan memakai fallback demo jika data sekitar belum tersedia.`);
  }, [activeModule.key, activeModule.menuLabel]);

  const profileName = [currentUser?.firstName, currentUser?.lastName].filter(Boolean).join(' ') || currentUser?.email || 'Pengguna GeoSeek';

  return (
    <>
      <Head>
        <title>{getPageTitle(activeModule.title)}</title>
      </Head>
      <SectionMain>
        <SectionTitleLineWithButton icon={moduleIconMap[activeModule.key] || icon.mdiViewDashboardOutline} title={activeModule.title} main>
          <BaseButton href="/dashboard" color="whiteDark" label="Dashboard" icon={icon.mdiViewDashboardOutline} />
        </SectionTitleLineWithButton>

        <div className="mb-6 grid gap-4 lg:grid-cols-[1.35fr_0.65fr]">
          <CardBox className="overflow-hidden bg-gradient-to-br from-blue-600 via-cyan-600 to-emerald-500 text-white">
            <div className="relative">
              <div className="absolute -right-10 -top-10 h-36 w-36 rounded-full bg-white/10 blur-2xl" />
              <div className="absolute -bottom-12 left-20 h-40 w-40 rounded-full bg-lime-200/10 blur-2xl" />
              <p className="text-sm font-semibold uppercase tracking-[0.35em] text-white/70">GeoSeek Pro Automation</p>
              <h2 className="mt-4 max-w-3xl text-4xl font-black leading-tight md:text-5xl">{activeModule.subtitle}</h2>
              <p className="mt-5 max-w-2xl text-sm leading-6 text-white/85">
                Lokasi aktif: {resolvedLocation.label}. GeoSeek kini mengambil data nyata dari backend `/public/places`,
                memakai GPS browser bila diizinkan, dan tetap punya fallback demo agar pencarian radius, produk, jasa, UMKM, peta, booking, kurir, dan insight bisnis selalu bisa dicoba.
              </p>
              <div className="mt-6 flex flex-wrap gap-3">
                {quickPrompts.slice(0, 4).map((prompt) => (
                  <button
                    key={prompt}
                    type="button"
                    className="rounded-full bg-white/15 px-4 py-2 text-sm font-semibold text-white backdrop-blur transition hover:bg-white/25"
                    onClick={() => setQuery(prompt)}
                  >
                    {prompt}
                  </button>
                ))}
              </div>
            </div>
          </CardBox>

          <CardBox className="bg-white/90 dark:bg-dark-900">
            <p className="text-sm text-gray-500 dark:text-gray-400">Profil aktif</p>
            <h3 className="mt-2 text-2xl font-bold text-gray-900 dark:text-white">{profileName}</h3>
            <div className="mt-4 space-y-3 text-sm text-gray-600 dark:text-gray-300">
              <div className="rounded-2xl bg-blue-50 p-4 dark:bg-blue-900/20">
                Radius aktif <strong>{radiusKm} km</strong> ({activeDistancePriority.label}) dari {resolvedLocation.label}
                <p className="mt-1 text-xs">{resolvedLocation.source === 'browser' ? 'Sumber: GPS browser' : 'Sumber: fallback backend demo'}{resolvedLocation.accuracyMeters ? ` • akurasi ±${resolvedLocation.accuracyMeters} m` : ''}</p>
              </div>
              <div className="rounded-2xl bg-emerald-50 p-4 dark:bg-emerald-900/20">
                {results.length} hasil untuk modul <strong>{activeModule.menuLabel}</strong>
                <p className="mt-1 text-xs">{apiItems.length ? `${apiItems.length} item backend dinormalisasi` : 'Fallback demo lokal aktif'}</p>
              </div>
              <div className="rounded-2xl bg-purple-50 p-4 dark:bg-purple-900/20">
                Kandidat backend <strong>{apiMeta.totalCandidates}</strong> • draft lokal <strong>{publishedItems.length}</strong>
                <p className="mt-1 text-xs">{apiMeta.radiusZoneLabel}</p>
              </div>
              <div className="rounded-2xl bg-orange-50 p-4 dark:bg-orange-900/20">
                Status: {isLoadingPlaces ? 'Memuat data backend GeoSeek...' : actionStatus}
              </div>
            </div>
          </CardBox>
        </div>

        <CardBox className="mb-6 bg-white/90 dark:bg-dark-900">
          <div className="mb-4 flex flex-wrap gap-2">
            {moduleOptions.map((option) => {
              const isActive = option.key === activeModule.key;

              return (
                <Link
                  key={option.key}
                  href={option.href}
                  className={`inline-flex items-center gap-2 rounded-full border px-3 py-2 text-sm font-semibold transition ${
                    isActive
                      ? 'border-blue-600 bg-blue-600 text-white shadow-lg shadow-blue-600/20'
                      : 'border-gray-200 bg-white text-gray-600 hover:border-blue-300 hover:text-blue-600 dark:border-dark-700 dark:bg-dark-800 dark:text-gray-300'
                  }`}
                >
                  <BaseIcon path={option.iconPath} size={16} />
                  {option.label}
                </Link>
              );
            })}
          </div>

          <div className="grid gap-4 xl:grid-cols-[1fr_180px_170px_170px]">
            <label className="block">
              <span className="mb-2 block text-sm font-bold text-gray-700 dark:text-gray-200">Pencarian otomatis</span>
              <input
                value={query}
                onChange={(event) => setQuery(event.target.value)}
                placeholder={activeModule.searchPlaceholder}
                className="h-12 w-full rounded-2xl border border-gray-200 bg-white px-4 text-gray-900 outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-200 dark:border-dark-700 dark:bg-dark-800 dark:text-white"
              />
            </label>
            <label className="block">
              <span className="mb-2 block text-sm font-bold text-gray-700 dark:text-gray-200">Radius</span>
              <select
                value={radiusKm}
                onChange={(event) => setRadiusKm(Number(event.target.value))}
                className="h-12 w-full rounded-2xl border border-gray-200 bg-white px-4 text-gray-900 outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-200 dark:border-dark-700 dark:bg-dark-800 dark:text-white"
              >
                {radiusOptions.map((radius) => {
                  const priority = getDistancePriority(radius);

                  return (
                    <option key={radius} value={radius}>
                      {radius} km — {priority.range} • {priority.label}
                    </option>
                  );
                })}
              </select>
            </label>
            <div className="flex items-end">
              <BaseButton
                color="info"
                label={isLoadingPlaces ? 'Memuat' : 'Jalankan'}
                icon={icon.mdiMagnify}
                className="h-12 w-full"
                onClick={() => {
                  setSearchRequestVersion((version) => version + 1);
                  recordAction(`Pencarian “${query || getApiQuery(query, activeModule.key)}” dikirim ke backend GeoSeek dan diurutkan dengan GeoScore.`, 'Pencarian');
                }}
              />
            </div>
            <div className="flex items-end">
              <BaseButton
                color="success"
                label={isResolvingLocation ? 'GPS...' : 'Gunakan GPS'}
                icon={icon.mdiCrosshairsGps}
                className="h-12 w-full"
                disabled={isResolvingLocation}
                onClick={requestCurrentLocation}
              />
            </div>
          </div>
          <div className="mt-4 grid gap-3 text-sm md:grid-cols-3">
            <div className="rounded-2xl bg-slate-50 p-4 text-gray-600 dark:bg-dark-800 dark:text-gray-300">
              <strong className="text-gray-900 dark:text-white">Lokasi:</strong> {locationStatus}
            </div>
            <div className="rounded-2xl bg-slate-50 p-4 text-gray-600 dark:bg-dark-800 dark:text-gray-300">
              <strong className="text-gray-900 dark:text-white">Data:</strong> {isLoadingPlaces ? 'memuat backend...' : apiItems.length ? `${apiItems.length} item backend aktif` : 'fallback demo aktif'}
            </div>
            <div className="rounded-2xl bg-slate-50 p-4 text-gray-600 dark:bg-dark-800 dark:text-gray-300">
              <strong className="text-gray-900 dark:text-white">Zona:</strong> {apiMeta.radiusZoneLabel}
            </div>
          </div>
          {(apiError || apiMeta.externalSources.length > 0 || apiMeta.expandedForNearest) && (
            <div className="mt-4 rounded-2xl border border-amber-200 bg-amber-50 p-4 text-sm text-amber-800 dark:border-amber-900/50 dark:bg-amber-900/20 dark:text-amber-200">
              {apiError || `Sumber eksternal aktif: ${apiMeta.externalSources.join(', ')}`}
              {apiMeta.expandedForNearest ? ' Radius diperluas otomatis untuk mencari hasil terdekat.' : ''}
            </div>
          )}
        </CardBox>

        <div className="mb-6 grid gap-4 md:grid-cols-2 xl:grid-cols-5">
          <StatCard label="Hasil Prioritas" value={results.length} help="Diurutkan dari jarak terdekat" iconPath={icon.mdiMagnify} />
          <StatCard label="Rata-rata GeoScore" value={insight.averageGeoScore} help="Dari modul aktif" iconPath={icon.mdiChartTimelineVariant} />
          <StatCard label="Promo Aktif" value={insight.promos} help="Siap disebar otomatis" iconPath={icon.mdiTicketPercentOutline} />
          <StatCard label="Booking/Kurir" value={insight.bookingReady + insight.deliveryReady} help="Aksi cepat tersedia" iconPath={icon.mdiCalendar} />
          <StatCard label="Data Backend" value={apiItems.length || 'Demo'} help={apiItems.length ? 'Places + offerings nyata' : 'Fallback lokal'} iconPath={icon.mdiDatabaseSearch} />
        </div>

        <div className="mb-6 grid gap-6 xl:grid-cols-[1fr_0.9fr]">
          <CardBox className="bg-white/90 dark:bg-dark-900">
            <div className="mb-4 flex items-start justify-between gap-4">
              <div>
                <h3 className="text-xl font-bold text-gray-900 dark:text-white">{activeModule.automationTitle}</h3>
                <p className="mt-1 text-sm leading-6 text-gray-600 dark:text-gray-300">{activeModule.automationDescription}</p>
              </div>
              <div className="rounded-2xl bg-blue-50 p-3 text-blue-600 dark:bg-blue-900/30 dark:text-blue-200">
                <BaseIcon path={icon.mdiRobot} size={24} />
              </div>
            </div>
            <BaseButtons type="justify-start" mb="mb-0" className="gap-2" classAddon="mb-2 mr-2">
              {actionSet.map((action) => (
                <BaseButton
                  key={action.label}
                  color={action.color}
                  label={action.label}
                  icon={action.iconPath}
                  onClick={() => recordAction(action.message, action.label)}
                />
              ))}
            </BaseButtons>
            <div className="mt-4 rounded-2xl bg-slate-50 p-4 text-sm text-gray-600 dark:bg-dark-800 dark:text-gray-300">
              <strong className="text-gray-900 dark:text-white">Status otomasi:</strong> {actionStatus}
            </div>
            <div className="mt-4 rounded-2xl border border-gray-200 p-4 dark:border-dark-700">
              <div className="mb-3 flex items-center justify-between gap-3">
                <div>
                  <p className="text-sm font-bold text-gray-900 dark:text-white">Riwayat aksi lokal</p>
                  <p className="text-xs text-gray-500 dark:text-gray-400">Order, booking, dispatch, dan publikasi tersimpan di browser.</p>
                </div>
                <BaseButton
                  color="whiteDark"
                  label="Reset"
                  icon={icon.mdiDeleteOutline}
                  small
                  disabled={!actionHistory.length && !publishedItems.length}
                  onClick={() => {
                    setActionHistory([]);
                    setPublishedItems([]);
                    setActionStatus('Data lokal GeoSeek dibersihkan. Data demo bawaan tetap tersedia.');
                  }}
                />
              </div>
              <div className="space-y-2">
                {actionHistory.length ? actionHistory.slice(0, 4).map((history) => (
                  <div key={history.id} className="rounded-xl bg-gray-50 p-3 text-xs text-gray-600 dark:bg-dark-800 dark:text-gray-300">
                    <div className="flex flex-wrap items-center justify-between gap-2">
                      <span className="font-bold text-gray-900 dark:text-white">{history.label}</span>
                      <span>{history.createdAt}</span>
                    </div>
                    <p className="mt-1">{history.message}</p>
                  </div>
                )) : (
                  <p className="rounded-xl bg-gray-50 p-3 text-xs text-gray-500 dark:bg-dark-800 dark:text-gray-400">
                    Belum ada aksi. Jalankan pencarian, publish draft, checkout, booking, atau kurir.
                  </p>
                )}
              </div>
            </div>
          </CardBox>

          <CardBox className="bg-white/90 dark:bg-dark-900">
            <div className="mb-4 flex items-start justify-between gap-4">
              <div>
                <h3 className="text-xl font-bold text-gray-900 dark:text-white">Smart Input / Auto Input</h3>
                <p className="mt-1 text-sm text-gray-600 dark:text-gray-300">Tulis laporan bebas, sistem membuat draft data terstruktur.</p>
              </div>
              <BaseIcon path={icon.mdiRobot} size={28} className="text-emerald-500" />
            </div>
            <textarea
              value={smartInput}
              onChange={(event) => setSmartInput(event.target.value)}
              className="h-28 w-full rounded-2xl border border-gray-200 bg-white p-4 text-sm text-gray-900 outline-none focus:border-emerald-500 focus:ring-2 focus:ring-emerald-200 dark:border-dark-700 dark:bg-dark-800 dark:text-white"
            />
            <div className="mt-3 flex flex-wrap gap-2">
              {sampleSmartInputs.map((sample, index) => (
                <button
                  key={sample}
                  type="button"
                  className="rounded-full bg-gray-100 px-3 py-1.5 text-xs font-semibold text-gray-600 hover:bg-emerald-100 hover:text-emerald-700 dark:bg-dark-800 dark:text-gray-300"
                  onClick={() => setSmartInput(sample)}
                >
                  Contoh {index + 1}
                </button>
              ))}
            </div>
            <div className="mt-4 grid gap-3 text-sm md:grid-cols-2">
              <div className="rounded-2xl bg-emerald-50 p-4 dark:bg-emerald-900/20">
                <p className="text-xs font-bold uppercase tracking-wider text-emerald-700 dark:text-emerald-200">Bisnis</p>
                <p className="mt-1 font-semibold text-gray-900 dark:text-white">{smartDraft.businessName}</p>
              </div>
              <div className="rounded-2xl bg-blue-50 p-4 dark:bg-blue-900/20">
                <p className="text-xs font-bold uppercase tracking-wider text-blue-700 dark:text-blue-200">Item</p>
                <p className="mt-1 font-semibold text-gray-900 dark:text-white">{smartDraft.itemName}</p>
              </div>
              <div className="rounded-2xl bg-purple-50 p-4 dark:bg-purple-900/20">
                <p className="text-xs font-bold uppercase tracking-wider text-purple-700 dark:text-purple-200">Kategori</p>
                <p className="mt-1 font-semibold text-gray-900 dark:text-white">{smartDraft.category}</p>
              </div>
              <div className="rounded-2xl bg-orange-50 p-4 dark:bg-orange-900/20">
                <p className="text-xs font-bold uppercase tracking-wider text-orange-700 dark:text-orange-200">Harga & Stok</p>
                <p className="mt-1 font-semibold text-gray-900 dark:text-white">{currency(smartDraft.price)} • {smartDraft.stock ?? 'stok belum diisi'}</p>
              </div>
            </div>
            <div className="mt-4 rounded-2xl border border-gray-200 p-4 text-sm text-gray-600 dark:border-dark-700 dark:text-gray-300">
              <p><strong>Lokasi:</strong> {smartDraft.location}</p>
              <p><strong>Promo:</strong> {smartDraft.promo}</p>
              <p><strong>Status:</strong> {smartDraft.status}</p>
              <p><strong>Tag:</strong> {smartDraft.tags.map((tag) => `#${tag}`).join(' ')}</p>
            </div>
            <BaseButton
              color="success"
              label="Publikasikan Draft Simulasi"
              icon={icon.mdiStore}
              className="mt-4 w-full"
              onClick={publishSmartDraft}
            />
          </CardBox>
        </div>

        <div className="mb-6 grid gap-6 xl:grid-cols-[0.9fr_1.1fr]">
          <CardBox className="bg-white/90 dark:bg-dark-900">
            <div className="mb-4 flex items-center justify-between gap-4">
              <div>
                <h3 className="text-xl font-bold text-gray-900 dark:text-white">Peta Radius Simulasi</h3>
                <p className="mt-1 text-sm text-gray-600 dark:text-gray-300">Pin otomatis dari hasil prioritas modul {activeModule.menuLabel}.</p>
              </div>
              <BaseIcon path={icon.mdiCrosshairsGps} size={28} className="text-blue-500" />
            </div>
            <div className="relative h-80 overflow-hidden rounded-3xl bg-gradient-to-br from-sky-100 via-emerald-100 to-lime-100 dark:from-slate-900 dark:via-cyan-950 dark:to-emerald-950">
              <div className="absolute inset-6 rounded-full border-2 border-dashed border-blue-400/50" />
              <div className="absolute left-1/2 top-1/2 z-10 flex -translate-x-1/2 -translate-y-1/2 items-center gap-2 rounded-full bg-blue-600 px-4 py-2 text-xs font-bold text-white shadow-xl">
                <BaseIcon path={icon.mdiCrosshairsGps} size={16} />
                Anda
              </div>
              {mapItems.map((item, index) => (
                <button
                  key={item.id}
                  type="button"
                  style={getMapPosition(item, index, resolvedLocation)}
                  className="absolute z-20 -translate-x-1/2 -translate-y-1/2 rounded-full bg-white p-2 text-blue-600 shadow-lg ring-4 ring-blue-500/20 transition hover:scale-110 dark:bg-dark-800 dark:text-blue-200"
                  title={item.name}
                  onClick={() => recordAction(`Pin “${item.name}” dipilih. Rute demo ${item.distanceKm.toFixed(1)} km siap dibuka.`, 'Rute Pin')}
                >
                  <BaseIcon path={moduleIconMap[activeModule.key] || icon.mdiMapMarker} size={18} />
                </button>
              ))}
            </div>
            <div className="mt-4 grid gap-2 text-sm text-gray-600 dark:text-gray-300">
              {mapItems.slice(0, 4).map((item) => (
                <div key={item.id} className="flex items-center justify-between rounded-2xl bg-gray-50 p-3 dark:bg-dark-800">
                  <span>{item.name}</span>
                  <span className="font-bold text-blue-600 dark:text-blue-300">{item.distanceKm.toFixed(1)} km</span>
                </div>
              ))}
            </div>
          </CardBox>

          <CardBox className="bg-white/90 dark:bg-dark-900">
            <div className="mb-4 flex items-center justify-between gap-4">
              <div>
                <h3 className="text-xl font-bold text-gray-900 dark:text-white">Marketplace, Booking & Kurir</h3>
                <p className="mt-1 text-sm text-gray-600 dark:text-gray-300">Simulasi transaksi lokal dengan keranjang, pembayaran, dan dispatch kurir.</p>
              </div>
              <BaseIcon path={icon.mdiCart} size={28} className="text-emerald-500" />
            </div>
            <div className="space-y-3">
              {cartItems.length ? cartItems.map((item) => (
                <div key={item.id} className="flex items-center justify-between gap-4 rounded-2xl bg-slate-50 p-4 dark:bg-dark-800">
                  <div>
                    <p className="font-semibold text-gray-900 dark:text-white">{item.name}</p>
                    <p className="text-xs text-gray-500 dark:text-gray-400">{item.businessName} • Qty {item.quantity}</p>
                  </div>
                  <p className="font-bold text-gray-900 dark:text-white">{currency(item.price * item.quantity)}</p>
                </div>
              )) : (
                <div className="rounded-2xl bg-slate-50 p-4 text-sm text-gray-500 dark:bg-dark-800 dark:text-gray-300">
                  Belum ada item berharga dalam hasil. Coba perluas radius atau ubah kata kunci.
                </div>
              )}
            </div>
            <div className="mt-4 rounded-2xl border border-gray-200 p-4 text-sm dark:border-dark-700">
              <div className="flex justify-between"><span>Subtotal</span><strong>{currency(checkout.subtotal)}</strong></div>
              <div className="mt-2 flex justify-between"><span>Ongkir lokal</span><strong>{currency(checkout.deliveryFee)}</strong></div>
              <div className="mt-2 flex justify-between"><span>Biaya platform</span><strong>{currency(checkout.platformFee)}</strong></div>
              <div className="mt-2 flex justify-between text-emerald-600"><span>Diskon otomatis</span><strong>-{currency(checkout.discount)}</strong></div>
              <div className="mt-3 flex justify-between border-t border-gray-200 pt-3 text-lg dark:border-dark-700"><span>Total</span><strong>{currency(checkout.total)}</strong></div>
              <p className="mt-3 text-xs text-gray-500 dark:text-gray-400">Metode bayar: {checkout.paymentMethods.join(', ')}</p>
            </div>
            <div className="mt-4 grid gap-3 md:grid-cols-3">
              <BaseButton color="info" label="QRIS" icon={icon.mdiCash} onClick={() => recordAction('Pembayaran QRIS simulasi siap dibuat.', 'QRIS')} />
              <BaseButton color="success" label="Booking" icon={icon.mdiCalendar} onClick={() => recordAction('Draft booking otomatis berhasil dibuat.', 'Booking')} />
              <BaseButton color="warning" label="Kurir" icon={icon.mdiTruck} onClick={() => recordAction('Kurir lokal terdekat berhasil dipilih.', 'Kurir')} />
            </div>
          </CardBox>
        </div>

        <CardBox className="mb-6 bg-white/90 dark:bg-dark-900">
          <div className="mb-4 flex items-center justify-between gap-4">
            <div>
              <h3 className="text-xl font-bold text-gray-900 dark:text-white">Insight Dashboard Bisnis</h3>
              <p className="mt-1 text-sm text-gray-600 dark:text-gray-300">Ringkasan otomatis untuk UMKM dan operator GeoSeek.</p>
            </div>
            <BaseIcon path={icon.mdiFinance} size={28} className="text-purple-500" />
          </div>
          <div className="grid gap-4 md:grid-cols-3 xl:grid-cols-6">
            <div className="rounded-2xl bg-blue-50 p-4 dark:bg-blue-900/20"><p className="text-xs text-blue-700 dark:text-blue-200">Produk</p><p className="text-2xl font-bold">{insight.products}</p></div>
            <div className="rounded-2xl bg-cyan-50 p-4 dark:bg-cyan-900/20"><p className="text-xs text-cyan-700 dark:text-cyan-200">Jasa</p><p className="text-2xl font-bold">{insight.services}</p></div>
            <div className="rounded-2xl bg-orange-50 p-4 dark:bg-orange-900/20"><p className="text-xs text-orange-700 dark:text-orange-200">Promo</p><p className="text-2xl font-bold">{insight.promos}</p></div>
            <div className="rounded-2xl bg-red-50 p-4 dark:bg-red-900/20"><p className="text-xs text-red-700 dark:text-red-200">Stok Rendah</p><p className="text-2xl font-bold">{insight.lowStock}</p></div>
            <div className="rounded-2xl bg-emerald-50 p-4 dark:bg-emerald-900/20"><p className="text-xs text-emerald-700 dark:text-emerald-200">Booking</p><p className="text-2xl font-bold">{insight.bookingReady}</p></div>
            <div className="rounded-2xl bg-lime-50 p-4 dark:bg-lime-900/20"><p className="text-xs text-lime-700 dark:text-lime-200">Kurir</p><p className="text-2xl font-bold">{insight.deliveryReady}</p></div>
          </div>
          <div className="mt-4 grid gap-3 md:grid-cols-2">
            {insight.recommendations.map((recommendation) => (
              <div key={recommendation} className="rounded-2xl border border-gray-200 p-4 text-sm text-gray-600 dark:border-dark-700 dark:text-gray-300">
                ✓ {recommendation}
              </div>
            ))}
          </div>
        </CardBox>

        <div className="mb-4 flex items-center justify-between gap-4">
          <div>
            <h3 className="text-2xl font-bold text-gray-900 dark:text-white">Hasil {activeModule.menuLabel}</h3>
            <p className="mt-1 text-sm text-gray-600 dark:text-gray-300">
              {activeModule.emptyHint} Sumber data: {hasBackendItemsForModule ? 'backend GeoSeek + draft lokal' : 'fallback demo lokal'}.
            </p>
          </div>
          <span className="rounded-full bg-gray-100 px-4 py-2 text-sm font-bold text-gray-600 dark:bg-dark-800 dark:text-gray-300">
            {results.length} hasil
          </span>
        </div>

        <div className="space-y-5">
          {isLoadingPlaces ? (
            <CardBox className="bg-white/90 text-center dark:bg-dark-900">
              <BaseIcon path={icon.mdiDatabaseSearch} size={42} className="mx-auto text-blue-500" />
              <h3 className="mt-4 text-xl font-bold text-gray-900 dark:text-white">Memuat data GeoSeek nyata...</h3>
              <p className="mt-2 text-sm text-gray-500 dark:text-gray-400">Mengambil places dan offerings dari backend berdasarkan lokasi, radius, dan modul aktif.</p>
            </CardBox>
          ) : results.length ? results.map((item) => (
            <ResultCard key={item.id} item={item} moduleKey={activeModule.key} onAction={(message) => recordAction(message, 'Aksi Item')} />
          )) : (
            <CardBox className="bg-white/90 text-center dark:bg-dark-900">
              <BaseIcon path={icon.mdiMagnify} size={42} className="mx-auto text-gray-400" />
              <h3 className="mt-4 text-xl font-bold text-gray-900 dark:text-white">Tidak ada hasil di radius ini</h3>
              <p className="mt-2 text-sm text-gray-500 dark:text-gray-400">Coba ubah kata kunci, izinkan GPS, atau perluas radius pencarian.</p>
              <BaseButton color="info" label="Perluas ke 20 km" className="mt-4" onClick={() => setRadiusKm(20)} />
            </CardBox>
          )}
        </div>
      </SectionMain>
    </>
  );
}
