"use client";

import { useState } from "react";
import type { CategoryId } from "@transportationer/shared";
import { CATEGORIES } from "@transportationer/shared";

type Weights = Record<CategoryId, number>;
export type OverlayMode = "isochrone" | "relative";

export interface SubcategoryDetail {
  subcategory: string;
  name: string | null;
  distanceM: number | null;
  travelTimeS: number | null;
}

export interface LocationScoreData {
  lat: number;
  lng: number;
  categoryScores: Record<CategoryId, number>;
  distancesM: Partial<Record<CategoryId, number>>;
  travelTimesS: Partial<Record<CategoryId, number>>;
  subcategoryDetails?: Partial<Record<CategoryId, SubcategoryDetail[]>>;
}

const SUBCATEGORY_LABELS: Record<string, string> = {
  // service_trade
  supermarket: "Supermarket",
  pharmacy: "Pharmacy",
  convenience: "Convenience store",
  restaurant: "Restaurant",
  cafe: "Café",
  bank: "Bank",
  atm: "ATM",
  market: "Market",
  laundry: "Laundry",
  post_office: "Post office",
  // transport
  train_station: "Train station",
  metro: "Metro",
  tram_stop: "Tram stop",
  bus_stop: "Bus stop",
  stop: "Transit stop",
  ferry: "Ferry",
  bike_share: "Bike share",
  car_share: "Car share",
  // work_school
  school: "School",
  driving_school: "Driving school",
  kindergarten: "Kindergarten",
  university: "University",
  coworking: "Coworking",
  office: "Office",
  // culture_community
  hospital: "Hospital",
  clinic: "Clinic",
  library: "Library",
  community_center: "Community center",
  social_services: "Social services",
  theatre: "Theatre",
  place_of_worship: "Place of worship",
  government: "Government",
  museum: "Museum",
  // recreation
  park: "Park",
  playground: "Playground",
  sports_facility: "Sports facility",
  gym: "Gym",
  green_space: "Green space",
  swimming_pool: "Swimming pool",
};

export function compositeScore(
  scores: Record<CategoryId, number>,
  weights: Weights,
): number {
  const entries = Object.entries(weights) as [CategoryId, number][];
  const total = entries.reduce((s, [, w]) => s + w, 0);
  if (total === 0) return 0;
  return entries.reduce((s, [cat, w]) => s + (scores[cat] ?? 0) * w, 0) / total;
}

function grade(score: number): string {
  if (score >= 0.8) return "A";
  if (score >= 0.65) return "B";
  if (score >= 0.5) return "C";
  if (score >= 0.35) return "D";
  return "F";
}

function gradeColor(g: string): string {
  const map: Record<string, string> = {
    A: "text-green-600",
    B: "text-green-500",
    C: "text-yellow-500",
    D: "text-orange-500",
    F: "text-red-600",
  };
  return map[g] ?? "text-gray-600";
}

function formatDist(m: number): string {
  return m >= 1000 ? `${(m / 1000).toFixed(1)} km` : `${Math.round(m)} m`;
}

function formatTime(s: number): string {
  const min = Math.round(s / 60);
  return min < 1 ? "<1 min" : `${min} min`;
}

export function LocationScorePanel({
  data,
  weights,
  address,
  estateValue,
  estatePercentile,
  estateScorePercentile,
  overlayMode,
  isochroneLoading,
  showPois,
  onTogglePois,
  poiCount,
  onOverlayModeChange,
  onClose,
}: {
  data: LocationScoreData;
  weights: Weights;
  address?: string;
  estateValue?: number | null;
  /** % of zones within 5 km with a lower value (0–100). */
  estatePercentile?: number | null;
  /** % of zones with similar accessibility score that have a lower value (0–100). */
  estateScorePercentile?: number | null;
  overlayMode: OverlayMode;
  isochroneLoading: boolean;
  showPois: boolean;
  onTogglePois: () => void;
  poiCount: number;
  onOverlayModeChange: (mode: OverlayMode) => void;
  onClose: () => void;
}) {
  const [expandedCategory, setExpandedCategory] = useState<CategoryId | null>(null);
  const composite = compositeScore(data.categoryScores, weights);
  const g = grade(composite);

  return (
    <div className="absolute bottom-8 right-4 z-20 bg-white rounded-xl shadow-lg border border-gray-100 w-72 p-4">
      {/* Header: grade + address + close */}
      <div className="flex items-start justify-between mb-3">
        <div>
          <div className={`text-5xl font-bold leading-none ${gradeColor(g)}`}>{g}</div>
          <div className="text-xs text-gray-400 mt-1">{Math.round(composite * 100)} / 100</div>
          {estateValue != null && (
            <div className="mt-1.5">
              <div className="inline-flex items-center gap-1 px-1.5 py-0.5 rounded bg-amber-50 border border-amber-200">
                <span className="text-amber-700 font-semibold text-xs">{estateValue.toLocaleString("de-DE")} €/m²</span>
                <span className="text-amber-400 text-[10px]">land value</span>
              </div>
              {(estatePercentile != null || estateScorePercentile != null) && (
                <div className="mt-1 space-y-0.5 pl-0.5">
                  {estatePercentile != null && (
                    <div className="text-[10px] text-amber-600">
                      Pricier than {estatePercentile}% of zones · 5 km radius
                    </div>
                  )}
                  {estateScorePercentile != null && (
                    <div className="text-[10px] text-amber-500">
                      Pricier than {estateScorePercentile}% · similar accessibility
                    </div>
                  )}
                </div>
              )}
            </div>
          )}
          {address && (
            <div className="text-xs text-gray-400 mt-1 truncate max-w-[200px]" title={address}>
              {address}
            </div>
          )}
        </div>
        <button
          onClick={onClose}
          className="text-gray-300 hover:text-gray-500 text-xl leading-none mt-0.5"
          aria-label="Close"
        >
          ×
        </button>
      </div>

      {/* Overlay mode toggle */}
      <div className="flex rounded-lg border border-gray-200 overflow-hidden text-xs mb-3.5">
        <button
          className={`flex-1 py-1.5 transition-colors ${
            overlayMode === "isochrone"
              ? "bg-blue-600 text-white font-medium"
              : "text-gray-500 hover:bg-gray-50"
          }`}
          onClick={() => onOverlayModeChange("isochrone")}
        >
          {isochroneLoading && overlayMode === "isochrone" ? "Loading…" : "Isochrone"}
        </button>
        <button
          className={`flex-1 py-1.5 transition-colors ${
            overlayMode === "relative"
              ? "bg-blue-600 text-white font-medium"
              : "text-gray-500 hover:bg-gray-50"
          }`}
          onClick={() => onOverlayModeChange("relative")}
        >
          Relative
        </button>
      </div>

      {/* POI pin toggle */}
      {poiCount > 0 && (
        <div className="mb-3">
          <button
            onClick={onTogglePois}
            className={`w-full py-1.5 rounded-lg text-xs font-medium transition-colors ${
              showPois
                ? "bg-blue-100 text-blue-700 hover:bg-blue-200"
                : "bg-gray-100 text-gray-500 hover:bg-gray-200"
            }`}
          >
            {showPois ? `Hide ${poiCount} POIs` : `Show ${poiCount} POIs`}
          </button>
        </div>
      )}

      {/* Per-category score bars */}
      <div className="space-y-2.5">
        {CATEGORIES.map((cat) => {
          const score = data.categoryScores[cat.id] ?? 0;
          const dist = data.distancesM[cat.id];
          const time = data.travelTimesS[cat.id];
          const barColor =
            score >= 0.65 ? "#22c55e" : score >= 0.4 ? "#eab308" : "#ef4444";
          const subcats = data.subcategoryDetails?.[cat.id];
          const isExpanded = expandedCategory === cat.id;
          const hasDetails = subcats && subcats.length > 0;
          return (
            <div key={cat.id}>
              <button
                className="w-full text-left"
                onClick={() => setExpandedCategory(isExpanded ? null : cat.id)}
                disabled={!hasDetails}
              >
                <div className="flex items-center justify-between text-xs mb-1">
                  <span className="text-gray-600 font-medium flex items-center gap-1">
                    {cat.label}
                    {hasDetails && (
                      <span className="text-gray-300 text-[9px]">{isExpanded ? "▲" : "▼"}</span>
                    )}
                  </span>
                  <span className="text-gray-400 text-[10px]">
                    {dist != null && formatDist(dist)}
                    {dist != null && time != null && " · "}
                    {time != null && formatTime(time)}
                  </span>
                </div>
                <div className="h-1.5 bg-gray-100 rounded-full overflow-hidden">
                  <div
                    className="h-full rounded-full transition-all duration-300"
                    style={{ width: `${Math.round(score * 100)}%`, backgroundColor: barColor }}
                  />
                </div>
              </button>
              {isExpanded && hasDetails && (
                <div className="mt-1.5 space-y-0.5 pl-1">
                  {subcats.map((d) => (
                    <div
                      key={d.subcategory}
                      className="flex items-center justify-between text-[10px] text-gray-500 py-0.5"
                    >
                      <span className="truncate max-w-[130px]" title={d.name ?? undefined}>
                        <span className="text-gray-400 mr-1">
                          {SUBCATEGORY_LABELS[d.subcategory] ?? d.subcategory}
                        </span>
                        {d.name && (
                          <span className="text-gray-600 font-medium">{d.name}</span>
                        )}
                      </span>
                      <span className="text-gray-400 shrink-0 ml-1">
                        {d.distanceM != null && formatDist(d.distanceM)}
                        {d.distanceM != null && d.travelTimeS != null && " · "}
                        {d.travelTimeS != null && formatTime(d.travelTimeS)}
                      </span>
                    </div>
                  ))}
                </div>
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}
