"use client";

import { useEffect, useReducer, useTransition } from "react";
import { useRouter } from "next/navigation";
import {
  makeInitialState,
  reducer,
  type Screen,
  type Tab,
} from "@/lib/app-state";
import { AppDataProvider, type AppData } from "@/lib/app-context";
import type { Place } from "@/lib/types";
import { deleteCollection, deletePlace } from "@/lib/db/actions";
import { loadSnapshot, saveSnapshot } from "@/lib/offline-cache";
import { TabBar } from "@/components/ui-primitives";
import { Icons } from "@/components/icons";
import { PlacesListScreen } from "@/screens/places-list-screen";
import { PlaceDetailScreen } from "@/screens/place-detail-screen";
import { CollectionsListScreen } from "@/screens/collections-list-screen";
import { CollectionDetailScreen } from "@/screens/collection-detail-screen";
import { ProfileScreen } from "@/screens/profile-screen";
import { AddPlaceSheet } from "@/sheets/add-place-sheet";
import { EditPlaceSheet } from "@/sheets/edit-place-sheet";
import { SaveToCollectionSheet } from "@/sheets/save-to-collection-sheet";
import { CollectionFormSheet } from "@/sheets/collection-form-sheet";
import { InviteDialog } from "@/sheets/invite-dialog";
import { MembersSheet, ConfirmDialog } from "@/sheets/members-sheet";

export function PlacesApp({
  initialPlaces,
  data,
}: {
  initialPlaces: Place[];
  data: AppData;
}) {
  // If we boot up offline, prefer the cached snapshot so the UI has *some*
  // data to show. When network returns, the visibility/focus effect refreshes.
  const bootData: { places: Place[]; data: AppData } = (() => {
    if (typeof window === "undefined") return { places: initialPlaces, data };
    if (!navigator.onLine) {
      const snap = loadSnapshot(data.me.id);
      if (snap) {
        return {
          places: snap.places,
          data: { me: snap.me, users: snap.users, collections: snap.collections },
        };
      }
    }
    return { places: initialPlaces, data };
  })();

  const [state, dispatch] = useReducer(reducer, bootData.places, makeInitialState);
  const [, startTransition] = useTransition();
  const router = useRouter();

  // Mirror the latest server snapshot to localStorage so it's available next
  // time the user boots up offline. Only writes when we trust the data
  // (i.e. currently online).
  useEffect(() => {
    if (typeof window === "undefined") return;
    if (!navigator.onLine) return;
    saveSnapshot({
      v: 1,
      savedAt: Date.now(),
      me: data.me,
      users: data.users,
      collections: data.collections,
      places: state.places,
    });
  }, [data, state.places]);

  // Realtime-lite sync: re-fetch server data when the tab regains focus or
  // network comes back. Cheap proxy for true realtime — catches changes other
  // members made while this tab was inactive. CLAUDE.md Phase 2.
  useEffect(() => {
    const refresh = () => router.refresh();
    const onVisible = () => {
      if (document.visibilityState === "visible") refresh();
    };
    document.addEventListener("visibilitychange", onVisible);
    window.addEventListener("focus", refresh);
    window.addEventListener("online", refresh);
    return () => {
      document.removeEventListener("visibilitychange", onVisible);
      window.removeEventListener("focus", refresh);
      window.removeEventListener("online", refresh);
    };
  }, [router]);

  useEffect(() => {
    if (!state.toast) return;
    const key = state.toastKey;
    const id = setTimeout(
      () => dispatch({ type: "CLEAR_TOAST", key }),
      2200,
    );
    return () => clearTimeout(id);
  }, [state.toast, state.toastKey]);

  useEffect(() => {
    const sync = () =>
      dispatch({ type: "SET_OFFLINE", value: !navigator.onLine });
    sync();
    window.addEventListener("online", sync);
    window.addEventListener("offline", sync);
    return () => {
      window.removeEventListener("online", sync);
      window.removeEventListener("offline", sync);
    };
  }, []);

  const top = state.stack[state.stack.length - 1];
  const activeTab: Tab =
    top.screen === "place" || top.screen === "collection"
      ? state.tab
      : (top.screen as Tab);

  const onTab = (id: string) => {
    if (id === "profile" || id === "collections" || id === "places") {
      dispatch({ type: "TAB", tab: id });
    }
  };

  const renderScreen = (screen: Screen) => {
    if (screen === "places")
      return <PlacesListScreen state={state} dispatch={dispatch} />;
    if (screen === "collections")
      return <CollectionsListScreen state={state} dispatch={dispatch} />;
    if (screen === "profile")
      return <ProfileScreen state={state} dispatch={dispatch} />;
    if (screen === "place")
      return (
        <PlaceDetailScreen
          state={{ ...state, placeId: top.placeId, collectionId: top.collectionId }}
          dispatch={dispatch}
        />
      );
    if (screen === "collection")
      return (
        <CollectionDetailScreen
          state={{ ...state, collectionId: top.collectionId }}
          dispatch={dispatch}
        />
      );
    return null;
  };

  const m = state.modal;
  const placeForDelete =
    m?.type === "confirmDeletePlace"
      ? state.places.find((p) => p.id === m.placeId)
      : null;
  const collectionForDelete =
    m?.type === "confirmDeleteCollection"
      ? bootData.data.collections.find((c) => c.id === m.collectionId)
      : null;

  return (
    <AppDataProvider value={bootData.data}>
      <div className="app-frame">
        {renderScreen(top.screen)}
        <TabBar
          active={activeTab}
          onTab={onTab}
          onFab={() => dispatch({ type: "OPEN_ADD" })}
          showFab={top.screen !== "profile"}
        />

        {m?.type === "add" && (
          <AddPlaceSheet
            onClose={() => dispatch({ type: "CLOSE_MODAL" })}
            dispatch={dispatch}
          />
        )}
        {m?.type === "editPlace" && (() => {
          const p = state.places.find((x) => x.id === m.placeId);
          return p ? (
            <EditPlaceSheet
              place={p}
              onClose={() => dispatch({ type: "CLOSE_MODAL" })}
              dispatch={dispatch}
            />
          ) : null;
        })()}
        {m?.type === "saveToCollection" && (
          <SaveToCollectionSheet
            placeId={m.placeId}
            onClose={() => dispatch({ type: "CLOSE_MODAL" })}
            dispatch={dispatch}
          />
        )}
        {m?.type === "createCollection" && (
          <CollectionFormSheet
            mode="create"
            onClose={() => dispatch({ type: "CLOSE_MODAL" })}
            dispatch={dispatch}
          />
        )}
        {m?.type === "editCollection" && (() => {
          const c = bootData.data.collections.find((x) => x.id === m.collectionId);
          return c ? (
            <CollectionFormSheet
              mode="edit"
              collection={c}
              onClose={() => dispatch({ type: "CLOSE_MODAL" })}
              dispatch={dispatch}
            />
          ) : null;
        })()}
        {m?.type === "invite" && (
          <InviteDialog
            collectionId={m.collectionId}
            onClose={() => dispatch({ type: "CLOSE_MODAL" })}
            dispatch={dispatch}
          />
        )}
        {m?.type === "members" && (
          <MembersSheet
            collectionId={m.collectionId}
            onClose={() => dispatch({ type: "CLOSE_MODAL" })}
            dispatch={dispatch}
          />
        )}
        {m?.type === "confirmDeletePlace" && placeForDelete && (
          <ConfirmDialog
            title="Xóa địa điểm?"
            body={`"${placeForDelete.name}" sẽ bị xóa khỏi tất cả bộ sưu tập. Không thể hoàn tác.`}
            confirmLabel="Xóa"
            onConfirm={() => {
              const id = m.placeId;
              dispatch({ type: "DELETE_PLACE", placeId: id });
              startTransition(() => {
                deletePlace(id).catch(() =>
                  dispatch({ type: "TOAST", value: "Xóa thất bại" }),
                );
              });
            }}
            onClose={() => dispatch({ type: "CLOSE_MODAL" })}
          />
        )}
        {m?.type === "confirmDeleteCollection" && collectionForDelete && (
          <ConfirmDialog
            title="Xóa bộ sưu tập?"
            body={`"${collectionForDelete.name}" sẽ bị xóa. Các địa điểm bên trong vẫn còn ở "Địa điểm".`}
            confirmLabel="Xóa"
            onConfirm={() => {
              const id = m.collectionId;
              dispatch({ type: "CLOSE_MODAL" });
              dispatch({ type: "BACK" });
              startTransition(() => {
                deleteCollection(id)
                  .then(() => dispatch({ type: "TOAST", value: "Đã xóa" }))
                  .catch(() => dispatch({ type: "TOAST", value: "Xóa thất bại" }));
              });
            }}
            onClose={() => dispatch({ type: "CLOSE_MODAL" })}
          />
        )}

        {state.toast && (
          <div className="toast" key={state.toastKey}>
            <Icons.Check size={14} stroke={2.5} />
            {state.toast}
          </div>
        )}
      </div>
    </AppDataProvider>
  );
}
