'use client';

import { useState, useEffect, useMemo } from 'react';
import Link from 'next/link';
import { useTranslations } from 'next-intl';
import { ScrapeResult } from './SearchSection';
import { useAuthStore } from '@/store/authStore';
import { type Country } from '@/lib/countries';

function parsePrice(price: string | undefined): number {
  if (!price || price === 'N/A') return Infinity;
  const num = parseFloat(price.replace(/[^0-9.]/g, ''));
  return isNaN(num) ? Infinity : num;
}

function AnimatedPriceDisplay({
  lowestPrice,
  highestPrice,
  currency,
  description,
  countryName,
  showCountry,
}: {
  lowestPrice: number;
  highestPrice: number;
  currency: string;
  description?: string;
  countryName: string;
  showCountry: boolean;
}) {
  const t = useTranslations('results');
  const [display, setDisplay] = useState(highestPrice);
  const [done, setDone] = useState(false);

  useEffect(() => {
    const DURATION = 1500;
    const startTime = performance.now();
    let raf: number;

    const animate = (now: number) => {
      const elapsed = now - startTime;
      const progress = Math.min(elapsed / DURATION, 1);
      setDisplay(highestPrice - (highestPrice - lowestPrice) * progress);

      if (progress < 1) {
        raf = requestAnimationFrame(animate);
      } else {
        setDisplay(lowestPrice);
        setDone(true);
      }
    };

    raf = requestAnimationFrame(animate);
    return () => cancelAnimationFrame(raf);
  }, [highestPrice, lowestPrice]);

  const savings = highestPrice - lowestPrice;

  return (
    <div className="space-y-2">
      <div className="flex items-baseline gap-2">
        <span
          className={`text-2xl font-bold tabular-nums transition-colors duration-500 ${
            done ? 'text-green-700' : 'text-gray-900'
          }`}
        >
          {display.toFixed(2)}
        </span>
        <span className="text-sm text-gray-500">{currency}</span>
        <span className="text-xs text-gray-400">desktop</span>
      </div>
      {description && <p className="text-xs text-gray-500">{description}</p>}
      {done && savings > 0.01 && (
        <div className="mt-2 flex items-start gap-2 px-3 py-2.5 bg-green-50 rounded-lg border border-green-200">
          <span className="text-base leading-tight shrink-0">💰</span>
          <p className="text-sm text-green-700 font-medium leading-snug">
            {showCountry ? (
              t('savingsMessage', { amount: savings.toFixed(2), currency, country: countryName })
            ) : (
              <>
                You can save {savings.toFixed(2)} {currency} by booking from{' '}
                <Link href="/pricing" className="text-brand-purple hover:underline font-semibold">
                  a cheaper region
                </Link>
              </>
            )}
          </p>
        </div>
      )}
    </div>
  );
}

interface Props {
  results: ScrapeResult[];
}

function TeaserCard({ hasGap }: { hasGap: boolean }) {
  const t = useTranslations('results');
  return (
    <div className="border-2 border-brand-purple rounded-xl p-5 bg-white">
      {hasGap ? (
        <>
          <div className="flex items-center gap-2 mb-2">
            <h3 className="text-base font-bold text-gray-900">{t('teaserHasGap.heading')}</h3>
          </div>
          <p className="text-sm text-gray-500 mb-4 leading-relaxed">
            {t('teaserHasGap.body')}
          </p>
        </>
      ) : (
        <>
          <div className="flex items-center gap-2 mb-2">
            <h3 className="text-base font-bold text-gray-900">{t('teaserNoGap.heading')}</h3>
          </div>
          <p className="text-sm text-gray-500 mb-4 leading-relaxed">
            {t('teaserNoGap.body')}
          </p>
        </>
      )}
      <div className="flex gap-2">
        <Link
          href="/signin?mode=register"
          className="flex-1 bg-brand-purple text-white text-sm font-medium py-2 rounded-lg text-center hover:bg-purple-700 transition-colors"
        >
          {hasGap ? t('teaserHasGap.ctaRegister') : t('teaserNoGap.ctaRegister')}
        </Link>
        <Link
          href="/signin"
          className="flex-1 border border-gray-300 text-gray-700 text-sm font-medium py-2 rounded-lg text-center hover:border-gray-400 transition-colors"
        >
          {hasGap ? t('teaserHasGap.ctaSignIn') : t('teaserNoGap.ctaSignIn')}
        </Link>
      </div>
    </div>
  );
}

function UpgradeCard({ plan, limit }: { plan: string; limit: number }) {
  const t = useTranslations('results');
  return (
    <div className="border-2 border-amber-300 bg-amber-50 rounded-xl p-5">
      <div className="flex items-center gap-2 mb-2">
        <h3 className="text-base font-bold text-gray-900">{t('limitReached.heading')}</h3>
      </div>
      <p className="text-sm text-gray-600 mb-1">
        {t('limitReached.body', { limit, plan })}
      </p>
      <p className="text-sm text-gray-500 mb-4">{t('limitReached.subBody')}</p>
      <Link
        href="/pricing"
        className="inline-flex items-center gap-1.5 bg-brand-purple text-white text-sm font-medium px-4 py-2 rounded-lg hover:bg-purple-700 transition-colors"
      >
        {t('limitReached.cta')}
        <svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
          <path strokeLinecap="round" strokeLinejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3" />
        </svg>
      </Link>
    </div>
  );
}

function SkeletonCard() {
  return (
    <div className="border-2 border-purple-200 rounded-xl p-5 animate-pulse">
      <div className="h-3 bg-purple-100 rounded w-1/3 mb-3" />
      <div className="h-6 bg-purple-100 rounded w-1/2 mb-2" />
      <div className="h-3 bg-purple-50 rounded w-2/3 mb-4" />
      <div className="h-3 bg-purple-50 rounded w-1/2" />
    </div>
  );
}

// ── World Map Dots ──────────────────────────────────────────────────────────
const MAP_W = 700;
const MAP_H = 320;
const LNG_STEP = 6;
const LAT_STEP = 5;
const HIGHLIGHT_R = 44; // SVG px — roughly 20° of arc

// Simplified land regions [minLng, maxLng, minLat, maxLat]
const LAND_REGIONS: [number, number, number, number][] = [
  [-168, -140,  55,  72],  // Alaska
  [-140,  -52,  43,  75],  // Canada
  [-125,  -65,  25,  50],  // Continental US
  [-118,  -85,  14,  32],  // Mexico
  [ -92,  -75,   7,  22],  // Central America
  [ -58,  -17,  60,  84],  // Greenland
  // South America — 6 latitude bands to approximate tapered shape
  [ -82,  -61,   5,  12],  // Colombia + Venezuela (narrow cap)
  [ -80,  -51,   0,   5],  // Guyana coast
  [ -82,  -34, -15,   0],  // Wide Amazon + NE Brazil bulge (widest)
  [ -76,  -34, -30, -15],  // Central + SE Brazil
  [ -73,  -50, -45, -30],  // Argentina + Uruguay (narrowing)
  [ -76,  -64, -58, -45],  // Patagonia (narrow southern tip)
  [ -12,   35,  35,  72],  // Europe
  [ -11,    3,  49,  61],  // UK + Ireland
  [  14,   32,  55,  72],  // Scandinavia
  // Africa — 7 latitude bands to approximate tapered shape
  [ -18,   37,  17,  37],  // N. Africa coast (Morocco → Egypt)
  [ -18,   50,   5,  17],  // Sahel + W. Africa + Horn of Africa (widest)
  [ -18,   42,   0,   5],  // W. equatorial Africa (Cameroon, Congo)
  [   8,   42,  -8,   0],  // Congo basin (western edge narrows)
  [  12,   40, -20,  -8],  // Central / SE Africa (Tanzania, Zambia)
  [  16,   36, -36, -20],  // Southern Africa (tapered tip)
  [  40,   50, -26, -12],  // Madagascar
  [  28,   63,  12,  42],  // Middle East + Turkey
  [  32,   65,  47,  74],  // W. Russia
  [  60,  180,  47,  74],  // E. Russia / Siberia
  [  60,   98,   8,  50],  // S. + Central Asia (India, Iran, Pakistan)
  [  98,  145,  18,  54],  // E. Asia (China, Korea, Japan)
  [  92,  109,   4,  28],  // SE Asia mainland
  [  94,  142, -11,   5],  // Indonesia + Malaysia
  [ 112,  155, -44, -10],  // Australia
  [ 166,  178, -47, -34],  // New Zealand
];

interface MapDot { x: number; y: number }

// Pre-compute all land dots once at module level
const MAP_DOTS: MapDot[] = (() => {
  const isLand = (lat: number, lng: number) =>
    LAND_REGIONS.some(([mnL, mxL, mnA, mxA]) => lng >= mnL && lng <= mxL && lat >= mnA && lat <= mxA);
  const dots: MapDot[] = [];
  for (let lat = 80; lat >= -55; lat -= LAT_STEP) {
    for (let lng = -175; lng <= 180; lng += LNG_STEP) {
      if (isLand(lat, lng)) {
        dots.push({
          x: Math.round(((lng + 180) / 360) * MAP_W),
          y: Math.round(((90 - lat) / 180) * MAP_H),
        });
      }
    }
  }
  return dots;
})();

// Approximate country centres [lat, lng]
const COUNTRY_COORDS: Record<string, [number, number]> = {
  IND: [22,  78],  IDN: [-5, 120],  TUR: [39,  35],
  BRA: [-15,-51],  ARG: [-38,-64],  SRB: [44,  21],
  ALB: [41,  20],  THA: [15, 101],  VNM: [16, 108],
  MEX: [23,-103],  MYS: [ 4, 102],  USA: [38, -97],
  GBR: [55,  -3],  FRA: [46,   2],  DEU: [51,  10],
  NOR: [65,  15],  NLD: [52,   5],  SWE: [62,  18],
  ITA: [43,  12],  ESP: [40,  -4],  AUS: [-25,134],
  CAN: [57,-106],  JPN: [36, 138],  ARE: [24,  54],
  SGP: [ 1, 104],  CHE: [47,   8],  AUT: [47,  14],
  BEL: [51,   4],  DNK: [56,  10],  FIN: [62,  26],
  NZL: [-42,173],  POL: [52,  20],  CZE: [50,  15],
  HUN: [47,  19],  ROU: [46,  25],  BGR: [43,  25],
  RUS: [60, 100],  CHN: [35, 105],  KOR: [37, 128],
  SAU: [24,  45],  ZAF: [-30, 26],  GRC: [39,  22],
  PRT: [39,  -8],  UKR: [49,  32],  PHL: [13, 122],
};

// Pure render — no memo. CheckingCard (unmemoized) drives re-renders on every
// markDone call, so the map always reflects the latest done state.
function WorldMapDots({ activeDots }: { activeDots: Set<number> }) {
  return (
    <svg
      viewBox={`0 0 ${MAP_W} ${MAP_H}`}
      className="w-full"
      style={{ height: 130 }}
      aria-hidden="true"
    >
      {MAP_DOTS.map((d, i) => (
        <circle
          key={i}
          cx={d.x}
          cy={d.y}
          r={2}
          style={{
            fill: activeDots.has(i) ? '#7c3aed' : '#9ca3af',
            transition: 'fill 0.5s ease',
          }}
        />
      ))}
    </svg>
  );
}
// ── End World Map Dots ──────────────────────────────────────────────────────

function CheckingCard({ progress }: { progress: { country: Country; done: boolean }[] }) {
  const t = useTranslations('results');
  // Compute active dot indices here so the map updates on every render of
  // CheckingCard (which is never memoized → re-renders on every markDone call).
  const allDone = progress.length > 0 && progress.every(p => p.done);
  const activeDots = useMemo(() => {
    if (allDone) return new Set(MAP_DOTS.map((_, i) => i));
    const hotspots = progress
      .filter(p => p.done)
      .flatMap(({ country }) => {
        const c = COUNTRY_COORDS[country.code];
        if (!c) return [];
        return [{ x: ((c[1] + 180) / 360) * MAP_W, y: ((90 - c[0]) / 180) * MAP_H }];
      });
    const set = new Set<number>();
    MAP_DOTS.forEach((dot, i) => {
      if (hotspots.some(h => Math.hypot(dot.x - h.x, dot.y - h.y) < HIGHLIGHT_R)) set.add(i);
    });
    return set;
  }, [progress, allDone]);

  return (
    <div className="border-2 border-purple-200 rounded-xl p-5 bg-white">
      <p className="text-xs font-semibold text-gray-400 uppercase tracking-wide mb-2">{t('checkingFrom')}</p>
      <div className="mb-4 -mx-1">
        <WorldMapDots activeDots={activeDots} />
      </div>
      <ul className="grid grid-cols-3 gap-x-3 gap-y-2">
        {progress.map(({ country, done }) => (
          <li key={country.code} className="flex items-center gap-1.5 text-sm min-w-0">
            <span className="shrink-0">{country.flag}</span>
            <span className={`truncate ${done ? 'text-gray-700' : 'text-gray-400'}`}>{country.name}</span>
            <span className="shrink-0 ml-auto">
              {done ? (
                <span className="text-green-500 font-bold">✓</span>
              ) : (
                <svg className="w-3 h-3 text-purple-400 animate-spin" fill="none" viewBox="0 0 24 24">
                  <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
                  <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
                </svg>
              )}
            </span>
          </li>
        ))}
      </ul>
    </div>
  );
}

function ResultCard({ result, showCountry }: { result: ScrapeResult; showCountry: boolean }) {
  const t = useTranslations('results');

  if (result.loading) {
    return result.checkingProgress
      ? <CheckingCard progress={result.checkingProgress} />
      : <SkeletonCard />;
  }
  if (result.teaser) return <TeaserCard hasGap={result.teaser.hasGap} />;
  if (result.limitReached) return <UpgradeCard plan={result.limitReached.plan} limit={result.limitReached.limit} />;

  if (result.error) {
    return (
      <div className="border-2 border-red-200 bg-red-50 rounded-xl p-5">
        {showCountry && (
          <div className="flex items-center gap-2 mb-2">
            <span>{result.country.flag}</span>
            <span className="text-sm font-medium text-gray-700">{result.country.name}</span>
          </div>
        )}
        <p className="text-sm text-red-600">{result.error}</p>
        <p className="text-xs text-gray-400 mt-1 truncate">{result.url}</p>
      </div>
    );
  }

  if (!result.data) {
    return (
      <div className="border-2 border-purple-200 rounded-xl p-5 min-h-[120px]" />
    );
  }

  const { data, country } = result;
  const hasPrice = data.desktop?.price && data.desktop.price !== 'N/A';
  const hasMobile = data.mobile?.price && data.mobile.price !== 'N/A';

  return (
    <div className="border-2 border-purple-400 rounded-xl p-5 bg-white hover:shadow-md transition-shadow">
      <div className="flex items-center justify-between mb-3">
        {showCountry ? (
          <div className="flex items-center gap-2">
            <span className="text-lg">{country.flag}</span>
            <span className="text-sm font-medium text-gray-600">{country.name}</span>
          </div>
        ) : (
          <div className="flex items-center gap-1.5">
            <svg className="w-3.5 h-3.5 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
              <path strokeLinecap="round" strokeLinejoin="round" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
            </svg>
            <Link href="/pricing" className="text-xs text-brand-purple hover:underline font-medium">
              {t('upgradeRevealCountry')}
            </Link>
          </div>
        )}
        {data.provider && (
          <span className="text-xs bg-purple-50 text-brand-purple px-2 py-0.5 rounded-full font-medium capitalize">
            {data.provider}
          </span>
        )}
      </div>

      {hasPrice ? (
        <div className="space-y-2">
          {result.highestResult && parsePrice(result.highestResult.price) > parsePrice(data.desktop.price) + 0.01 ? (
            <AnimatedPriceDisplay
              lowestPrice={parsePrice(data.desktop.price)}
              highestPrice={parsePrice(result.highestResult.price)}
              currency={data.desktop.currency}
              description={data.desktop.description}
              countryName={country.name}
              showCountry={showCountry}
            />
          ) : (
            <>
              <div className="flex items-baseline gap-2">
                <span className="text-2xl font-bold text-gray-900">{data.desktop.price}</span>
                <span className="text-sm text-gray-500">{data.desktop.currency}</span>
                <span className="text-xs text-gray-400">desktop</span>
              </div>
              {data.desktop.description && (
                <p className="text-xs text-gray-500">{data.desktop.description}</p>
              )}
            </>
          )}
          {hasMobile && (
            <div className="flex items-baseline gap-2 pt-1 border-t border-gray-100">
              <span className="text-lg font-semibold text-gray-700">{data.mobile.price}</span>
              <span className="text-sm text-gray-400">{data.mobile.currency}</span>
              <span className="text-xs text-gray-400">📱 mobile</span>
            </div>
          )}
          {data.reserveUrl && (
            <a
              href={data.reserveUrl}
              target="_blank"
              rel="noopener noreferrer"
              className="inline-block mt-3 text-xs text-brand-purple hover:underline"
            >
              Book at this price →
            </a>
          )}
        </div>
      ) : (
        <div className="flex items-center gap-2 text-amber-500 text-sm">
          <span>⚠</span>
          <span>Price not found</span>
        </div>
      )}

      <p className="text-xs text-gray-300 mt-3 truncate">{result.url}</p>
    </div>
  );
}

export default function SearchResults({ results }: Props) {
  const { user } = useAuthStore();
  const showCountry = (user?.plan ?? 'free') !== 'free';

  if (results.length === 0) {
    return (
      <section className="py-4 pb-[calc(2rem+50px)] bg-white hidden">
        <div className="max-w-6xl mx-auto px-6">
          <p className="text-sm text-gray-400 mb-4">Search results</p>
          <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
            {[0, 1, 2].map(i => (
              <div key={i} className="border-2 border-purple-200 rounded-xl min-h-[120px]" />
            ))}
          </div>
        </div>
      </section>
    );
  }

  return (
    <section className="py-4 pb-[calc(2rem+50px)] bg-white">
      <div className="max-w-6xl mx-auto px-6">
        <p className="text-sm text-gray-500 mb-4">Search results</p>
        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
          {results.map(result => (
            <div
              key={`${result.slotId}-${result.country.code}`}
              className={result.loading && result.checkingProgress ? 'col-span-full' : ''}
            >
              <ResultCard result={result} showCountry={showCountry} />
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}
