"use client";

import { useMemo, useState } from "react";
import { useLang } from "@/context/LanguageContext";
import {
  Alert,
  Button,
  Card,
  DatePicker,
  EmptyState,
  Input,
  Modal,
  PageHeader,
  PageLoader,
  Pagination,
  Select,
  StatCard,
  usePagination,
} from "@/components/ui";
import { api, useApi } from "@/lib/client";
import { formatBDT, formatDate } from "@/lib/utils";
import { ATTENDANCE_STATUSES, HOSTEL_TYPES, ROOM_TYPES } from "@/lib/constants";
import { emsConfirm } from "@/components/ConfirmDialog";
import {
  IconCheck,
  IconEdit,
  IconHome,
  IconLayers,
  IconPlus,
  IconTrash,
  IconUserCheck,
  IconUsers,
} from "@/components/icons";

interface HostelRow {
  id: number;
  name: string;
  nameBn: string | null;
  type: string;
  wardenName: string | null;
  wardenPhone: string | null;
  monthlyFee: number;
  isActive: boolean;
  roomCount: number;
  residentCount: number;
}

interface RoomRow {
  id: number;
  hostelId: number;
  hostelName: string | null;
  roomNo: string;
  floor: number;
  capacity: number;
  roomType: string;
  monthlyFee: number;
  occupied: number;
}

interface MemberRow {
  id: number;
  studentId: number;
  roll: string;
  studentName: string;
  className: string | null;
  hostelId: number;
  hostelName: string;
  roomId: number | null;
  roomNo: string | null;
  bedNo: string | null;
  monthlyFee: number;
  joinDate: string;
  status: string;
}

interface HostelData {
  stats: {
    hostels: number;
    activeHostels: number;
    rooms: number;
    capacity: number;
    residents: number;
    vacantBeds: number;
    monthlyExpected: number;
    todayPresent: number;
    todayAbsent: number;
    todayLeave: number;
  };
  hostels: HostelRow[];
  rooms: RoomRow[];
  members: MemberRow[];
}

interface AttEntry {
  memberId: number;
  roll: string;
  studentName: string;
  nameBn: string | null;
  hostelName: string;
  roomNo: string | null;
  bedNo: string | null;
  status: string | null;
  note: string | null;
}

interface AttendanceData {
  date: string;
  entries: AttEntry[];
  counts: { marked: number; present: number; absent: number; leave: number };
}

interface StudentMini {
  id: number;
  roll: string;
  name: string;
}

type Tab = "hostels" | "rooms" | "residents" | "attendance";

const emptyHostelForm = {
  name: "",
  nameBn: "",
  type: "BOYS",
  wardenName: "",
  wardenPhone: "",
  monthlyFee: "0",
};

const emptyRoomForm = {
  hostelId: "",
  roomNo: "",
  floor: "0",
  capacity: "4",
  roomType: "SHARED",
  monthlyFee: "0",
};

export default function PortalHostelPage() {
  const { t, locale } = useLang();
  const [tab, setTab] = useState<Tab>("hostels");
  const [message, setMessage] = useState<{ type: "success" | "error"; text: string } | null>(null);

  const { data, loading, reload } = useApi<HostelData>("/api/portal/hostel");
  const { data: studentsData } = useApi<{ students: StudentMini[] }>("/api/portal/students");

  // Hostel form
  const [formOpen, setFormOpen] = useState(false);
  const [editingHostel, setEditingHostel] = useState<HostelRow | null>(null);
  const [hostelForm, setHostelForm] = useState(emptyHostelForm);
  const [saving, setSaving] = useState(false);
  const [search, setSearch] = useState("");

  // Room form
  const [roomOpen, setRoomOpen] = useState(false);
  const [editingRoom, setEditingRoom] = useState<RoomRow | null>(null);
  const [roomForm, setRoomForm] = useState(emptyRoomForm);
  const [roomSaving, setRoomSaving] = useState(false);
  const [roomHostelFilter, setRoomHostelFilter] = useState("");
  const [roomQ, setRoomQ] = useState("");
  const [roomTypeFilter, setRoomTypeFilter] = useState("");
  const [hostelQ, setHostelQ] = useState("");
  const [hostelTypeFilter, setHostelTypeFilter] = useState("");
  const [resHostel, setResHostel] = useState("");
  const [resStatus, setResStatus] = useState("");
  const [attQ, setAttQ] = useState("");

  // Allocation form
  const [assignForm, setAssignForm] = useState({ studentId: "", hostelId: "", roomId: "", bedNo: "", monthlyFee: "" });
  const [assignSaving, setAssignSaving] = useState(false);

  // Change room modal
  const [moveMember, setMoveMember] = useState<MemberRow | null>(null);
  const [moveForm, setMoveForm] = useState({ hostelId: "", roomId: "", bedNo: "" });
  const [moveSaving, setMoveSaving] = useState(false);

  // Attendance
  const today = new Date().toISOString().slice(0, 10);
  const [attDate, setAttDate] = useState(today);
  const { data: att, loading: attLoading, reload: attReload } = useApi<AttendanceData>(
    `/api/portal/hostel/attendance?date=${attDate}`
  );
  const [attDraft, setAttDraft] = useState<Record<number, string>>({});
  const [attSaving, setAttSaving] = useState(false);

  const filteredRooms = useMemo(() => {
    if (!data) return [];
    const q = roomQ.trim().toLowerCase();
    return data.rooms.filter(
      (r) =>
        (!roomHostelFilter || r.hostelId === Number(roomHostelFilter)) &&
        (!q || r.roomNo.toLowerCase().includes(q) || (r.hostelName ?? "").toLowerCase().includes(q)) &&
        (!roomTypeFilter || r.roomType === roomTypeFilter),
    );
  }, [data, roomHostelFilter, roomQ, roomTypeFilter]);

  const residents = useMemo(() => {
    if (!data) return [];
    const q = search.trim().toLowerCase();
    return data.members.filter(
      (m) =>
        (!q || m.studentName.toLowerCase().includes(q) || m.roll.toLowerCase().includes(q) || (m.roomNo ?? "").toLowerCase().includes(q)) &&
        (!resHostel || m.hostelId === Number(resHostel)) &&
        (!resStatus || m.status === resStatus),
    );
  }, [data, search, resHostel, resStatus]);

  const hostels = useMemo(() => {
    if (!data) return [];
    const q = hostelQ.trim().toLowerCase();
    return data.hostels.filter(
      (h) =>
        (!q || h.name.toLowerCase().includes(q) || (h.nameBn ?? "").toLowerCase().includes(q) || (h.wardenName ?? "").toLowerCase().includes(q)) &&
        (!hostelTypeFilter || h.type === hostelTypeFilter),
    );
  }, [data, hostelQ, hostelTypeFilter]);

  const hostelsPager = usePagination(hostels, 10);
  const filteredRoomsPager = usePagination(filteredRooms, 10);
  const residentsPager = usePagination(residents, 10);

  /** Students not yet living in any hostel. */
  const allocatableStudents = useMemo(() => {
    const assigned = new Set((data?.members ?? []).map((m) => m.studentId));
    return (studentsData?.students ?? []).filter((s) => !assigned.has(s.id));
  }, [data, studentsData]);

  /** Rooms of the currently selected hostel that still have free beds. */
  function freeRooms(hostelId: string, dataOverride?: HostelData, excludeMemberId?: number) {
    const src = dataOverride ?? data;
    const activeIn = (roomId: number) =>
      (src?.members ?? []).filter((m) => m.roomId === roomId && m.status === "ACTIVE" && m.id !== excludeMemberId).length;
    return (src?.rooms ?? []).filter(
      (r) => String(r.hostelId) === hostelId && activeIn(r.id) < r.capacity
    );
  }

  const assignRooms = freeRooms(assignForm.hostelId);
  const moveRooms = moveMember ? freeRooms(moveForm.hostelId, undefined, moveMember.id) : [];

  function notify(type: "success" | "error", text: string) {
    setMessage({ type, text });
    window.scrollTo({ top: 0, behavior: "smooth" });
  }

  /* ------------------ Hostels tab ------------------ */

  function openCreateHostel() {
    setEditingHostel(null);
    setHostelForm(emptyHostelForm);
    setFormOpen(true);
  }

  function openEditHostel(h: HostelRow) {
    setEditingHostel(h);
    setHostelForm({
      name: h.name,
      nameBn: h.nameBn ?? "",
      type: HOSTEL_TYPES.includes(h.type as never) ? h.type : "BOYS",
      wardenName: h.wardenName ?? "",
      wardenPhone: h.wardenPhone ?? "",
      monthlyFee: String(h.monthlyFee),
    });
    setFormOpen(true);
  }

  async function saveHostel() {
    setSaving(true);
    try {
      if (editingHostel) {
        await api(`/api/portal/hostel/${editingHostel.id}`, {
          method: "PUT",
          body: JSON.stringify(hostelForm),
        });
        notify("success", t.portal.hostelPage.hostelUpdated);
      } else {
        await api("/api/portal/hostel", { method: "POST", body: JSON.stringify(hostelForm) });
        notify("success", t.portal.hostelPage.hostelCreated);
      }
      setFormOpen(false);
      reload();
    } catch {
      notify("error", t.common.tryAgain);
    } finally {
      setSaving(false);
    }
  }

  async function removeHostel(h: HostelRow) {
    if (!(await emsConfirm({ message: t.common.confirmDelete, danger: true }))) return;
    try {
      await api(`/api/portal/hostel/${h.id}`, { method: "DELETE" });
      notify("success", t.common.deletedSuccessfully);
      reload();
    } catch (e) {
      const err = e instanceof Error ? e.message : "";
      notify("error", err === "IN_USE" ? t.portal.hostelPage.hostelInUse : t.common.tryAgain);
    }
  }

  /* ------------------ Rooms tab ------------------ */

  function openCreateRoom() {
    setEditingRoom(null);
    setRoomForm({
      ...emptyRoomForm,
      hostelId: roomHostelFilter || (data?.hostels[0] ? String(data.hostels[0].id) : ""),
    });
    setRoomOpen(true);
  }

  function openEditRoom(r: RoomRow) {
    setEditingRoom(r);
    setRoomForm({
      hostelId: String(r.hostelId),
      roomNo: r.roomNo,
      floor: String(r.floor),
      capacity: String(r.capacity),
      roomType: ROOM_TYPES.includes(r.roomType as never) ? r.roomType : "SHARED",
      monthlyFee: String(r.monthlyFee),
    });
    setRoomOpen(true);
  }

  async function saveRoom() {
    setRoomSaving(true);
    try {
      if (editingRoom) {
        await api(`/api/portal/hostel/rooms/${editingRoom.id}`, {
          method: "PUT",
          body: JSON.stringify(roomForm),
        });
        notify("success", t.portal.hostelPage.roomUpdated);
      } else {
        await api("/api/portal/hostel/rooms", { method: "POST", body: JSON.stringify(roomForm) });
        notify("success", t.portal.hostelPage.roomCreated);
      }
      setRoomOpen(false);
      reload();
    } catch (e) {
      const err = e instanceof Error ? e.message : "";
      notify(
        "error",
        err === "DUPLICATE_ROOM"
          ? t.portal.hostelPage.duplicateRoom
          : err === "CAPACITY_BELOW_OCCUPANCY"
            ? t.portal.hostelPage.capacityBelowOccupancy
            : t.common.tryAgain
      );
    } finally {
      setRoomSaving(false);
    }
  }

  async function removeRoom(r: RoomRow) {
    if (!(await emsConfirm({ message: t.common.confirmDelete, danger: true }))) return;
    try {
      await api(`/api/portal/hostel/rooms/${r.id}`, { method: "DELETE" });
      notify("success", t.common.deletedSuccessfully);
      reload();
    } catch (e) {
      const err = e instanceof Error ? e.message : "";
      notify("error", err === "IN_USE" ? t.portal.hostelPage.roomInUse : t.common.tryAgain);
    }
  }

  /* ------------------ Residents tab ------------------ */

  async function allocateStudent() {
    setAssignSaving(true);
    try {
      await api("/api/portal/hostel/members", {
        method: "POST",
        body: JSON.stringify(assignForm),
      });
      setAssignForm({ studentId: "", hostelId: "", roomId: "", bedNo: "", monthlyFee: "" });
      reload();
      notify("success", t.portal.hostelPage.memberAssigned);
    } catch (e) {
      const err = e instanceof Error ? e.message : "";
      notify(
        "error",
        err === "ALREADY_MEMBER"
          ? t.portal.hostelPage.alreadyMember
          : err === "ROOM_FULL"
            ? t.portal.hostelPage.roomFull
            : t.common.tryAgain
      );
    } finally {
      setAssignSaving(false);
    }
  }

  function openMove(m: MemberRow) {
    setMoveMember(m);
    setMoveForm({ hostelId: String(m.hostelId), roomId: m.roomId ? String(m.roomId) : "", bedNo: m.bedNo ?? "" });
  }

  async function saveMove() {
    if (!moveMember) return;
    setMoveSaving(true);
    try {
      await api(`/api/portal/hostel/members/${moveMember.id}`, {
        method: "PUT",
        body: JSON.stringify(moveForm),
      });
      setMoveMember(null);
      reload();
      notify("success", t.portal.hostelPage.memberUpdated);
    } catch (e) {
      const err = e instanceof Error ? e.message : "";
      notify("error", err === "ROOM_FULL" ? t.portal.hostelPage.roomFull : t.common.tryAgain);
    } finally {
      setMoveSaving(false);
    }
  }

  async function vacate(m: MemberRow) {
    if (!(await emsConfirm({ message: t.portal.hostelPage.vacateConfirm, danger: false }))) return;
    try {
      await api(`/api/portal/hostel/members/${m.id}`, { method: "DELETE" });
      reload();
      notify("success", t.portal.hostelPage.memberRemoved);
    } catch {
      notify("error", t.common.tryAgain);
    }
  }

  /* ------------------ Attendance tab ------------------ */

  async function saveAttendance() {
    if (!att) return;
    const entries = Object.entries(attDraft).map(([memberId, status]) => ({ memberId: Number(memberId), status }));
    if (entries.length === 0) return;
    setAttSaving(true);
    try {
      await api("/api/portal/hostel/attendance", {
        method: "POST",
        body: JSON.stringify({ date: att.date, entries }),
      });
      setAttDraft({});
      attReload();
      reload();
      notify("success", t.portal.hostelPage.attendanceSaved);
    } catch {
      notify("error", t.common.tryAgain);
    } finally {
      setAttSaving(false);
    }
  }

  if (loading) return <PageLoader text={t.common.loading} />;
  const s = data?.stats;

  return (
    <div>
      <PageHeader
        title={t.portal.hostelPage.title}
        subtitle={t.portal.hostelPage.subtitle}
        action={
          <span className="badge badge-secondary px-3 py-2">{t.portal.hostelPage.feeNote}</span>
        }
      />

      {message && (
        <div className="mb-4">
          <Alert type={message.type} onClose={() => setMessage(null)}>{message.text}</Alert>
        </div>
      )}

      {/* Stats */}
      <div className="row g-3 mb-4">
        <div className="col-xl-2 col-sm-4 col-6">
          <StatCard label={t.portal.hostelPage.totalHostels} value={String(s?.hostels ?? 0)} icon={<IconHome />} accent="teal" />
        </div>
        <div className="col-xl-2 col-sm-4 col-6">
          <StatCard label={t.portal.hostelPage.totalRooms} value={String(s?.rooms ?? 0)} icon={<IconLayers />} accent="blue" />
        </div>
        <div className="col-xl-2 col-sm-4 col-6">
          <StatCard label={t.portal.hostelPage.capacity} value={String(s?.capacity ?? 0)} icon={<IconHome />} accent="sky" />
        </div>
        <div className="col-xl-2 col-sm-4 col-6">
          <StatCard label={t.portal.hostelPage.residents} value={String(s?.residents ?? 0)} icon={<IconUsers />} accent="purple" />
        </div>
        <div className="col-xl-2 col-sm-4 col-6">
          <StatCard label={t.portal.hostelPage.vacantBeds} value={String(s?.vacantBeds ?? 0)} icon={<IconUserCheck />} accent="orange" />
        </div>
        <div className="col-xl-2 col-sm-4 col-6">
          <StatCard label={t.portal.hostelPage.monthlyExpected} value={formatBDT(s?.monthlyExpected ?? 0, locale)} icon={<IconCheck />} accent="red" />
        </div>
      </div>

      {/* Tabs */}
      <ul className="nav nav-tabs mb-4" role="tablist">
        {(["hostels", "rooms", "residents", "attendance"] as Tab[]).map((key) => {
          const labels: Record<Tab, string> = {
            hostels: t.portal.hostelPage.tabHostels,
            rooms: t.portal.hostelPage.tabRooms,
            residents: t.portal.hostelPage.tabResidents,
            attendance: t.portal.hostelPage.tabAttendance,
          };
          return (
            <li className="nav-item" key={key}>
              <button
                className={`nav-link ${tab === key ? "active" : ""}`}
                onClick={() => setTab(key)}
                type="button"
              >
                {labels[key]}
              </button>
            </li>
          );
        })}
      </ul>

      {/* ---------- Hostels tab ---------- */}
      {tab === "hostels" && (
        !data || hostels.length === 0 ? (
          <div className="card">
            <EmptyState
              icon={<IconHome />}
              title={t.portal.hostelPage.noHostels}
              action={
                <Button onClick={openCreateHostel}>
                  <IconPlus className="svg-16" />
                  <span className="ms-1">{t.portal.hostelPage.newHostel}</span>
                </Button>
              }
            />
          </div>
        ) : (
          <div className="card">
            <div className="card-header d-flex flex-wrap align-items-center gap-2">
              <div className="has-search" style={{ maxWidth: 220 }}>
                <span className="fa fa-search form-control-feedback" />
                <input className="form-control" placeholder={t.common.search} value={hostelQ} onChange={(e) => setHostelQ(e.target.value)} />
              </div>
              <div style={{ maxWidth: 150 }}>
                <Select wrapperClassName="form-group mb-0" value={hostelTypeFilter} onChange={(e) => setHostelTypeFilter(e.target.value)}>
                  <option value="">{t.portal.hostelPage.allTypes}</option>
                  {[...new Set(data.hostels.map((h) => h.type))].map((ty) => (
                    <option key={ty} value={ty}>{t.hostelTypes[ty as keyof typeof t.hostelTypes] ?? ty}</option>
                  ))}
                </Select>
              </div>
              <Button onClick={openCreateHostel} className="ms-auto">
                <IconPlus className="svg-16" />
                <span className="ms-1">{t.portal.hostelPage.newHostel}</span>
              </Button>
            </div>
            <div className="table-responsive">
              <table className="table table-hover align-middle mb-0">
                <thead className="ems-table-head">
                  <tr>
                    <th>{t.portal.hostelPage.hostelName}</th>
                    <th>{t.portal.hostelPage.hostelType}</th>
                    <th>{t.portal.hostelPage.warden}</th>
                    <th>{t.portal.hostelPage.monthlyFeeLabel}</th>
                    <th>{t.portal.hostelPage.roomsColumn}</th>
                    <th>{t.common.actions}</th>
                  </tr>
                </thead>
                <tbody>
                  {hostelsPager.paged.map((h) => (
                    <tr key={h.id}>
                      <td>
                        <p className="mb-0 f-w-700">{h.name}</p>
                        <p className="mb-0 ems-fs-11 text-muted">{h.nameBn ?? ""}</p>
                      </td>
                      <td>
                        <span className="ems-type-pill">{t.hostelTypes[h.type as keyof typeof t.hostelTypes] ?? h.type}</span>
                      </td>
                      <td className="ems-fs-13">
                        <p className="mb-0 f-w-600">{h.wardenName ?? "—"}</p>
                        <p className="mb-0 ems-fs-11 text-muted">{h.wardenPhone ?? ""}</p>
                      </td>
                      <td className="ems-fs-13">{formatBDT(h.monthlyFee, locale)}</td>
                      <td>
                        <span className="badge badge-secondary me-1">{h.roomCount}</span>
                        <span className={`badge ${h.residentCount > 0 ? "badge-success" : "badge-light"} me-1`}>
                          {h.residentCount}
                        </span>
                        <span className="ems-fs-11 text-muted">{t.portal.hostelPage.residentsShort}</span>
                      </td>
                      <td>
                        <button className="btn btn-soft-secondary btn-sm me-1" onClick={() => openEditHostel(h)} type="button">
                          <IconEdit className="svg-16" />
                        </button>
                        <button className="btn btn-soft-danger btn-sm" onClick={() => removeHostel(h)} type="button">
                          <IconTrash className="svg-16" />
                        </button>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
            <Pagination {...hostelsPager} onPageChange={hostelsPager.setPage} onSizeChange={hostelsPager.setSize} />
          </div>
        )
      )}

      {/* ---------- Rooms tab ---------- */}
      {tab === "rooms" && (
        !data || data.hostels.length === 0 ? (
          <div className="card">
            <EmptyState icon={<IconHome />} title={t.portal.hostelPage.createHostelFirst} />
          </div>
        ) : (
          <div className="card">
            <div className="card-header d-flex flex-wrap align-items-center gap-2">
              <div className="d-flex flex-wrap align-items-center gap-2">
                <div style={{ maxWidth: 220 }}>
                  <Select
                    wrapperClassName="form-group mb-0"
                    value={roomHostelFilter}
                    onChange={(e) => setRoomHostelFilter(e.target.value)}
                  >
                    <option value="">{t.portal.hostelPage.allHostels}</option>
                    {data.hostels.map((h) => (
                      <option key={h.id} value={h.id}>
                        {h.name}
                      </option>
                    ))}
                  </Select>
                </div>
                <div className="has-search" style={{ maxWidth: 200 }}>
                  <span className="fa fa-search form-control-feedback" />
                  <input className="form-control" placeholder={t.common.search} value={roomQ} onChange={(e) => setRoomQ(e.target.value)} />
                </div>
                <div style={{ maxWidth: 160 }}>
                  <Select wrapperClassName="form-group mb-0" value={roomTypeFilter} onChange={(e) => setRoomTypeFilter(e.target.value)}>
                    <option value="">{t.portal.hostelPage.allRoomTypes}</option>
                    {[...new Set(data.rooms.map((r) => r.roomType))].map((ty) => (
                      <option key={ty} value={ty}>{t.roomTypes[ty as keyof typeof t.roomTypes] ?? ty}</option>
                    ))}
                  </Select>
                </div>
              </div>
              <Button onClick={openCreateRoom} className="ms-auto">
                <IconPlus className="svg-16" />
                <span className="ms-1">{t.portal.hostelPage.newRoom}</span>
              </Button>
            </div>
            {filteredRooms.length === 0 ? (
              <EmptyState icon={<IconLayers />} title={t.portal.hostelPage.noRooms} />
            ) : (
              <>
              <div className="table-responsive">
                <table className="table table-hover align-middle mb-0">
                  <thead className="ems-table-head">
                    <tr>
                      <th>{t.portal.hostelPage.roomNo}</th>
                      <th>{t.portal.hostelPage.hostelName}</th>
                      <th>{t.portal.hostelPage.floor}</th>
                      <th>{t.portal.hostelPage.roomType}</th>
                      <th>{t.portal.hostelPage.monthlyFeeLabel}</th>
                      <th>{t.portal.hostelPage.occupancy}</th>
                      <th className="text-end">{t.common.actions}</th>
                    </tr>
                  </thead>
                  <tbody>
                    {filteredRoomsPager.paged.map((r) => (
                      <tr key={r.id}>
                        <td className="f-w-700">{r.roomNo}</td>
                        <td className="ems-fs-13">{r.hostelName}</td>
                        <td className="ems-fs-13">{r.floor}</td>
                        <td>
                          <span className="ems-type-pill">{t.roomTypes[r.roomType as keyof typeof t.roomTypes] ?? r.roomType}</span>
                        </td>
                        <td className="ems-fs-13">{formatBDT(r.monthlyFee, locale)}</td>
                        <td>
                          <span className={`badge ${r.occupied >= r.capacity ? "badge-danger" : r.occupied > 0 ? "badge-success" : "badge-secondary"} me-1`}>
                            {r.occupied}/{r.capacity}
                          </span>
                          <span className="ems-fs-11 text-muted">
                            {Math.max(0, r.capacity - r.occupied)} {t.portal.hostelPage.free}
                          </span>
                        </td>
                        <td className="text-end">
                          <button className="btn btn-soft-secondary btn-sm me-1" onClick={() => openEditRoom(r)} type="button">
                            <IconEdit className="svg-16" />
                          </button>
                          <button className="btn btn-soft-danger btn-sm" onClick={() => removeRoom(r)} type="button">
                            <IconTrash className="svg-16" />
                          </button>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
              <Pagination {...filteredRoomsPager} onPageChange={filteredRoomsPager.setPage} onSizeChange={filteredRoomsPager.setSize} />
              </>
            )}
          </div>
        )
      )}

      {/* ---------- Residents tab ---------- */}
      {tab === "residents" && (
        <div className="row g-4">
          <div className="col-xl-4">
            <Card title={t.portal.hostelPage.assignTitle} icon={<IconUserCheck className="svg-18" />}>
              <Select
                label={t.portal.hostelPage.selectStudentLabel}
                value={assignForm.studentId}
                onChange={(e) => setAssignForm({ ...assignForm, studentId: e.target.value })}
              >
                <option value="">— {t.common.filter} —</option>
                {allocatableStudents.map((st) => (
                  <option key={st.id} value={st.id}>
                    {st.roll} — {st.name}
                  </option>
                ))}
              </Select>
              <Select
                label={t.portal.hostelPage.selectHostelLabel}
                value={assignForm.hostelId}
                onChange={(e) => setAssignForm({ ...assignForm, hostelId: e.target.value, roomId: "" })}
              >
                <option value="">— {t.common.filter} —</option>
                {(data?.hostels ?? []).filter((h) => h.isActive).map((h) => (
                  <option key={h.id} value={h.id}>
                    {h.name}
                  </option>
                ))}
              </Select>
              <Select
                label={t.portal.hostelPage.selectRoomLabel}
                value={assignForm.roomId}
                onChange={(e) => setAssignForm({ ...assignForm, roomId: e.target.value })}
              >
                <option value="">{t.portal.hostelPage.noRoomPreference}</option>
                {assignRooms.map((r) => (
                  <option key={r.id} value={r.id}>
                    {r.roomNo} · {r.occupied}/{r.capacity}
                  </option>
                ))}
              </Select>
              <div className="row">
                <div className="col-md-6">
                  <Input
                    label={t.portal.hostelPage.bedNoLabel}
                    value={assignForm.bedNo}
                    onChange={(e) => setAssignForm({ ...assignForm, bedNo: e.target.value })}
                    placeholder="A-1"
                  />
                </div>
                <div className="col-md-6">
                  <Input
                    label={t.portal.hostelPage.monthlyFeeLabel}
                    type="number"
                    min="0"
                    value={assignForm.monthlyFee}
                    onChange={(e) => setAssignForm({ ...assignForm, monthlyFee: e.target.value })}
                    placeholder="auto"
                  />
                </div>
              </div>
              <Button
                onClick={allocateStudent}
                loading={assignSaving}
                disabled={!assignForm.studentId || !assignForm.hostelId || !allocatableStudents.some((x) => String(x.id) === assignForm.studentId)}
              >
                <IconUserCheck className="svg-16" />
                <span className="ms-1">{t.portal.hostelPage.assignTitle}</span>
              </Button>
            </Card>
          </div>

          <div className="col-xl-8">
            <div className="card">
              <div className="card-header d-flex flex-wrap align-items-center gap-2">
                <div className="has-search" style={{ maxWidth: 240 }}>
                  <span className="fa fa-search form-control-feedback" />
                  <input
                    className="form-control"
                    placeholder={t.common.search}
                    value={search}
                    onChange={(e) => setSearch(e.target.value)}
                  />
                </div>
                <div style={{ maxWidth: 190 }}>
                  <Select wrapperClassName="form-group mb-0" value={resHostel} onChange={(e) => setResHostel(e.target.value)}>
                    <option value="">{t.portal.hostelPage.allHostels}</option>
                    {(data?.hostels ?? []).map((h) => (
                      <option key={h.id} value={h.id}>{h.name}</option>
                    ))}
                  </Select>
                </div>
                <div style={{ maxWidth: 140 }}>
                  <Select wrapperClassName="form-group mb-0" value={resStatus} onChange={(e) => setResStatus(e.target.value)}>
                    <option value="">{t.portal.hostelPage.allStatuses}</option>
                    <option value="ACTIVE">{t.common.active}</option>
                    <option value="INACTIVE">{t.common.inactive}</option>
                  </Select>
                </div>
              </div>
              {residents.length === 0 ? (
                <EmptyState icon={<IconUsers />} title={t.portal.hostelPage.noMembers} />
              ) : (
                <>
                <div className="table-responsive">
                  <table className="table table-hover align-middle mb-0">
                    <thead className="ems-table-head">
                      <tr>
                    <th>{t.portal.studentsPage.rollNo}</th>
                    <th>{t.portal.hostelPage.selectHostelLabel}</th>
                        <th>{t.portal.hostelPage.roomNo}</th>
                        <th>{t.portal.hostelPage.monthlyFeeLabel}</th>
                        <th>{t.common.status}</th>
                        <th className="text-end">{t.common.actions}</th>
                      </tr>
                    </thead>
                    <tbody>
                      {residentsPager.paged.map((m) => (
                        <tr key={m.id}>
                          <td>
                            <p className="mb-0 f-w-700">
                              {m.roll} — {m.studentName}
                            </p>
                            <p className="mb-0 ems-fs-11 text-muted">{m.className ?? ""}</p>
                          </td>
                          <td className="ems-fs-13">{m.hostelName}</td>
                          <td className="ems-fs-13">
                            {m.roomNo ?? "—"}
                            {m.bedNo ? <span className="text-muted"> · {m.bedNo}</span> : null}
                          </td>
                          <td className="ems-fs-13">{formatBDT(m.monthlyFee, locale)}</td>
                          <td>
                            <span className={`badge ${m.status === "ACTIVE" ? "badge-success" : "badge-secondary"}`}>
                              {m.status === "ACTIVE" ? t.common.active : t.common.inactive}
                            </span>
                          </td>
                          <td className="text-end">
                            <button className="btn btn-soft-secondary btn-sm me-1" onClick={() => openMove(m)} type="button">
                              <IconEdit className="svg-16" />
                            </button>
                            <button className="btn btn-soft-danger btn-sm" onClick={() => vacate(m)} type="button">
                              <IconTrash className="svg-16" />
                            </button>
                          </td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
                <Pagination {...residentsPager} onPageChange={residentsPager.setPage} onSizeChange={residentsPager.setSize} />
                </>
              )}
            </div>
          </div>
        </div>
      )}

      {/* ---------- Attendance tab ---------- */}
      {tab === "attendance" && (
        <div className="card">
          <div className="card-header d-flex flex-wrap align-items-center justify-content-between gap-2">
            <div className="d-flex align-items-center gap-2">
              <DatePicker
                wrapperClassName="form-group mb-0"
                style={{ maxWidth: 180 }}
                value={attDate}
                onChange={(e) => {
                  setAttDate(e.target.value);
                  setAttDraft({});
                }}
              />
              {att && (
                <span className="badge badge-secondary">
                  {t.portal.hostelPage.attendanceFor} {formatDate(att.date, locale)}
                </span>
              )}
              <div className="has-search" style={{ maxWidth: 220 }}>
                <span className="fa fa-search form-control-feedback" />
                <input className="form-control" placeholder={t.common.search} value={attQ} onChange={(e) => setAttQ(e.target.value)} />
              </div>
            </div>
            <Button onClick={saveAttendance} loading={attSaving} disabled={Object.keys(attDraft).length === 0}>
              <IconCheck className="svg-16" />
              <span className="ms-1">{t.portal.hostelPage.saveAttendance}</span>
            </Button>
          </div>
          {attLoading || !att ? (
            <div className="card-body text-center py-4">
              <span className="spinner-border text-primary" role="status" />
            </div>
          ) : att.entries.length === 0 ? (
            <EmptyState icon={<IconUsers />} title={t.portal.hostelPage.noMembers} />
          ) : (
            <div className="table-responsive">
              <table className="table table-hover align-middle mb-0">
                <thead className="ems-table-head">
                  <tr>
                    <th>{t.portal.studentsPage.rollNo}</th>
                    <th>{t.common.name}</th>
                    <th>{t.portal.hostelPage.roomNo}</th>
                    <th className="text-end">{t.common.status}</th>
                  </tr>
                </thead>
                <tbody>
                  {att.entries
                    .filter((e) => {
                      const q = attQ.trim().toLowerCase();
                      return !q || e.roll.toLowerCase().includes(q) || e.studentName.toLowerCase().includes(q) || (e.roomNo ?? "").toLowerCase().includes(q);
                    })
                    .map((e) => {
                    const current = attDraft[e.memberId] ?? e.status;
                    return (
                      <tr key={e.memberId}>
                        <td>
                          <span className="ems-roll-badge">{e.roll}</span>
                        </td>
                        <td>
                          <p className="mb-0 f-w-600">{e.studentName}</p>
                          <p className="mb-0 ems-fs-11 text-muted">{e.hostelName}</p>
                        </td>
                        <td className="ems-fs-13">
                          {e.roomNo ?? "—"}
                          {e.bedNo ? <span className="text-muted"> · {e.bedNo}</span> : null}
                        </td>
                        <td className="text-end">
                          <div className="btn-group btn-group-sm" role="group">
                            {ATTENDANCE_STATUSES.map((st) => (
                              <button
                                key={st}
                                type="button"
                                className={`btn ${
                                  current === st
                                    ? st === "PRESENT"
                                      ? "btn-success"
                                      : st === "ABSENT"
                                        ? "btn-danger"
                                        : "btn-warning"
                                    : "btn-outline-secondary"
                                }`}
                                onClick={() => setAttDraft({ ...attDraft, [e.memberId]: st })}
                              >
                                {t.status[st]}
                              </button>
                            ))}
                          </div>
                        </td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>
          )}
        </div>
      )}

      {/* Hostel create/edit modal */}
      <Modal
        open={formOpen}
        onClose={() => setFormOpen(false)}
        title={editingHostel ? t.portal.hostelPage.editHostel : t.portal.hostelPage.newHostel}
        wide
      >
        <div className="row">
          <div className="col-md-6">
            <Input label={t.portal.hostelPage.hostelName} value={hostelForm.name} onChange={(e) => setHostelForm({ ...hostelForm, name: e.target.value })} />
          </div>
          <div className="col-md-6">
            <Input label={t.portal.hostelPage.hostelNameBn} value={hostelForm.nameBn} onChange={(e) => setHostelForm({ ...hostelForm, nameBn: e.target.value })} />
          </div>
          <div className="col-md-6">
            <Select label={t.portal.hostelPage.hostelType} value={hostelForm.type} onChange={(e) => setHostelForm({ ...hostelForm, type: e.target.value })}>
              {HOSTEL_TYPES.map((ty) => (
                <option key={ty} value={ty}>
                  {t.hostelTypes[ty]}
                </option>
              ))}
            </Select>
          </div>
          <div className="col-md-6">
            <Input label={t.portal.hostelPage.defaultFee} type="number" min="0" value={hostelForm.monthlyFee} onChange={(e) => setHostelForm({ ...hostelForm, monthlyFee: e.target.value })} />
          </div>
          <div className="col-md-6">
            <Input label={t.portal.hostelPage.warden} value={hostelForm.wardenName} onChange={(e) => setHostelForm({ ...hostelForm, wardenName: e.target.value })} />
          </div>
          <div className="col-md-6">
            <Input label={t.portal.hostelPage.wardenPhone} value={hostelForm.wardenPhone} onChange={(e) => setHostelForm({ ...hostelForm, wardenPhone: e.target.value })} placeholder="+880 1XXX-XXXXXX" />
          </div>
        </div>
        <div className="d-flex justify-content-end gap-2">
          <Button variant="secondary" onClick={() => setFormOpen(false)}>
            {t.common.cancel}
          </Button>
          <Button onClick={saveHostel} loading={saving} disabled={!hostelForm.name.trim()}>
            {t.common.save}
          </Button>
        </div>
      </Modal>

      {/* Room create/edit modal */}
      <Modal
        open={roomOpen}
        onClose={() => setRoomOpen(false)}
        title={editingRoom ? t.portal.hostelPage.editRoom : t.portal.hostelPage.newRoom}
        wide
      >
        <div className="row">
          <div className="col-md-6">
            <Select label={t.portal.hostelPage.selectHostelLabel} value={roomForm.hostelId} onChange={(e) => setRoomForm({ ...roomForm, hostelId: e.target.value })}>
              <option value="">— {t.common.filter} —</option>
              {(data?.hostels ?? []).map((h) => (
                <option key={h.id} value={h.id}>
                  {h.name}
                </option>
              ))}
            </Select>
          </div>
          <div className="col-md-6">
            <Input label={t.portal.hostelPage.roomNo} value={roomForm.roomNo} onChange={(e) => setRoomForm({ ...roomForm, roomNo: e.target.value })} placeholder="101" />
          </div>
          <div className="col-md-4">
            <Input label={t.portal.hostelPage.floor} type="number" min="0" value={roomForm.floor} onChange={(e) => setRoomForm({ ...roomForm, floor: e.target.value })} />
          </div>
          <div className="col-md-4">
            <Input label={t.portal.hostelPage.beds} type="number" min="1" value={roomForm.capacity} onChange={(e) => setRoomForm({ ...roomForm, capacity: e.target.value })} />
          </div>
          <div className="col-md-4">
            <Select label={t.portal.hostelPage.roomType} value={roomForm.roomType} onChange={(e) => setRoomForm({ ...roomForm, roomType: e.target.value })}>
              {ROOM_TYPES.map((rt) => (
                <option key={rt} value={rt}>
                  {t.roomTypes[rt]}
                </option>
              ))}
            </Select>
          </div>
          <div className="col-md-6">
            <Input label={t.portal.hostelPage.roomFee} type="number" min="0" value={roomForm.monthlyFee} onChange={(e) => setRoomForm({ ...roomForm, monthlyFee: e.target.value })} />
          </div>
        </div>
        <div className="d-flex justify-content-end gap-2">
          <Button variant="secondary" onClick={() => setRoomOpen(false)}>
            {t.common.cancel}
          </Button>
          <Button onClick={saveRoom} loading={roomSaving} disabled={!roomForm.roomNo.trim() || !roomForm.hostelId}>
            {t.common.save}
          </Button>
        </div>
      </Modal>

      {/* Change room modal */}
      <Modal
        open={!!moveMember}
        onClose={() => setMoveMember(null)}
        title={t.portal.hostelPage.changeRoomTitle}
        wide
      >
        <div className="row">
          <div className="col-md-6">
            <Select
              label={t.portal.hostelPage.selectHostelLabel}
              value={moveForm.hostelId}
              onChange={(e) => setMoveForm({ ...moveForm, hostelId: e.target.value, roomId: "" })}
            >
              <option value="">— {t.common.filter} —</option>
              {(data?.hostels ?? []).filter((h) => h.isActive).map((h) => (
                <option key={h.id} value={h.id}>
                  {h.name}
                </option>
              ))}
            </Select>
          </div>
          <div className="col-md-6">
            <Select
              label={t.portal.hostelPage.selectRoomLabel}
              value={moveForm.roomId}
              onChange={(e) => setMoveForm({ ...moveForm, roomId: e.target.value })}
            >
              <option value="">{t.portal.hostelPage.clearRoomOption}</option>
              {moveRooms.map((r) => (
                <option key={r.id} value={r.id}>
                  {r.roomNo} · {r.occupied}/{r.capacity}
                </option>
              ))}
            </Select>
          </div>
          <div className="col-md-6">
            <Input
              label={t.portal.hostelPage.bedNoLabel}
              value={moveForm.bedNo}
              onChange={(e) => setMoveForm({ ...moveForm, bedNo: e.target.value })}
              placeholder="A-1"
            />
          </div>
        </div>
        <div className="d-flex justify-content-end gap-2">
          <Button variant="secondary" onClick={() => setMoveMember(null)}>
            {t.common.cancel}
          </Button>
          <Button onClick={saveMove} loading={moveSaving} disabled={!moveForm.hostelId}>
            {t.common.saveChanges}
          </Button>
        </div>
      </Modal>
    </div>
  );
}
