"use client";

import React, { useCallback, useEffect, useRef, useState } from "react";
import Link from "next/link";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { getApiErrorMessage } from "@/lib/api-error";
import { cn } from "@/lib/utils";
import { parseBulkLayoutFile } from "@/lib/parse-property-layout-bulk-upload";
import {
  useGetTenantUsersQuery,
  useLazyGetTenantPropertyFullQuery,
  useReplaceTenantPropertyPlazaLayoutMutation,
} from "@/redux/api";
import { toast } from "sonner";
import { FileDown, Plus, Trash2, Upload } from "lucide-react";
import type { ClientWorkspaceChildCtx } from "@/features/client/client-workspace-layout";
import type { PropertyRow } from "@/features/client/property-types";

const SITE_TYPES = ["plaza", "town", "society", "other"] as const;
const UNIT_TYPES = ["shop", "apartment", "office", "warehouse", "other"] as const;

type SiteKind = (typeof SITE_TYPES)[number];

type UnitDraft = {
  key: string;
  unitNumber: string;
  type: (typeof UNIT_TYPES)[number];
  size: string;
  tenantUserId: string;
};

type FloorDraft = {
  key: string;
  name: string;
  level: string;
  units: UnitDraft[];
};

const PLOT_ZONING_TYPES = ["commercial", "residential"] as const;
type PlotZoning = (typeof PLOT_ZONING_TYPES)[number];

type TownUnitDraft = {
  key: string;
  plotNumber: string;
  plotZoning: PlotZoning;
  size: string;
  streetNumber: string;
  tenantUserId: string;
};

type TownBlockDraft = {
  key: string;
  name: string;
  level: string;
  units: TownUnitDraft[];
};

function newKey() {
  return `k-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
}

function emptyUnit(): UnitDraft {
  return {
    key: newKey(),
    unitNumber: "",
    type: "shop",
    size: "",
    tenantUserId: "",
  };
}

function emptyFloor(): FloorDraft {
  return {
    key: newKey(),
    name: "",
    level: "0",
    units: [emptyUnit()],
  };
}

function floorDraftMergeKey(f: FloorDraft): string {
  return `${f.name.trim().toLowerCase()}|||${String(f.level).trim()}`;
}

/**
 * Merges bulk-upload floors into the current editor state: matching floor name + level
 * adds new units or updates same unit number; floors only in the file are appended.
 */
function mergePlazaFloorDrafts(
  existing: FloorDraft[],
  incoming: FloorDraft[],
  genKey: () => string
): FloorDraft[] {
  const result = existing.map((f) => ({
    ...f,
    units: f.units.map((u) => ({ ...u })),
  }));

  for (const inf of incoming) {
    const hasIncomingUnits = inf.units.some((u) => u.unitNumber.trim());
    if (!inf.name.trim() && !hasIncomingUnits) continue;

    const idx = result.findIndex((f) => floorDraftMergeKey(f) === floorDraftMergeKey(inf));
    if (idx >= 0) {
      const cur = result[idx];
      const nextUnits = [...cur.units];
      for (const iu of inf.units) {
        const un = iu.unitNumber.trim();
        if (!un) continue;
        const j = nextUnits.findIndex(
          (u) => u.unitNumber.trim().toLowerCase() === un.toLowerCase()
        );
        if (j >= 0) {
          nextUnits[j] = {
            ...nextUnits[j],
            type: iu.type,
            size: iu.size,
            tenantUserId: iu.tenantUserId,
          };
        } else {
          nextUnits.push({ ...iu, key: genKey() });
        }
      }
      result[idx] = {
        ...cur,
        name: inf.name.trim() || cur.name,
        level: inf.level !== "" ? inf.level : cur.level,
        units: nextUnits.length ? nextUnits : [emptyUnit()],
      };
    } else {
      result.push({
        key: genKey(),
        name: inf.name,
        level: inf.level,
        units: inf.units.map((u) => ({ ...u, key: genKey() })),
      });
    }
  }
  return result;
}

function emptyTownUnit(): TownUnitDraft {
  return {
    key: newKey(),
    plotNumber: "",
    plotZoning: "residential",
    size: "",
    streetNumber: "",
    tenantUserId: "",
  };
}

function emptyTownBlock(): TownBlockDraft {
  return {
    key: newKey(),
    name: "",
    level: "0",
    units: [emptyTownUnit()],
  };
}

type Props = {
  ctx: ClientWorkspaceChildCtx;
  property: PropertyRow;
  listHref: string;
  onCancel: () => void;
  onSaved: () => void;
};

export default function PropertyLayoutEditorForm({
  ctx,
  property,
  listHref,
  onCancel,
  onSaved,
}: Props) {
  const { tenantApiKey, tenantReady } = ctx;
  const [floors, setFloors] = useState<FloorDraft[]>([emptyFloor()]);
  const [townBlocks, setTownBlocks] = useState<TownBlockDraft[]>([emptyTownBlock()]);
  const { data: teamUsers = [] } = useGetTenantUsersQuery(tenantApiKey, {
    skip: !tenantReady,
  });
  const [fetchPropertyFull] = useLazyGetTenantPropertyFullQuery();
  const [replacePlazaLayout] = useReplaceTenantPropertyPlazaLayoutMutation();
  const [loadingFull, setLoadingFull] = useState(false);
  const [saving, setSaving] = useState(false);
  const bulkModalFileRef = useRef<HTMLInputElement>(null);
  /** Bumped after bulk save so an older in-flight /full fetch cannot overwrite fresh UI. */
  const layoutApplyEpochRef = useRef(0);
  const layoutPropertyIdRef = useRef(property._id);
  layoutPropertyIdRef.current = property._id;
  const [bulkModalOpen, setBulkModalOpen] = useState(false);
  const [bulkProgress, setBulkProgress] = useState(0);
  const [bulkPhase, setBulkPhase] = useState<
    "idle" | "reading" | "parsing" | "ready" | "error"
  >("idle");
  const [stagedBulkFloors, setStagedBulkFloors] = useState<FloorDraft[] | null>(null);
  const [stagedBulkWarnings, setStagedBulkWarnings] = useState<string[]>([]);
  const [bulkModalSaving, setBulkModalSaving] = useState(false);
  const [bulkDropActive, setBulkDropActive] = useState(false);

  const siteTypeResolved: SiteKind =
    property.siteType && SITE_TYPES.includes(property.siteType as SiteKind)
      ? (property.siteType as SiteKind)
      : "other";

  const needsLayout =
    siteTypeResolved === "plaza" ||
    siteTypeResolved === "town" ||
    siteTypeResolved === "society";
  const isTown = siteTypeResolved === "town";
  const isCommercialPlaza = property.type === "commercial" && siteTypeResolved === "plaza";

  const mapFullToFloors = useCallback(
    (
      data: {
        structures: Array<{
          _id: string;
          name: string;
          type: string;
          level?: number;
        }>;
        units: Array<{
          _id: string;
          structureId: string;
          unitNumber: string;
          type: string;
          size?: number | null;
        }>;
        unitUsers: Array<{
          unitId: string;
          userId: { _id?: string } | string;
          status?: string;
        }>;
      },
      siteKind: SiteKind
    ) => {
      const stType = siteKind === "town" ? "phase" : "floor";
      const floorStructs = data.structures
        .filter((s) => s.type === stType)
        .sort((a, b) => (a.level ?? 0) - (b.level ?? 0));
      const next: FloorDraft[] = floorStructs.map((s) => {
        const uForFloor = data.units.filter((u) => String(u.structureId) === String(s._id));
        const units: UnitDraft[] = uForFloor.map((u) => {
          const active = data.unitUsers.find(
            (uu) =>
              String(uu.unitId) === String(u._id) &&
              (uu.status === "active" || uu.status == null)
          );
          let tid = "";
          if (active?.userId) {
            tid =
              typeof active.userId === "object" && active.userId && "_id" in active.userId
                ? String((active.userId as { _id: string })._id)
                : String(active.userId);
          }
          return {
            key: newKey(),
            unitNumber: u.unitNumber,
            type: (UNIT_TYPES.includes(u.type as (typeof UNIT_TYPES)[number])
              ? u.type
              : "other") as (typeof UNIT_TYPES)[number],
            size:
              u.size != null && String(u.size).trim() !== "" ? String(u.size) : "",
            tenantUserId: tid,
          };
        });
        return {
          key: newKey(),
          name: s.name,
          level: String(s.level ?? 0),
          units: units.length ? units : [emptyUnit()],
        };
      });
      setFloors(next.length ? next : [emptyFloor()]);
    },
    []
  );

  const mapFullToTownBlocks = useCallback(
    (data: {
      structures: Array<{
        _id: string;
        name: string;
        type: string;
        level?: number;
        parentId?: string | null;
      }>;
      units: Array<{
        _id: string;
        structureId: string;
        unitNumber: string;
        type: string;
        size?: number | null;
        plotZoning?: "commercial" | "residential" | null;
        streetNumber?: string;
      }>;
      unitUsers: Array<{
        unitId: string;
        userId: { _id?: string } | string;
        status?: string;
      }>;
    }) => {
      const rootBlocks = data.structures
        .filter((s) => s.type === "block" && (s.parentId == null || s.parentId === ""))
        .sort((a, b) => (a.level ?? 0) - (b.level ?? 0));

      const mapOneUnit = (u: (typeof data.units)[0]): TownUnitDraft => {
        const active = data.unitUsers.find(
          (uu) =>
            String(uu.unitId) === String(u._id) &&
            (uu.status === "active" || uu.status == null)
        );
        let tid = "";
        if (active?.userId) {
          tid =
            typeof active.userId === "object" && active.userId && "_id" in active.userId
              ? String((active.userId as { _id: string })._id)
              : String(active.userId);
        }
        const zoning: PlotZoning =
          u.plotZoning === "commercial" ? "commercial" : "residential";
        return {
          key: newKey(),
          plotNumber: u.unitNumber,
          plotZoning: zoning,
          size: u.size != null && String(u.size).trim() !== "" ? String(u.size) : "",
          streetNumber: u.streetNumber != null ? String(u.streetNumber) : "",
          tenantUserId: tid,
        };
      };

      const collectUnitsForBlock = (blockId: string): TownUnitDraft[] => {
        const seen = new Set<string>();
        const out: TownUnitDraft[] = [];
        const phaseIds = data.structures
          .filter((s) => s.type === "phase" && String(s.parentId ?? "") === String(blockId))
          .sort((a, b) => (a.level ?? 0) - (b.level ?? 0))
          .map((s) => s._id);
        for (const pid of phaseIds) {
          for (const u of data.units) {
            if (String(u.structureId) !== String(pid)) continue;
            const id = String(u._id);
            if (seen.has(id)) continue;
            seen.add(id);
            out.push(mapOneUnit(u));
          }
        }
        for (const u of data.units) {
          if (String(u.structureId) !== String(blockId)) continue;
          const id = String(u._id);
          if (seen.has(id)) continue;
          seen.add(id);
          out.push(mapOneUnit(u));
        }
        return out.length ? out : [emptyTownUnit()];
      };

      if (rootBlocks.length > 0) {
        const next: TownBlockDraft[] = rootBlocks.map((block) => ({
          key: newKey(),
          name: block.name,
          level: String(block.level ?? 0),
          units: collectUnitsForBlock(String(block._id)),
        }));
        setTownBlocks(next.length ? next : [emptyTownBlock()]);
        return;
      }

      const flatPhases = data.structures
        .filter((s) => s.type === "phase")
        .sort((a, b) => (a.level ?? 0) - (b.level ?? 0));
      const merged: TownUnitDraft[] = [];
      const seenFlat = new Set<string>();
      for (const ph of flatPhases) {
        for (const u of data.units) {
          if (String(u.structureId) !== String(ph._id)) continue;
          const id = String(u._id);
          if (seenFlat.has(id)) continue;
          seenFlat.add(id);
          merged.push(mapOneUnit(u));
        }
      }
      setTownBlocks([
        {
          key: newKey(),
          name: "Block 1",
          level: "0",
          units: merged.length ? merged : [emptyTownUnit()],
        },
      ]);
    },
    []
  );

  useEffect(() => {
    if (!needsLayout || !tenantReady) {
      setFloors([emptyFloor()]);
      setTownBlocks([emptyTownBlock()]);
      return;
    }
    setLoadingFull(true);
    const loadPropertyId = property._id;
    void (async () => {
      const epochAtFetchStart = layoutApplyEpochRef.current;
      try {
        const d = await fetchPropertyFull({
          tenantKey: tenantApiKey,
          propertyId: loadPropertyId,
        }).unwrap();
        if (epochAtFetchStart !== layoutApplyEpochRef.current) return;
        if (layoutPropertyIdRef.current !== loadPropertyId) return;
        if (d?.structures && d?.units) {
          if (siteTypeResolved === "town") {
            mapFullToTownBlocks({
              structures: d.structures,
              units: d.units,
              unitUsers: d.unitUsers || [],
            });
          } else {
            mapFullToFloors(
              {
                structures: d.structures,
                units: d.units,
                unitUsers: d.unitUsers || [],
              },
              siteTypeResolved
            );
          }
        } else {
          setFloors([emptyFloor()]);
          setTownBlocks([emptyTownBlock()]);
        }
      } catch {
        if (epochAtFetchStart !== layoutApplyEpochRef.current) return;
        if (layoutPropertyIdRef.current !== loadPropertyId) return;
        setFloors([emptyFloor()]);
        setTownBlocks([emptyTownBlock()]);
      } finally {
        setLoadingFull(false);
      }
    })();
  }, [
    needsLayout,
    tenantReady,
    tenantApiKey,
    property._id,
    siteTypeResolved,
    fetchPropertyFull,
    mapFullToFloors,
    mapFullToTownBlocks,
  ]);

  const buildPlazaPayloadFromFloors = (list: FloorDraft[]) => {
    const floorPayload = list
      .filter((f) => f.name.trim())
      .map((f, i) => ({
        name: f.name.trim(),
        level: f.level !== "" ? Number(f.level) : i,
        units: f.units
          .filter((u) => u.unitNumber.trim())
          .map((u) => ({
            unitNumber: u.unitNumber.trim(),
            type: u.type,
            size: u.size.trim() === "" ? null : Number(u.size),
            tenants: u.tenantUserId
              ? [{ userId: u.tenantUserId, role: "tenant" as const }]
              : [],
          })),
      }));
    return { floors: floorPayload };
  };

  const buildPlazaPayload = () => buildPlazaPayloadFromFloors(floors);

  const buildTownBlocksPayload = () => {
    const blocks = townBlocks
      .filter((b) => b.name.trim())
      .map((b, bi) => ({
        name: b.name.trim(),
        level: b.level !== "" ? Number(b.level) : bi,
        units: b.units
          .filter((u) => u.plotNumber.trim())
          .map((u) => ({
            unitNumber: u.plotNumber.trim(),
            type: "plot" as const,
            plotZoning: u.plotZoning,
            size: u.size.trim() === "" ? null : Number(u.size),
            streetNumber: u.streetNumber.trim() || undefined,
            tenants: u.tenantUserId
              ? [{ userId: u.tenantUserId, role: "tenant" as const }]
              : [],
          })),
      }))
      .filter((b) => b.units.length > 0);
    return { blocks };
  };

  const save = async () => {
    if (!tenantReady) {
      toast.error("Workspace not ready");
      return;
    }
    if (!needsLayout) return;

    if (isTown) {
      const okTown = townBlocks.some((b) => b.name.trim());
      if (!okTown) {
        toast.error("Add at least one block with a name");
        return;
      }
    } else {
      const validFloors = floors.some((f) => f.name.trim());
      if (!validFloors) {
        toast.error("Add at least one floor with a name");
        return;
      }
    }

    setSaving(true);
    try {
      if (isTown) {
        const tb = buildTownBlocksPayload();
        if (tb.blocks.length === 0) {
          toast.error(
            "Add blocks and at least one plot number per block you want to save"
          );
          setSaving(false);
          return;
        }
        await replacePlazaLayout({
          tenantKey: tenantApiKey,
          propertyId: property._id,
          payload: tb,
        }).unwrap();
      } else {
        const payload = buildPlazaPayload();
        if (payload.floors.length === 0) {
          toast.error("Add floors and units for this layout");
          setSaving(false);
          return;
        }
        await replacePlazaLayout({
          tenantKey: tenantApiKey,
          propertyId: property._id,
          payload,
        }).unwrap();
      }
      toast.success("Layout saved");
      onSaved();
    } catch (e: unknown) {
      toast.error(getApiErrorMessage(e, "Could not save layout"));
    } finally {
      setSaving(false);
    }
  };

  const resetBulkModal = useCallback(() => {
    setBulkProgress(0);
    setBulkPhase("idle");
    setStagedBulkFloors(null);
    setStagedBulkWarnings([]);
    if (bulkModalFileRef.current) bulkModalFileRef.current.value = "";
  }, []);

  const openBulkModal = () => {
    resetBulkModal();
    setBulkModalOpen(true);
  };

  const processBulkFile = (file: File) => {
    if (!tenantReady) return;
    setStagedBulkFloors(null);
    setStagedBulkWarnings([]);
    setBulkPhase("reading");
    setBulkProgress(0);

    const reader = new FileReader();
    reader.onprogress = (e) => {
      if (e.lengthComputable && e.total > 0) {
        setBulkProgress(Math.min(55, Math.round((e.loaded / e.total) * 55)));
      }
    };
    reader.onload = () => {
      setBulkPhase("parsing");
      setBulkProgress(62);
      try {
        const buf = reader.result as ArrayBuffer;
        setBulkProgress(78);
        const { floors: parsed, warnings } = parseBulkLayoutFile(buf, teamUsers);
        const next: FloorDraft[] = parsed.map((f) => ({
          key: newKey(),
          name: f.name,
          level: f.level,
          units: f.units.map((u) => ({
            key: newKey(),
            unitNumber: u.unitNumber,
            type: u.type,
            size: u.size,
            tenantUserId: u.tenantUserId,
          })),
        }));
        setBulkProgress(100);
        setStagedBulkFloors(next);
        setStagedBulkWarnings(warnings);
        setBulkPhase("ready");
        toast.success(
          `File processed: ${next.length} floor group(s). Save merges with floors already on this page.`
        );
        if (warnings.length) {
          const msg = warnings.slice(0, 4).join(" · ");
          toast.warning(warnings.length > 4 ? `${msg} · …` : msg, { duration: 10000 });
        }
      } catch (e: unknown) {
        setBulkPhase("error");
        setBulkProgress(0);
        toast.error(getApiErrorMessage(e, "Could not read file"));
      }
    };
    reader.onerror = () => {
      setBulkPhase("error");
      setBulkProgress(0);
      toast.error("Could not read file");
    };
    reader.readAsArrayBuffer(file);
  };

  const saveBulkFromModal = async () => {
    if (!tenantReady || !stagedBulkFloors) return;
    const merged = mergePlazaFloorDrafts(floors, stagedBulkFloors, newKey);
    const payload = buildPlazaPayloadFromFloors(merged);
    if (payload.floors.length === 0) {
      toast.error("No valid floors to save");
      return;
    }
    setBulkModalSaving(true);
    try {
      await replacePlazaLayout({
        tenantKey: tenantApiKey,
        propertyId: property._id,
        payload,
      }).unwrap();

      layoutApplyEpochRef.current += 1;

      try {
        const d = await fetchPropertyFull(
          {
            tenantKey: tenantApiKey,
            propertyId: property._id,
          },
          false
        ).unwrap();
        if (d?.structures && d?.units) {
          if (siteTypeResolved === "town") {
            mapFullToTownBlocks({
              structures: d.structures,
              units: d.units,
              unitUsers: d.unitUsers || [],
            });
          } else {
            mapFullToFloors(
              {
                structures: d.structures,
                units: d.units,
                unitUsers: d.unitUsers || [],
              },
              siteTypeResolved
            );
          }
        } else {
          setFloors(merged);
        }
      } catch {
        setFloors(merged);
      }

      toast.success("Layout updated — file data merged with existing floors.");
      setBulkModalOpen(false);
      resetBulkModal();
    } catch (e: unknown) {
      toast.error(getApiErrorMessage(e, "Could not save layout"));
    } finally {
      setBulkModalSaving(false);
    }
  };

  const editBasicHref = `${listHref}/${property._id}/edit`;

  const townLayoutSection = (
    <>
      <div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
        <p className="min-w-0 flex-1 text-xs leading-relaxed text-gray-600 sm:text-sm">
          Add blocks, then plots under each block: plot number, type (commercial or residential),
          size, and optional street #. Optional user link; rent is not used for Town plots.
        </p>
        <Button
          type="button"
          variant="outline"
          size="sm"
          className="w-full shrink-0 sm:w-auto"
          onClick={() => setTownBlocks((prev) => [...prev, emptyTownBlock()])}
        >
          <Plus className="mr-1 size-4" />
          Block
        </Button>
      </div>

      <div className="space-y-8">
        {townBlocks.map((block, bi) => (
          <div key={block.key} className="rounded-lg border border-gray-200 bg-gray-50/50 p-4">
            <div className="mb-4 flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:items-end">
              <div className="min-w-0 flex-1 sm:min-w-[140px]">
                <Label className="text-xs sm:text-sm">Block</Label>
                <Input
                  placeholder="e.g. Block A, Block B"
                  value={block.name}
                  onChange={(e) => {
                    const v = e.target.value;
                    setTownBlocks((prev) =>
                      prev.map((b, i) => (i === bi ? { ...b, name: v } : b))
                    );
                  }}
                />
              </div>
              <div className="w-full sm:w-24">
                <Label className="text-xs sm:text-sm">Level</Label>
                <Input
                  type="number"
                  className="[appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
                  value={block.level}
                  onChange={(e) => {
                    const v = e.target.value;
                    setTownBlocks((prev) =>
                      prev.map((b, i) => (i === bi ? { ...b, level: v } : b))
                    );
                  }}
                />
              </div>
              <Button
                type="button"
                variant="ghost"
                size="icon"
                className="self-end text-red-600 sm:self-auto"
                onClick={() =>
                  setTownBlocks((prev) =>
                    prev.length <= 1 ? prev : prev.filter((_, i) => i !== bi)
                  )
                }
                disabled={townBlocks.length === 1}
              >
                <Trash2 className="size-4" />
              </Button>
            </div>

            <div className="space-y-3 border-t border-gray-200 pt-4">
              <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
                <span className="text-[11px] font-medium uppercase tracking-wide text-gray-500 sm:text-xs">
                  Plots in this block
                </span>
                <Button
                  type="button"
                  variant="secondary"
                  size="sm"
                  className="w-full sm:w-auto"
                  onClick={() =>
                    setTownBlocks((prev) =>
                      prev.map((b, i) =>
                        i === bi ? { ...b, units: [...b.units, emptyTownUnit()] } : b
                      )
                    )
                  }
                >
                  <Plus className="mr-1 size-4" />
                  Plot
                </Button>
              </div>

              {block.units.map((plot, ui) => (
                <div
                  key={plot.key}
                  className="grid grid-cols-1 gap-3 rounded-md border bg-white p-3 sm:grid-cols-[minmax(0,5.5rem)_minmax(0,8rem)_minmax(0,4.5rem)_minmax(0,5rem)_minmax(0,1fr)_auto] sm:items-end"
                >
                  <div className="min-w-0">
                    <Label className="text-xs">Plot number</Label>
                    <Input
                      placeholder="e.g. 45-A"
                      value={plot.plotNumber}
                      onChange={(e) => {
                        const v = e.target.value;
                        setTownBlocks((prev) =>
                          prev.map((b, i) =>
                            i === bi
                              ? {
                                  ...b,
                                  units: b.units.map((u, k) =>
                                    k === ui ? { ...u, plotNumber: v } : u
                                  ),
                                }
                              : b
                          )
                        );
                      }}
                    />
                  </div>
                  <div className="min-w-0">
                    <Label className="text-xs">Plot type</Label>
                    <Select
                      value={plot.plotZoning}
                      onValueChange={(v) => {
                        setTownBlocks((prev) =>
                          prev.map((b, i) =>
                            i === bi
                              ? {
                                  ...b,
                                  units: b.units.map((u, k) =>
                                    k === ui ? { ...u, plotZoning: v as PlotZoning } : u
                                  ),
                                }
                              : b
                          )
                        );
                      }}
                    >
                      <SelectTrigger className="min-w-0 max-w-full">
                        <SelectValue />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectItem value="residential">Residential</SelectItem>
                        <SelectItem value="commercial">Commercial</SelectItem>
                      </SelectContent>
                    </Select>
                  </div>
                  <div className="min-w-0 sm:max-w-[5rem]">
                    <Label className="text-xs">Size (m²)</Label>
                    <Input
                      inputMode="decimal"
                      placeholder="e.g. 120"
                      value={plot.size}
                      onChange={(e) => {
                        const v = e.target.value;
                        setTownBlocks((prev) =>
                          prev.map((b, i) =>
                            i === bi
                              ? {
                                  ...b,
                                  units: b.units.map((u, k) =>
                                    k === ui ? { ...u, size: v } : u
                                  ),
                                }
                              : b
                          )
                        );
                      }}
                    />
                  </div>
                  <div className="min-w-0 sm:max-w-[5rem]">
                    <Label className="text-xs">Street # (optional)</Label>
                    <Input
                      placeholder="e.g. 12"
                      value={plot.streetNumber}
                      onChange={(e) => {
                        const v = e.target.value;
                        setTownBlocks((prev) =>
                          prev.map((b, i) =>
                            i === bi
                              ? {
                                  ...b,
                                  units: b.units.map((u, k) =>
                                    k === ui ? { ...u, streetNumber: v } : u
                                  ),
                                }
                              : b
                          )
                        );
                      }}
                    />
                  </div>
                  <div className="min-w-0">
                    <Label className="text-xs">Link user (optional)</Label>
                    <Select
                      value={plot.tenantUserId || "__none__"}
                      onValueChange={(v) => {
                        const val = v === "__none__" ? "" : v;
                        setTownBlocks((prev) =>
                          prev.map((b, i) =>
                            i === bi
                              ? {
                                  ...b,
                                  units: b.units.map((u, k) =>
                                    k === ui ? { ...u, tenantUserId: val } : u
                                  ),
                                }
                              : b
                          )
                        );
                      }}
                    >
                      <SelectTrigger className="min-w-0 max-w-full">
                        <SelectValue placeholder="None" />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectItem value="__none__">None</SelectItem>
                        {teamUsers.map((u) => (
                          <SelectItem key={u._id} value={u._id}>
                            {[u.firstName, u.lastName].filter(Boolean).join(" ") || u.username}{" "}
                            ({u.email})
                          </SelectItem>
                        ))}
                      </SelectContent>
                    </Select>
                  </div>
                  <Button
                    type="button"
                    variant="ghost"
                    size="icon"
                    className="justify-self-end text-red-600 sm:justify-self-auto"
                    onClick={() =>
                      setTownBlocks((prev) =>
                        prev.map((b, i) =>
                          i === bi
                            ? {
                                ...b,
                                units:
                                  b.units.filter((_, k) => k !== ui).length > 0
                                    ? b.units.filter((_, k) => k !== ui)
                                    : [emptyTownUnit()],
                              }
                            : b
                        )
                      )
                    }
                  >
                    <Trash2 className="size-4" />
                  </Button>
                </div>
              ))}
            </div>
          </div>
        ))}
      </div>
    </>
  );

  return (
    <>
      <div className="min-w-0 overflow-hidden rounded-md border bg-white">
        <div className="border-b px-4 py-2 sm:px-6">
          <Button variant="link" className="h-auto p-0 text-sm font-normal" asChild>
            <Link href={listHref}>← Back to properties</Link>
          </Button>
        </div>

      <div className="overflow-x-hidden px-4 py-3 sm:px-6 sm:py-4">
        <h2 className="text-base font-semibold text-gray-900">More details</h2>
        <p className="mt-1 text-sm text-gray-600">
          <span className="font-medium">{property.name}</span>
          <span className="text-gray-400"> · </span>
          <span className="capitalize">{siteTypeResolved}</span>
        </p>
        <p className="mt-2 text-xs leading-relaxed text-gray-500 sm:text-sm">
          Floors, units, blocks, and plots for this property. Save replaces the existing layout for
          this site type.
        </p>

        {!needsLayout ? (
          <div className="mt-6 rounded-md border border-amber-200 bg-amber-50 p-4 text-sm text-amber-900">
            <p>
              Layout editing is only available when site layout is Plaza, Town, or Society. Change
              it on{" "}
              <Link href={editBasicHref} className="font-medium text-primary underline">
                Edit property
              </Link>
              .
            </p>
          </div>
        ) : loadingFull ? (
          <p className="mt-6 text-sm text-gray-500">Loading layout…</p>
        ) : (
          <div className="mt-6 space-y-4">
            {isCommercialPlaza && !isTown && (
              <div className="rounded-lg border border-gray-200 bg-white px-3 py-2.5 sm:px-4">
                <h3 className="text-sm font-semibold text-gray-900">Floors & units</h3>
                <p className="mt-1 text-xs text-gray-500">
                  Add one or more floors, then multiple units on each floor.
                </p>
              </div>
            )}
            {isTown ? (
              townLayoutSection
            ) : (
              <>
                <div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
                  <div className="min-w-0 flex-1 space-y-2">
                    <p className="text-xs leading-relaxed text-gray-600 sm:text-sm">
                      Each floor becomes a structure; units belong to a floor. Add multiple units
                      per floor. One tenant per unit here (add more in admin if needed).
                    </p>
                    <p className="text-[11px] leading-relaxed text-gray-500 sm:text-xs">
                      <strong>Bulk upload</strong> opens a window; on Save, new rows are{" "}
                      <strong>merged</strong> with the layout already on this page (same floor + level
                      adds or updates units).
                    </p>
                  </div>
                  <div className="flex w-full shrink-0 flex-col gap-2 sm:w-auto sm:flex-row sm:items-center">
                    <Button
                      type="button"
                      variant="secondary"
                      size="sm"
                      className="w-full sm:w-auto"
                      onClick={openBulkModal}
                    >
                      <Upload className="mr-1 size-4" />
                      Bulk upload
                    </Button>
                    <Button
                      type="button"
                      variant="outline"
                      size="sm"
                      className="w-full sm:w-auto"
                      onClick={() => setFloors((prev) => [...prev, emptyFloor()])}
                    >
                      <Plus className="mr-1 size-4" />
                      Floor
                    </Button>
                  </div>
                </div>

                <div className="space-y-6">
                  {floors.map((floor, fi) => (
                    <div
                      key={floor.key}
                      className="rounded-lg border border-gray-200 bg-gray-50/50 p-4"
                    >
                      <div className="mb-3 flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:items-end">
                        <div className="min-w-0 flex-1 sm:min-w-[140px]">
                          <Label className="text-xs sm:text-sm">Floor name</Label>
                          <Input
                            placeholder="e.g. Ground, 1st Floor"
                            value={floor.name}
                            onChange={(e) => {
                              const v = e.target.value;
                              setFloors((prev) =>
                                prev.map((f, i) => (i === fi ? { ...f, name: v } : f))
                              );
                            }}
                          />
                        </div>
                        <div className="w-full sm:w-24">
                          <Label className="text-xs sm:text-sm">Level</Label>
                          <Input
                            type="number"
                            className="[appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
                            value={floor.level}
                            onChange={(e) => {
                              const v = e.target.value;
                              setFloors((prev) =>
                                prev.map((f, i) => (i === fi ? { ...f, level: v } : f))
                              );
                            }}
                          />
                        </div>
                        <Button
                          type="button"
                          variant="ghost"
                          size="icon"
                          className="self-end text-red-600 sm:self-auto"
                          onClick={() =>
                            setFloors((prev) =>
                              prev.length <= 1 ? prev : prev.filter((_, i) => i !== fi)
                            )
                          }
                          disabled={floors.length === 1}
                        >
                          <Trash2 className="size-4" />
                        </Button>
                      </div>

                      <div className="space-y-3">
                        <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
                          <span className="text-[11px] font-medium uppercase tracking-wide text-gray-500 sm:text-xs">
                            Units on this floor
                          </span>
                          <Button
                            type="button"
                            variant="secondary"
                            size="sm"
                            className="w-full sm:w-auto"
                            onClick={() =>
                              setFloors((prev) =>
                                prev.map((f, i) =>
                                  i === fi ? { ...f, units: [...f.units, emptyUnit()] } : f
                                )
                              )
                            }
                          >
                            <Plus className="mr-1 size-4" />
                            Unit
                          </Button>
                        </div>

                        {floor.units.map((unit, ui) => (
                          <div
                            key={unit.key}
                            className="grid grid-cols-1 gap-3 rounded-md border bg-white p-3 sm:grid-cols-[minmax(0,7rem)_minmax(0,9rem)_minmax(0,5.5rem)_minmax(0,1fr)_auto] sm:items-end"
                          >
                            <div className="min-w-0">
                              <Label className="text-xs">Unit #</Label>
                              <Input
                                placeholder="101"
                                value={unit.unitNumber}
                                onChange={(e) => {
                                  const v = e.target.value;
                                  setFloors((prev) =>
                                    prev.map((f, i) =>
                                      i === fi
                                        ? {
                                            ...f,
                                            units: f.units.map((u, j) =>
                                              j === ui ? { ...u, unitNumber: v } : u
                                            ),
                                          }
                                        : f
                                    )
                                  );
                                }}
                              />
                            </div>
                            <div className="min-w-0">
                              <Label className="text-xs">Type</Label>
                              <Select
                                value={unit.type}
                                onValueChange={(v) => {
                                  setFloors((prev) =>
                                    prev.map((f, i) =>
                                      i === fi
                                        ? {
                                            ...f,
                                            units: f.units.map((u, j) =>
                                              j === ui
                                                ? { ...u, type: v as UnitDraft["type"] }
                                                : u
                                            ),
                                          }
                                        : f
                                    )
                                  );
                                }}
                              >
                                <SelectTrigger className="min-w-0 max-w-full">
                                  <SelectValue />
                                </SelectTrigger>
                                <SelectContent>
                                  {UNIT_TYPES.map((t) => (
                                    <SelectItem key={t} value={t}>
                                      {t}
                                    </SelectItem>
                                  ))}
                                </SelectContent>
                              </Select>
                            </div>
                            <div className="min-w-0 sm:max-w-[5.5rem]">
                              <Label className="text-xs">Size (m²)</Label>
                              <Input
                                inputMode="decimal"
                                placeholder="e.g. 45"
                                value={unit.size}
                                onChange={(e) => {
                                  const v = e.target.value;
                                  setFloors((prev) =>
                                    prev.map((f, i) =>
                                      i === fi
                                        ? {
                                            ...f,
                                            units: f.units.map((u, j) =>
                                              j === ui ? { ...u, size: v } : u
                                            ),
                                          }
                                        : f
                                    )
                                  );
                                }}
                              />
                            </div>
                            <div className="min-w-0">
                              <Label className="text-xs">Tenant (optional)</Label>
                              <Select
                                value={unit.tenantUserId || "__none__"}
                                onValueChange={(v) => {
                                  const val = v === "__none__" ? "" : v;
                                  setFloors((prev) =>
                                    prev.map((f, i) =>
                                      i === fi
                                        ? {
                                            ...f,
                                            units: f.units.map((u, j) =>
                                              j === ui ? { ...u, tenantUserId: val } : u
                                            ),
                                          }
                                        : f
                                    )
                                  );
                                }}
                              >
                                <SelectTrigger className="min-w-0 max-w-full">
                                  <SelectValue placeholder="None" />
                                </SelectTrigger>
                                <SelectContent>
                                  <SelectItem value="__none__">None</SelectItem>
                                  {teamUsers.map((u) => (
                                    <SelectItem key={u._id} value={u._id}>
                                      {[u.firstName, u.lastName].filter(Boolean).join(" ") ||
                                        u.username}{" "}
                                      ({u.email})
                                    </SelectItem>
                                  ))}
                                </SelectContent>
                              </Select>
                            </div>
                            <Button
                              type="button"
                              variant="ghost"
                              size="icon"
                              className="justify-self-end text-red-600 sm:justify-self-auto"
                              onClick={() =>
                                setFloors((prev) =>
                                  prev.map((f, i) =>
                                    i === fi
                                      ? {
                                          ...f,
                                          units:
                                            f.units.filter((_, j) => j !== ui).length > 0
                                              ? f.units.filter((_, j) => j !== ui)
                                              : [emptyUnit()],
                                        }
                                      : f
                                  )
                                )
                              }
                            >
                              <Trash2 className="size-4" />
                            </Button>
                          </div>
                        ))}
                      </div>
                    </div>
                  ))}
                </div>
              </>
            )}
          </div>
        )}
      </div>

        {needsLayout ? (
          <div className="flex flex-col gap-2 border-t px-4 py-3 sm:flex-row sm:flex-wrap sm:px-6 sm:py-4">
            <Button
              variant="outline"
              className="w-full sm:w-auto"
              type="button"
              onClick={onCancel}
              disabled={saving}
            >
              Cancel
            </Button>
            <Button
              type="button"
              className="w-full sm:w-auto"
              onClick={() => void save()}
              disabled={saving || !tenantReady || loadingFull}
            >
              {saving ? "Saving…" : "Save layout"}
            </Button>
          </div>
        ) : null}
      </div>

      <Dialog
        open={bulkModalOpen}
        onOpenChange={(open) => {
          if (!open && bulkModalSaving) return;
          if (!open) resetBulkModal();
          setBulkModalOpen(open);
        }}
      >
        <DialogContent
          className="max-w-xl gap-4"
          onPointerDownOutside={(e) => bulkModalSaving && e.preventDefault()}
          onEscapeKeyDown={(e) => bulkModalSaving && e.preventDefault()}
        >
          <DialogHeader>
            <DialogTitle>Bulk upload</DialogTitle>
            <DialogDescription>
              Download the sample file, fill your rows, then drop the file here or click to browse.
              Row 1 must be headers (e.g. Floor name, Level, Unit #, Type, Size, Tenant). Saving adds
              to your current layout: same floor name + level gets new units (same unit # updates that
              unit); new floors are added.
            </DialogDescription>
          </DialogHeader>

          {(bulkPhase === "reading" || bulkPhase === "parsing") && (
            <div className="space-y-2">
              <div className="flex justify-between text-xs text-muted-foreground">
                <span>
                  {bulkPhase === "reading" ? "Reading file…" : "Processing rows…"}
                </span>
                <span>{bulkProgress}%</span>
              </div>
              <div className="h-2.5 w-full overflow-hidden rounded-full bg-muted">
                <div
                  className="h-full bg-primary transition-[width] duration-200 ease-out"
                  style={{ width: `${bulkProgress}%` }}
                />
              </div>
            </div>
          )}

          <div className="flex flex-wrap gap-2">
            <Button variant="outline" size="sm" className="gap-2" asChild>
              <a
                href="/property-bulk-layout-template.csv"
                download="property-layout-template.csv"
              >
                <FileDown className="size-4 shrink-0" />
                Download sample CSV
              </a>
            </Button>
          </div>

          <input
            ref={bulkModalFileRef}
            type="file"
            accept=".csv,.xlsx,.xls,text/csv,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
            className="hidden"
            onChange={(e) => {
              const f = e.target.files?.[0];
              e.target.value = "";
              if (f) processBulkFile(f);
            }}
          />

          <button
            type="button"
            className={cn(
              "flex min-h-[132px] w-full cursor-pointer flex-col items-center justify-center rounded-lg border-2 border-dashed px-4 py-6 text-center text-sm transition-colors outline-none focus-visible:ring-2 focus-visible:ring-ring",
              bulkDropActive ? "border-primary bg-primary/5" : "border-muted-foreground/30 hover:border-muted-foreground/50",
              bulkModalSaving && "pointer-events-none opacity-60",
              (bulkPhase === "reading" || bulkPhase === "parsing") &&
                "pointer-events-none cursor-wait opacity-70"
            )}
            onDragOver={(e) => {
              e.preventDefault();
              e.stopPropagation();
              setBulkDropActive(true);
            }}
            onDragLeave={(e) => {
              e.preventDefault();
              e.stopPropagation();
              setBulkDropActive(false);
            }}
            onDrop={(e) => {
              e.preventDefault();
              e.stopPropagation();
              setBulkDropActive(false);
              const f = e.dataTransfer.files?.[0];
              if (f) processBulkFile(f);
            }}
            onClick={() => bulkModalFileRef.current?.click()}
          >
            <Upload className="mb-2 size-8 text-muted-foreground" aria-hidden />
            <span className="font-medium text-foreground">Drag & drop CSV or Excel here</span>
            <span className="mt-1 text-xs text-muted-foreground">or click to choose a file</span>
          </button>

          {bulkPhase === "ready" && stagedBulkFloors ? (
            <p className="rounded-md border border-emerald-200 bg-emerald-50 px-3 py-2 text-sm text-emerald-900">
              Ready: <strong>{stagedBulkFloors.length}</strong> floor group(s) in file,{" "}
              <strong>
                {stagedBulkFloors.reduce((n, f) => n + f.units.length, 0)}
              </strong>{" "}
              units. <strong>Save</strong> merges this with floors already below (same floor + level:
              units added or updated by unit #).
            </p>
          ) : null}

          {stagedBulkWarnings.length > 0 ? (
            <div className="max-h-24 overflow-y-auto rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-950">
              <p className="mb-1 font-medium">Notes</p>
              <ul className="list-inside list-disc space-y-0.5">
                {stagedBulkWarnings.slice(0, 12).map((w, i) => (
                  <li key={i}>{w}</li>
                ))}
              </ul>
              {stagedBulkWarnings.length > 12 ? (
                <p className="mt-1 text-amber-800">+{stagedBulkWarnings.length - 12} more…</p>
              ) : null}
            </div>
          ) : null}

          <DialogFooter className="gap-2 sm:gap-0">
            <Button
              type="button"
              variant="outline"
              disabled={bulkModalSaving}
              onClick={() => {
                setBulkModalOpen(false);
                resetBulkModal();
              }}
            >
              Cancel
            </Button>
            <Button
              type="button"
              disabled={
                bulkModalSaving ||
                bulkPhase !== "ready" ||
                !stagedBulkFloors ||
                !tenantReady
              }
              onClick={() => void saveBulkFromModal()}
            >
              {bulkModalSaving ? "Saving…" : "Save"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </>
  );
}
