import React, { useEffect, useRef, useState } from "react";
import "maplibre-gl/dist/maplibre-gl.css";
import "../../styles/map.css";
import "../../styles/mapMarkers.css";
import "../../styles/posts.css";
import "../../styles/filters.css";

import { createPost } from "../../api/client";
import {
  FILTER_MAIN_CATEGORIES,
  FILTER_CATEGORY_MAP,
  CREATE_CATEGORY_MAP,
} from "./mapConfig";
import { useMapCore } from "./useMapCore";
import { useUserPosition } from "./useUserPosition";
import { usePostsEngine } from "./usePostsEngine";
import { useAuth } from "../../auth/AuthContext";
import FilterButtons from "../Filters/FilterButtons";
import TimeFilterButtons from "../Filters/TimeFilterButtons";

export default function MapView({
  theme = "dark",
  onPostsState,
  selectedPost,
  onSelectPost,
}) {
  const { authenticated, username, token, needsEmailVerification } = useAuth();

  const { containerRef, mapRef, markersRef, expandedElRef, viewParams, hasLastView } =
    useMapCore(theme);

  const [mainFilter, setMainFilter] = useState("All");
  const TIME_FILTER_KEY = "sociowire:timeFilter";
  const [timeFilter, setTimeFilter] = useState(() => {
    try {
      const v = localStorage.getItem(TIME_FILTER_KEY);
      const ok = ["NOW", "TODAY", "RECENT", "PAST"].includes(v);
      return ok ? v : "TODAY";
    } catch {
      return "TODAY";
    }
  });
  const [subFilter, setSubFilter] = useState("All");

  useEffect(() => {
    try {
      localStorage.setItem(TIME_FILTER_KEY, timeFilter);
    } catch {}
  }, [timeFilter]);

  const stageRef = useRef(null);
  const [showSubcats, setShowSubcats] = useState(true);

  const userPosition = useUserPosition(mapRef, hasLastView);

  const [searchQuery, setSearchQuery] = useState("");

  const { status, visiblePosts, loadingPosts, loadError, handleIncomingPost } =
    usePostsEngine({
      theme,
      mapRef,
      viewParams,
      mainFilter,
      subFilter,
      timeFilter,
      searchQuery,
      markersRef,
      expandedElRef,
    });

  const [isCreating, setIsCreating] = useState(false);
  const [draftTitle, setDraftTitle] = useState("");
  const [draftBody, setDraftBody] = useState("");
  const [draftCategory, setDraftCategory] = useState("News");
  const [draftSubCategory, setDraftSubCategory] = useState(
    CREATE_CATEGORY_MAP.News[0]
  );
  const [draftCoords, setDraftCoords] = useState(null);
  const [isSaving, setIsSaving] = useState(false);
  const [saveError, setSaveError] = useState("");

  const bottomCategories = FILTER_CATEGORY_MAP[mainFilter] || ["All"];

  const getSubcatIcon = (main, sub) => {
    const M = {
      All: {
        All: "fa-solid fa-layer-group",
      },

      News: {
        All: "fa-solid fa-layer-group",
        World: "fa-solid fa-globe",
        Politics: "fa-solid fa-landmark-flag",
        Tech: "fa-solid fa-microchip",
        Finance: "fa-solid fa-chart-line",
        Local: "fa-solid fa-location-dot",
      },

      Friends: {
        All: "fa-solid fa-layer-group",
        Nearby: "fa-solid fa-location-crosshairs",
        Chats: "fa-solid fa-comments",
        Groups: "fa-solid fa-user-group",
        Stories: "fa-solid fa-book-open",
        Favs: "fa-solid fa-heart",
      },

      Events: {
        All: "fa-solid fa-layer-group",
        Today: "fa-solid fa-calendar-day",
        Weekend: "fa-solid fa-calendar-week",
        Music: "fa-solid fa-music",
        Sports: "fa-solid fa-football",
        Local: "fa-solid fa-location-dot",
      },

      Market: {
        All: "fa-solid fa-layer-group",
        Actu: "fa-solid fa-newspaper",
        Tech: "fa-solid fa-microchip",
        Finan: "fa-solid fa-money-bill-trend-up",
        Sport: "fa-solid fa-basketball",
        Deals: "fa-solid fa-tags",
      },
    };

    return (M[main] && M[main][sub]) || "";
  };

  useEffect(() => {
    if (!bottomCategories.length) return;
    if (!subFilter || !bottomCategories.includes(subFilter)) setSubFilter("All");
  }, [mainFilter, bottomCategories, subFilter]);

  useEffect(() => {
    if (!onPostsState) return;
    onPostsState({
      status,
      posts: visiblePosts,
      loading: loadingPosts,
      error: loadError,
    });
  }, [status, visiblePosts, loadingPosts, loadError, onPostsState]);

  useEffect(() => {
    if (!selectedPost) return;
    const map = mapRef.current;
    if (!map) return;

    const lng = selectedPost.lon ?? selectedPost.lng;
    const lat = selectedPost.lat ?? selectedPost.latitude;

    if (typeof lng === "number" && typeof lat === "number") {
      map.flyTo({ center: [lng, lat], zoom: 8, speed: 1.4 });
    }
  }, [selectedPost, mapRef]);

  useEffect(() => {
    const el = stageRef.current;
    if (!el || typeof IntersectionObserver === "undefined") return;

    const obs = new IntersectionObserver(
      (entries) => {
        const e = entries && entries[0];
        const ok = !!(e && e.isIntersecting && e.intersectionRatio > 0.15);
        setShowSubcats(ok);
      },
      { threshold: [0, 0.15, 0.3, 0.6] }
    );

    obs.observe(el);
    return () => obs.disconnect();
  }, []);

  useEffect(() => {
    const proto = window.location.protocol === "https:" ? "wss" : "ws";
    const host =
      window.location.port === "5173"
        ? `${window.location.hostname}:8081`
        : window.location.host;
    const wsUrl = `${proto}://${host}/ws`;

    let ws;
    try {
      ws = new WebSocket(wsUrl);
    } catch {
      return;
    }

    ws.onmessage = (ev) => {
      try {
        const msg = JSON.parse(ev.data);
        if (msg.type === "new_post" && msg.post) handleIncomingPost(msg.post);
      } catch {}
    };

    return () => ws && ws.close();
  }, [handleIncomingPost]);

  const handleFlyToMe = () => {
    const map = mapRef.current;
    if (!map || !userPosition) return;
    map.flyTo({ center: userPosition, zoom: 9, speed: 1.2 });
  };

  const handleOpenCreate = () => {
    if (!authenticated) {
      alert("You must be logged in to place a wire.");
      return;
    }

    if (needsEmailVerification) {
      alert(
        "You must verify your email before posting. Use 'Resend email' in the top bar, then login again."
      );
      return;
    }

    setIsCreating(true);
    setDraftTitle("");
    setDraftBody("");
    const main = mainFilter === "All" ? "News" : mainFilter;
    setDraftCategory(main);
    const list = CREATE_CATEGORY_MAP[main] || CREATE_CATEGORY_MAP.News;
    setDraftSubCategory(list[0]);
    setDraftCoords(null);
  };

  const handleSearchSubmit = (e) => {
    e.preventDefault();
  };

  const handleClearSearch = () => {
    setSearchQuery("");
  };

  const handleSubmitPost = async () => {
    if (isSaving) return;
    setSaveError("");

    const map = mapRef.current;
    if (!map) return;

    if (!authenticated) {
      setSaveError("You must be logged in to post.");
      return;
    }

    if (needsEmailVerification) {
      setSaveError(
        "Verify your email to post. Use 'Resend email' in the top bar, then login again."
      );
      return;
    }

    const authorName = (username || "").trim() || "anon";

    let baseLng;
    let baseLat;

    if (draftCoords && draftCoords.length === 2) {
      baseLng = draftCoords[0];
      baseLat = draftCoords[1];
    } else {
      const center = map.getCenter();
      baseLng = center.lng;
      baseLat = center.lat;
    }

    const pixelOffsetY = -20;
    const screenPoint = map.project([baseLng, baseLat]);
    const correctedPoint = { x: screenPoint.x, y: screenPoint.y + pixelOffsetY };
    const correctedLngLat = map.unproject([correctedPoint.x, correctedPoint.y]);
    const lng = correctedLngLat.lng;
    const lat = correctedLngLat.lat;

    if (!draftTitle.trim()) {
      setSaveError("Title required.");
      return;
    }

    try {
      setIsSaving(true);

      const newPost = await createPost(
        {
          title: draftTitle.trim(),
          snippet: draftBody.trim() || draftTitle.trim(),
          category:
            draftCategory === "Events" ? "EVENT" : draftCategory.toUpperCase(),
          sub_category: draftSubCategory || "ALL",
          lat,
          lon: lng,
          author: authorName,
        },
        token
      );

      if (newPost && newPost.id) handleIncomingPost(newPost);

      setIsSaving(false);
      setIsCreating(false);
    } catch (e) {
      console.error(e);
      setIsSaving(false);

      const code = e && (e.code || "");
      const msg = String((e && e.message) || "").toLowerCase();
      const isNotVerified =
        code === "email_not_verified" ||
        (e &&
          e.status === 403 &&
          (msg.includes("not verified") || msg.includes("verify")));

      if (isNotVerified) {
        setSaveError(
          "Verify your email to post. Use 'Resend email' in the top bar, then login again."
        );
      } else {
        setSaveError((e && e.message) || "Error creating post.");
      }
    }
  };

  const handleMainFilterSelect = (code) => {
    if (!FILTER_MAIN_CATEGORIES.includes(code)) return;
    setMainFilter(code);
  };

  const handleSelectPost = (post) => {
    if (onSelectPost) onSelectPost(post);
    const map = mapRef.current;
    if (!map) return;
    const lng = post.lon ?? post.lng;
    const lat = post.lat ?? post.latitude;
    if (typeof lng === "number" && typeof lat === "number") {
      map.flyTo({ center: [lng, lat], zoom: 8, speed: 1.4 });
    }
  };

  return (
    <div className="map-page">
      <div className="map-stage" ref={stageRef}>
        <div ref={containerRef} className="map-container" />
        {status && <div className="map-status">{status}</div>}

        {/* TOP: Search à gauche, 2 icônes à droite, sur une seule ligne */}
        <div className="map-overlay map-overlay-top">
          <div className="sw-top-row">
            <form
              className="sw-searchbar sw-top-search"
              onSubmit={handleSearchSubmit}
              role="search"
              aria-label="Search"
            >
              <i className="fa-solid fa-magnifying-glass sw-search-icon" />
              <input
                className="sw-search-input"
                type="search"
                placeholder="Look at… (city, topic, @user)"
                value={searchQuery}
                onChange={(e) => setSearchQuery(e.target.value)}
                autoCapitalize="none"
                autoCorrect="off"
                spellCheck={false}
              />
              {searchQuery ? (
                <button
                  type="button"
                  className="sw-search-clear"
                  onClick={handleClearSearch}
                  aria-label="Clear search"
                  title="Clear"
                >
                  ✕
                </button>
              ) : null}
            </form>

            <div className="map-top-actions">
              <button
                type="button"
                className="map-action-btn"
                onClick={handleFlyToMe}
                disabled={!userPosition}
              >
                <div className="map-action-icon">
                  <i className="fa-solid fa-location-crosshairs" />
                </div>
                <div className="map-action-label">My spot</div>
              </button>

              <button
                type="button"
                className="map-action-btn"
                onClick={handleOpenCreate}
              >
                <div className="map-action-icon">
                  <i className="fa-solid fa-bolt" />
                </div>
                <div className="map-action-label">New wire</div>
              </button>
            </div>
          </div>
        </div>

        <div className="map-overlay map-overlay-left">
          <TimeFilterButtons
            active={timeFilter}
            onSelect={(code) => setTimeFilter(code)}
          />
        </div>

        <div className="map-overlay map-overlay-right">
          <FilterButtons active={mainFilter} onSelect={handleMainFilterSelect} />
        </div>

        <div className="map-overlay map-overlay-bottom">
          <div className="sw-bottom-row">
            {bottomCategories.map((c) => (
              <button
                key={c}
                type="button"
                className={
                  "sw-bottom-item" + (subFilter === c ? " sw-bottom-active" : "")
                }
                onClick={() => setSubFilter(c)}
              >
                <div className="sw-bottom-circle">
                  {(() => {
                    const ic = getSubcatIcon(mainFilter, c);
                    return ic ? (
                      <i className={ic} />
                    ) : c === "All" ? (
                      "All"
                    ) : (
                      c.slice(0, 2)
                    );
                  })()}
                </div>
                <div className="sw-bottom-label">{c}</div>
              </button>
            ))}
          </div>
        </div>

        {isCreating && (
          <div className="map-overlay map-crosshair">
            <div className="crosshair-aim" />
          </div>
        )}

        {isCreating && (
          <div className="map-overlay create-post-panel">
            <div className="create-post-header">
              <span>Create wire</span>
              <button
                className="create-close"
                onClick={() => setIsCreating(false)}
              >
                ✕
              </button>
            </div>

            <span className="crosshair-label">
              Move the map, aim with the crosshair — your wire will be pinned
              there.
            </span>

            <div className="create-row">
              <select
                value={draftCategory}
                onChange={(e) => {
                  const cat = e.target.value;
                  setDraftCategory(cat);
                  setDraftSubCategory(
                    (CREATE_CATEGORY_MAP[cat] || CREATE_CATEGORY_MAP.News)[0]
                  );
                }}
              >
                {["News", "Friends", "Events", "Market"].map((cat) => (
                  <option key={cat}>{cat}</option>
                ))}
              </select>

              <select
                value={draftSubCategory}
                onChange={(e) => setDraftSubCategory(e.target.value)}
              >
                {(CREATE_CATEGORY_MAP[draftCategory] ||
                  CREATE_CATEGORY_MAP.News
                ).map((sub) => (
                  <option key={sub}>{sub}</option>
                ))}
              </select>
            </div>

            <input
              className="create-input"
              placeholder="Short title..."
              value={draftTitle}
              onChange={(e) => setDraftTitle(e.target.value)}
            />

            <textarea
              className="create-textarea"
              rows={2}
              placeholder="Context (optional)..."
              value={draftBody}
              onChange={(e) => setDraftBody(e.target.value)}
            />

            {saveError && <div className="create-error">{saveError}</div>}

            <div className="create-actions">
              <button
                className="chip-pill"
                onClick={handleSubmitPost}
                disabled={isSaving}
              >
                {isSaving ? "Posting..." : "Post"}
              </button>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}
