"use client";

import React, { useEffect, useMemo, useRef, useState } from "react";
import Link from "next/link";
import { useParams } from "next/navigation";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { getApiErrorMessage } from "@/lib/api-error";
import { uploadTenantImageFile } from "@/lib/upload-tenant-image";
import {
  useCreateTenantDirectoryUserMutation,
  useDeleteTenantPropertyMutation,
  useGetTenantAssignableRolesQuery,
  useGetTenantPropertiesQuery,
  useUpdateTenantPropertyMutation,
} from "@/redux/api";
import { toast } from "sonner";
import { CircleDollarSign, Filter, LayoutGrid, Pencil, Search, Trash2, X } from "lucide-react";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import ClientWorkspaceLayout, {
  type ClientWorkspaceChildCtx,
} from "./client-workspace-layout";
import type { PropertyRow } from "./property-types";
import PropertyMaintenanceEditorForm from "./property-editor/property-maintenance-editor-form";
import noPropertyImage from "@/assets/images/No_Image_Available.jpg";

const NO_PROPERTY_IMAGE_SRC =
  typeof noPropertyImage === "string" ? noPropertyImage : noPropertyImage.src;

function propertyHasPhasesOrFloorsLayout(p: PropertyRow): boolean {
  const s = (p.siteType || "").toLowerCase();
  return s === "plaza" || s === "town" || s === "society";
}

function PropertyPhotoCell({
  property: p,
  uploading,
  uploadLocked,
  onFileChosen,
}: {
  property: PropertyRow;
  uploading: boolean;
  /** True while any row is uploading — avoids overlapping requests. */
  uploadLocked: boolean;
  onFileChosen: (files: FileList | null) => void;
}) {
  const inputRef = useRef<HTMLInputElement>(null);

  const displaySrc =
    p.photo != null && String(p.photo).trim() !== ""
      ? String(p.photo).trim()
      : NO_PROPERTY_IMAGE_SRC;

  return (
    <div className="flex flex-col items-start gap-1">
      {/* eslint-disable-next-line @next/next/no-img-element -- remote API URLs + static fallback */}
      <img
        src={displaySrc}
        alt=""
        onError={(e: React.SyntheticEvent<HTMLImageElement>) => {
          e.currentTarget.onerror = null;
          e.currentTarget.src = NO_PROPERTY_IMAGE_SRC;
        }}
        className="size-14 rounded border border-gray-200 object-cover"
      />
      <input
        ref={inputRef}
        type="file"
        aria-label={`Upload photo for ${p.name}`}
        className="hidden"
        accept="image/png,image/jpeg,image/jpg,image/webp,image/gif"
        onChange={(e) => {
          onFileChosen(e.target.files);
          e.target.value = "";
        }}
      />

    </div>
  );
}

function ClientPropertiesTableBody({ ctx }: { ctx: ClientWorkspaceChildCtx }) {
  const { app } = useParams() as { app: string };
  const base = `/${app}/properties`;
  const { tenantApiKey, tenantReady, moduleBlockedProperty: moduleBlocked } = ctx;
  const [idModalOpen, setIdModalOpen] = useState(false);
  const [modalPropertyId, setModalPropertyId] = useState<string | null>(null);
  const [resFirst, setResFirst] = useState("");
  const [resLast, setResLast] = useState("");
  const [resEmail, setResEmail] = useState("");
  const [resPassword, setResPassword] = useState("");
  const [resRoleId, setResRoleId] = useState("");
  const [tenantSubmitting, setTenantSubmitting] = useState(false);
  const [photoUploadingId, setPhotoUploadingId] = useState<string | null>(null);
  const [maintenanceProperty, setMaintenanceProperty] = useState<PropertyRow | null>(null);
  const [searchInput, setSearchInput] = useState("");
  const [appliedSearch, setAppliedSearch] = useState("");
  const [page, setPage] = useState(1);
  const pageSize = 10;

  const skipTenant = !tenantReady || moduleBlocked;
  const { data: properties = [], isFetching: listLoading } =
    useGetTenantPropertiesQuery(tenantApiKey, { skip: skipTenant });

  const { data: assignableRoles = [] } = useGetTenantAssignableRolesQuery(
    tenantApiKey,
    { skip: !idModalOpen || skipTenant },
  );

  const [deleteProperty] = useDeleteTenantPropertyMutation();
  const [updateProperty] = useUpdateTenantPropertyMutation();
  const [createTenantUser] = useCreateTenantDirectoryUserMutation();

  const normalizedAppliedSearch = appliedSearch.trim().toLowerCase();
  const filteredProperties = useMemo(() => {
    if (!normalizedAppliedSearch) return properties;
    return properties.filter((p) => {
      const haystack = [
        p.name || "",
        p.type || "",
        p.siteType || "",
        p.address?.street || "",
        p.address?.city || "",
        p.address?.area || "",
      ]
        .join(" ")
        .toLowerCase();
      return haystack.includes(normalizedAppliedSearch);
    });
  }, [properties, normalizedAppliedSearch]);
  const totalPages = Math.max(1, Math.ceil(filteredProperties.length / pageSize));
  const pagedProperties = useMemo(() => {
    const start = (page - 1) * pageSize;
    return filteredProperties.slice(start, start + pageSize);
  }, [filteredProperties, page]);
  const filterIsActive =
    normalizedAppliedSearch.length > 0 &&
    searchInput.trim().toLowerCase() === normalizedAppliedSearch;

  useEffect(() => {
    if (page > totalPages) setPage(totalPages);
  }, [page, totalPages]);

  const resetResidentForm = () => {
    setResFirst("");
    setResLast("");
    setResEmail("");
    setResPassword("");
    setResRoleId("");
  };

  const submitResidentForm = () => {
    if (!modalPropertyId || !tenantReady) return;
    if (!resFirst.trim() || !resLast.trim()) {
      toast.error("First and last name are required");
      return;
    }
    if (!resEmail.trim()) {
      toast.error("Email is required");
      return;
    }
    if (resPassword.length < 8) {
      toast.error("Password must be at least 8 characters");
      return;
    }
    if (!resRoleId) {
      toast.error("Select a role");
      return;
    }
    setTenantSubmitting(true);
    void (async () => {
      try {
        await createTenantUser({
          tenantKey: tenantApiKey,
          body: {
            firstName: resFirst.trim(),
            lastName: resLast.trim(),
            email: resEmail.trim(),
            password: resPassword,
            role: resRoleId,
            propertyId: modalPropertyId,
          },
        }).unwrap();
        toast.success("Tenant user added");
        setIdModalOpen(false);
        setModalPropertyId(null);
        resetResidentForm();
      } catch (e: unknown) {
        toast.error(getApiErrorMessage(e, "Could not add user"));
      } finally {
        setTenantSubmitting(false);
      }
    })();
  };

  const onPropertyPhotoSelected = (p: PropertyRow, fileList: FileList | null) => {
    const file = fileList?.[0];
    if (!file || !tenantReady) return;
    setPhotoUploadingId(p._id);
    void (async () => {
      try {
        const url = await uploadTenantImageFile(tenantApiKey, file);
        await updateProperty({
          tenantKey: tenantApiKey,
          propertyId: p._id,
          body: { photo: url },
        }).unwrap();
        toast.success("Property photo updated");
      } catch (e: unknown) {
        toast.error(getApiErrorMessage(e, "Could not update photo"));
      } finally {
        setPhotoUploadingId(null);
      }
    })();
  };

  const remove = async (p: PropertyRow) => {
    if (!tenantReady) return;
    if (!confirm(`Delete property “${p.name}”? This removes structures and units under it.`))
      return;
    try {
      await deleteProperty({
        tenantKey: tenantApiKey,
        propertyId: p._id,
      }).unwrap();
      toast.success("Property deleted");
    } catch (e: unknown) {
      toast.error(getApiErrorMessage(e, "Could not delete property"));
    }
  };

  const handleFilterButtonClick = () => {
    if (filterIsActive) {
      setAppliedSearch("");
      setSearchInput("");
      setPage(1);
      return;
    }
    setAppliedSearch(searchInput.trim());
    setPage(1);
  };

  if (!tenantReady) {
    return <p className="text-sm text-gray-500">Select a client to load properties.</p>;
  }

  if (moduleBlocked) {
    return (
      <p className="rounded-md border border-amber-200 bg-amber-50 p-4 text-sm text-amber-900">
        The Property module is not enabled for this organization. You cannot view or edit properties
        until an administrator enables the module for this client.
      </p>
    );
  }

  return (
    <>
      <div className="min-w-0 overflow-hidden rounded-xl border bg-white">
        <div className="space-y-3 border-b px-3 py-3 sm:px-4">
          <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
            <h2 className="font-semibold text-gray-900">Properties</h2>
            <div className="flex w-full flex-col gap-2 sm:w-auto sm:flex-row sm:items-center sm:justify-end">
              <div className="relative w-full sm:w-56">
                <Search className="pointer-events-none absolute left-2.5 top-1/2 size-4 -translate-y-1/2 text-gray-400" />
                <Input
                  className="h-9 pl-8"
                  placeholder="Search"
                  value={searchInput}
                  onChange={(e) => setSearchInput(e.target.value)}
                />
              </div>
              <Button
                type="button"
                variant="outline"
                size="sm"
                className="h-9 px-3"
                onClick={handleFilterButtonClick}
              >
                {filterIsActive ? (
                  <X className="mr-2 size-4" />
                ) : (
                  <Filter className="mr-2 size-4" />
                )}
                {filterIsActive ? "Cancel" : "Filters"}
              </Button>
              {tenantReady ? (
                <Button size="sm" className="h-9 px-4" asChild>
                  <Link href={`${base}/new`}>Add property</Link>
                </Button>
              ) : (
                <Button size="sm" className="h-9 px-4" disabled>
                  Add property
                </Button>
              )}
            </div>
          </div>
        </div>
        {listLoading ? (
          <div className="p-6 text-center text-sm text-gray-500 sm:p-8">Loading properties…</div>
        ) : (
          <Table className="min-w-[1080px]">
            <TableHeader>
              <TableRow className="bg-muted/30">
                <TableHead className="w-[100px]">Photo</TableHead>
                <TableHead>Name</TableHead>
                <TableHead>Usage</TableHead>
                <TableHead>Site layout</TableHead>
                <TableHead>Address</TableHead>
                <TableHead>City</TableHead>
                <TableHead>Area</TableHead>
                <TableHead className="w-[220px] sm:w-[240px]" />
              </TableRow>
            </TableHeader>
            <TableBody>
              {pagedProperties.length === 0 ? (
                <TableRow>
                  <TableCell colSpan={8} className="text-center text-gray-400">
                    {normalizedAppliedSearch
                      ? "No properties match your current filter."
                      : "No properties yet. Click Add property to create one."}
                  </TableCell>
                </TableRow>
              ) : (
                pagedProperties.map((p) => (
                  <TableRow key={p._id}>
                    <TableCell className="align-middle">
                      <PropertyPhotoCell
                        property={p}
                        uploading={photoUploadingId === p._id}
                        uploadLocked={photoUploadingId !== null}
                        onFileChosen={(files) => onPropertyPhotoSelected(p, files)}
                      />
                    </TableCell>
                    <TableCell className="font-medium">{p.name}</TableCell>
                    <TableCell>{p.type}</TableCell>
                    <TableCell className="capitalize text-gray-700">
                      {p.siteType || "—"}
                    </TableCell>
                    <TableCell className="max-w-[200px] truncate text-gray-700">
                      {p.address?.street?.trim() || "—"}
                    </TableCell>
                    <TableCell>{p.address?.city || "—"}</TableCell>
                    <TableCell>{p.address?.area || "—"}</TableCell>
                    <TableCell className="flex shrink-0 flex-nowrap justify-end gap-1 sm:gap-2">
                      {/* <Button
                        variant="outline"
                        size="icon"
                        aria-label="Add user for this property"
                        onClick={() => {
                          setModalPropertyId(p._id);
                          setIdModalOpen(true);
                        }}
                      >
                        <UserPlus className="size-4" />
                      </Button> */}
                      <Button variant="outline" size="icon" asChild title="More details">
                        <Link
                          href={`${base}/${p._id}/more-details`}
                          aria-label="More details — floors and units"
                        >
                          <LayoutGrid className="size-4" />
                        </Link>
                      </Button>
                      <Button
                        variant="outline"
                        size="icon"
                        title="Maintenance charges"
                        aria-label="Maintenance charges"
                        onClick={() => setMaintenanceProperty(p)}
                      >
                        <CircleDollarSign className="size-4" />
                      </Button>
                      <Button variant="outline" size="icon" asChild>
                        <Link href={`${base}/${p._id}/edit`} aria-label="Edit property">
                          <Pencil className="size-4" />
                        </Link>
                      </Button>

                      <Button variant="outline" size="icon" onClick={() => remove(p)}>
                        <Trash2 className="size-4 text-red-600" />
                      </Button>
                    </TableCell>
                  </TableRow>
                ))
              )}
            </TableBody>
          </Table>
        )}
        <div className="flex items-center justify-between border-t px-3 py-3 sm:px-4">
          <Button
            type="button"
            variant="outline"
            size="sm"
            disabled={page <= 1 || listLoading}
            onClick={() => setPage((prev) => Math.max(1, prev - 1))}
          >
            Previous
          </Button>
          <p className="text-xs text-gray-500">{`Page ${page} of ${totalPages}`}</p>
          <Button
            type="button"
            variant="outline"
            size="sm"
            disabled={page >= totalPages || listLoading}
            onClick={() => setPage((prev) => Math.min(totalPages, prev + 1))}
          >
            Next
          </Button>
        </div>
      </div>

      <Dialog
        open={maintenanceProperty !== null}
        onOpenChange={(open) => {
          if (!open) setMaintenanceProperty(null);
        }}
      >
        <DialogContent className="max-h-[min(90vh,100dvh)] w-[calc(100vw-1rem)] max-w-md gap-4 overflow-y-auto p-4 sm:p-6">
          {maintenanceProperty ? (
            <>
              <DialogHeader className="space-y-1.5 text-left">
                <DialogTitle className="text-base sm:text-lg">Maintenance charges</DialogTitle>
                <DialogDescription>
                  Default maintenance for{" "}
                  <span className="font-medium text-foreground">{maintenanceProperty.name}</span>.
                  Used when user billing is set to Standard.
                </DialogDescription>
              </DialogHeader>
              <PropertyMaintenanceEditorForm
                ctx={ctx}
                property={maintenanceProperty}
                listHref={base}
                embedded
                onCancel={() => setMaintenanceProperty(null)}
                onSaved={() => setMaintenanceProperty(null)}
              />
            </>
          ) : null}
        </DialogContent>
      </Dialog>

      <Dialog
        open={idModalOpen}
        onOpenChange={(open) => {
          setIdModalOpen(open);
          if (!open) {
            setModalPropertyId(null);
            resetResidentForm();
          }
        }}
      >
        <DialogContent className="max-h-[min(90vh,100dvh)] w-[calc(100vw-1rem)] max-w-lg gap-4 overflow-y-auto p-4 sm:p-6">
          <DialogHeader className="space-y-1 text-left">
            <DialogTitle className="text-base sm:text-lg">Add Tenant</DialogTitle>
          </DialogHeader>
          <div className="grid gap-3 py-2">
            <div className="grid gap-2 sm:grid-cols-2">
              <div>
                <Label htmlFor="prop-res-fn">First name</Label>
                <Input
                  id="prop-res-fn"
                  value={resFirst}
                  onChange={(e) => setResFirst(e.target.value)}
                />
              </div>
              <div>
                <Label htmlFor="prop-res-ln">Last name</Label>
                <Input id="prop-res-ln" value={resLast} onChange={(e) => setResLast(e.target.value)} />
              </div>
            </div>
            <div>
              <Label htmlFor="prop-res-em">Email</Label>
              <Input
                id="prop-res-em"
                type="email"
                value={resEmail}
                onChange={(e) => setResEmail(e.target.value)}
              />
            </div>
            <div>
              <Label htmlFor="prop-res-pw">Password</Label>
              <Input
                id="prop-res-pw"
                type="password"
                autoComplete="new-password"
                value={resPassword}
                onChange={(e) => setResPassword(e.target.value)}
              />
            </div>
            <div>
              <Label>Role</Label>
              <Select value={resRoleId} onValueChange={setResRoleId}>
                <SelectTrigger className="min-w-0 max-w-full">
                  <SelectValue placeholder="Select role" />
                </SelectTrigger>
                <SelectContent>
                  {assignableRoles.map((r) => (
                    <SelectItem key={r._id} value={r._id}>
                      {r.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <p className="text-xs text-gray-500">
              Create a custom role on the{" "}
              <Link href={`/${app}/roles`} className="font-medium text-primary underline">
                Roles
              </Link>{" "}
              page if you need a new label (e.g. Tenant).
            </p>
          </div>
          <DialogFooter className="gap-2 sm:gap-0">
            <Button
              type="button"
              variant="outline"
              className="w-full sm:w-auto"
              onClick={() => {
                setIdModalOpen(false);
                setModalPropertyId(null);
                resetResidentForm();
              }}
            >
              Cancel
            </Button>
            <Button
              type="button"
              className="w-full sm:w-auto"
              disabled={tenantSubmitting}
              onClick={submitResidentForm}
            >
              {tenantSubmitting ? "Adding…" : "Add user"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </>
  );
}

export default function ClientPropertiesListPage() {
  return (
    <ClientWorkspaceLayout
      title=""
      barDescription="Listed properties belong to the client selected above."
    >
      {(ctx) => <ClientPropertiesTableBody ctx={ctx} />}
    </ClientWorkspaceLayout>
  );
}
