import React, { useContext, useEffect, useState } from "react";
import {
  createGroupInviteLink,
  decideGroupJoinRequest,
  deleteGroupInviteLink,
  deleteHousehold,
  getGroupInviteLinks,
  getGroupJoinPolicy,
  getHouseholdMembers,
  getPendingGroupJoinRequests,
  removeMember,
  revokeGroupInviteLink,
  reviveGroupInviteLink,
  setGroupJoinPolicy,
  updateHousehold,
  updateMemberRole,
} from "../../api/households";
import { ToggleButtonGroup } from "../common";
import ConfirmSlideModal from "../modals/ConfirmSlideModal";
import { AuthContext } from "../../context/AuthContext";
import { HouseholdContext } from "../../context/HouseholdContext";
import useActionToast from "../../hooks/useActionToast";
import getApiErrorMessage from "../../lib/getApiErrorMessage";
import "../../styles/components/manage/ManageHousehold.css";

const JOIN_POLICY_OPTIONS = [
  { label: "Disabled", value: "NOT_ACCEPTING" },
  { label: "Auto", value: "AUTO_ACCEPT" },
  { label: "Manual", value: "APPROVAL_REQUIRED" },
];

const ROLE_METADATA = {
  owner: { icon: "👑", label: "Owner" },
  admin: { icon: "🛠️", label: "Admin" },
  member: { icon: "🙂", label: "Member" },
  viewer: { icon: "👀", label: "Viewer" },
};

const STATUS_METADATA = {
  Active: { tone: "active", icon: "🟢" },
  Used: { tone: "used", icon: "⚪" },
  Revoked: { tone: "revoked", icon: "🔴" },
  Expired: { tone: "expired", icon: "🟠" },
};

function getRequesterLabel(request) {
  return (
    request.display_name?.trim() ||
    request.name?.trim() ||
    request.username?.trim() ||
    `User #${request.user_id}`
  );
}

export default function ManageHousehold() {
  const { userId } = useContext(AuthContext);
  const { activeHousehold, refreshHouseholds } = useContext(HouseholdContext);
  const toast = useActionToast();
  const [members, setMembers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [editingName, setEditingName] = useState(false);
  const [newName, setNewName] = useState("");
  const [joinPolicy, setJoinPolicyValue] = useState("NOT_ACCEPTING");
  const [inviteLinks, setInviteLinks] = useState([]);
  const [pendingRequests, setPendingRequests] = useState([]);
  const [inviteLoading, setInviteLoading] = useState(false);
  const [inviteError, setInviteError] = useState("");
  const [ttlDays, setTtlDays] = useState(7);
  const [singleUseMode, setSingleUseMode] = useState("UNLIMITED");
  const [pendingDecisionId, setPendingDecisionId] = useState(null);
  const [isLeaveModalOpen, setIsLeaveModalOpen] = useState(false);
  const [pendingRoleChange, setPendingRoleChange] = useState(null);

  const isManager = ["owner", "admin"].includes(activeHousehold?.role);
  const isOwner = activeHousehold?.role === "owner";
  const isMemberOnly = activeHousehold?.role === "member";

  useEffect(() => {
    loadMembers();
    if (isManager) {
      loadJoinAndInvites();
    } else {
      setPendingRequests([]);
    }
  }, [activeHousehold?.id, isManager]);

  const loadMembers = async () => {
    if (!activeHousehold?.id) return;
    setLoading(true);
    try {
      const response = await getHouseholdMembers(activeHousehold.id);
      setMembers(response.data);
    } catch (error) {
      console.error("Failed to load members:", error);
    } finally {
      setLoading(false);
    }
  };

  const loadJoinAndInvites = async () => {
    if (!activeHousehold?.id || !isManager) return;
    setInviteLoading(true);
    setInviteError("");
    try {
      const [policyResponse, linksResponse, requestsResponse] = await Promise.all([
        getGroupJoinPolicy(activeHousehold.id),
        getGroupInviteLinks(activeHousehold.id),
        getPendingGroupJoinRequests(activeHousehold.id),
      ]);
      setJoinPolicyValue(policyResponse.data.joinPolicy || "NOT_ACCEPTING");
      setInviteLinks(linksResponse.data.links || []);
      setPendingRequests(requestsResponse.data.requests || []);
    } catch (error) {
      setInviteError(error.response?.data?.error?.message || "Failed to load invite links");
    } finally {
      setInviteLoading(false);
    }
  };

  const getLinkStatus = (link) => {
    const now = Date.now();
    if (link.single_use && link.used_at) return "Used";
    if (link.revoked_at) return "Revoked";
    if (new Date(link.expires_at).getTime() <= now) return "Expired";
    return "Active";
  };

  const copyTextToClipboard = async (text) => {
    if (!text) return false;

    if (navigator?.clipboard?.writeText) {
      try {
        await navigator.clipboard.writeText(text);
        return true;
      } catch {
        // Fall through to legacy copy fallback.
      }
    }

    try {
      const textArea = document.createElement("textarea");
      textArea.value = text;
      textArea.setAttribute("readonly", "");
      textArea.style.position = "fixed";
      textArea.style.top = "-9999px";
      textArea.style.left = "-9999px";
      document.body.appendChild(textArea);
      textArea.focus();
      textArea.select();
      const copied = document.execCommand("copy");
      document.body.removeChild(textArea);
      return copied;
    } catch {
      return false;
    }
  };

  const copyInviteLink = async (token) => {
    const inviteUrl = `${window.location.origin}/invite/${encodeURIComponent(token)}`;
    const copied = await copyTextToClipboard(inviteUrl);
    if (copied) {
      const tokenLast4 = String(token || "").slice(-4);
      toast.info("Copied invite link", `Copied invite link ending in ${tokenLast4}`);
      return;
    }

    toast.error(
      "Copy invite link failed",
      "Copy invite link failed: unable to access clipboard. Copy manually."
    );
  };

  const handleCreateInviteLink = async () => {
    try {
      setInviteError("");
      await createGroupInviteLink(activeHousehold.id, {
        policy: joinPolicy,
        singleUse: singleUseMode === "ONE_TIME",
        ttlDays,
      });
      await loadJoinAndInvites();
      toast.success("Created invite link", `Created invite link (${ttlDays} day TTL)`);
    } catch (error) {
      const message = getApiErrorMessage(error, "Failed to create invite link");
      setInviteError(message);
      toast.error("Create invite link failed", `Create invite link failed: ${message}`);
    }
  };

  const handleUpdateJoinPolicy = async (value) => {
    try {
      setInviteError("");
      await setGroupJoinPolicy(activeHousehold.id, value);
      setJoinPolicyValue(value);
      toast.success("Updated join policy", `Join policy set to ${value}`);
    } catch (error) {
      const message = getApiErrorMessage(error, "Failed to update join policy");
      setInviteError(message);
      toast.error("Update join policy failed", `Update join policy failed: ${message}`);
    }
  };

  const handleJoinRequestDecision = async (request, decision) => {
    const requesterName = getRequesterLabel(request);
    setPendingDecisionId(request.id);
    try {
      setInviteError("");
      await decideGroupJoinRequest(activeHousehold.id, request.id, decision);
      await Promise.all([loadJoinAndInvites(), loadMembers()]);
      if (decision === "APPROVE") {
        toast.success("Approved join request", `Approved ${requesterName}`);
      } else {
        toast.info("Denied join request", `Denied ${requesterName}`);
      }
    } catch (error) {
      const message = getApiErrorMessage(error, "Failed to update join request");
      setInviteError(message);
      toast.error("Join request update failed", `Join request update failed: ${message}`);
    } finally {
      setPendingDecisionId(null);
    }
  };

  const handleRevokeInvite = async (linkId) => {
    try {
      setInviteError("");
      await revokeGroupInviteLink(activeHousehold.id, linkId);
      await loadJoinAndInvites();
      toast.success("Revoked invite link", "Revoked invite link");
    } catch (error) {
      const message = getApiErrorMessage(error, "Failed to revoke invite link");
      setInviteError(message);
      toast.error("Revoke invite link failed", `Revoke invite link failed: ${message}`);
    }
  };

  const handleReviveInvite = async (linkId) => {
    try {
      setInviteError("");
      await reviveGroupInviteLink(activeHousehold.id, linkId, ttlDays);
      await loadJoinAndInvites();
      toast.success("Revived invite link", `Revived invite link for ${ttlDays} days`);
    } catch (error) {
      const message = getApiErrorMessage(error, "Failed to revive invite link");
      setInviteError(message);
      toast.error("Revive invite link failed", `Revive invite link failed: ${message}`);
    }
  };

  const handleDeleteInvite = async (linkId) => {
    if (!confirm("Delete this invite link permanently?")) return;
    try {
      setInviteError("");
      await deleteGroupInviteLink(activeHousehold.id, linkId);
      await loadJoinAndInvites();
      toast.success("Deleted invite link", "Deleted invite link");
    } catch (error) {
      const message = getApiErrorMessage(error, "Failed to delete invite link");
      setInviteError(message);
      toast.error("Delete invite link failed", `Delete invite link failed: ${message}`);
    }
  };

  const handleUpdateName = async () => {
    if (!newName.trim() || newName === activeHousehold.name) {
      setEditingName(false);
      return;
    }

    try {
      await updateHousehold(activeHousehold.id, newName);
      await refreshHouseholds();
      toast.success("Updated household name", `Updated household name to ${newName.trim()}`);
      setEditingName(false);
    } catch (error) {
      const message = getApiErrorMessage(error, "Failed to update household name");
      toast.error("Update household name failed", `Update household name failed: ${message}`);
    }
  };

  const handleConfirmRoleChange = async () => {
    if (!pendingRoleChange) return;

    const { memberId, nextRole, memberName } = pendingRoleChange;

    try {
      await updateMemberRole(activeHousehold.id, memberId, nextRole);
      await Promise.all([
        loadMembers(),
        nextRole === "owner" ? refreshHouseholds() : Promise.resolve(),
      ]);
      if (nextRole === "owner") {
        toast.success("Transferred household ownership", `Transferred ownership to ${memberName}`);
      } else {
        toast.success("Updated member role", `Updated role for ${memberName} to ${nextRole}`);
      }
      setPendingRoleChange(null);
    } catch (error) {
      const message = getApiErrorMessage(error, "Failed to update member role");
      toast.error("Update member role failed", `Update member role failed: ${message}`);
    }
  };

  const handleUpdateRole = (memberId, nextRole, memberName) => {
    if (!nextRole) return;

    setPendingRoleChange({ memberId, nextRole, memberName });
  };

  const handleRemoveMember = async (memberId, username) => {
    if (!confirm(`Remove ${username} from this household?`)) return;

    try {
      await removeMember(activeHousehold.id, memberId);
      await loadMembers();
      toast.success("Removed member", `Removed member ${username}`);
    } catch (error) {
      const message = getApiErrorMessage(error, "Failed to remove member");
      toast.error("Remove member failed", `Remove member failed: ${message}`);
    }
  };

  const handleDeleteHousehold = async () => {
    if (!confirm(`Delete "${activeHousehold.name}"? This will delete all lists and data. This cannot be undone.`)) return;
    if (!confirm("Are you absolutely sure? Type DELETE to confirm.")) return;

    try {
      const householdName = activeHousehold.name;
      await deleteHousehold(activeHousehold.id);
      await refreshHouseholds();
      toast.success("Deleted household", `Deleted household ${householdName}`);
    } catch (error) {
      const message = getApiErrorMessage(error, "Failed to delete household");
      toast.error("Delete household failed", `Delete household failed: ${message}`);
    }
  };

  const handleLeaveHousehold = async () => {
    if (!activeHousehold?.id) return;

    try {
      const householdName = activeHousehold.name;
      await removeMember(activeHousehold.id, parseInt(userId, 10));
      setIsLeaveModalOpen(false);
      await refreshHouseholds();
      toast.success("Left household", `Left household ${householdName}`);
    } catch (error) {
      const message = getApiErrorMessage(error, "Failed to leave household");
      toast.error("Leave household failed", `Leave household failed: ${message}`);
    }
  };

  const managerCount = members.filter((member) => ["owner", "admin"].includes(member.role)).length;
  const memberCount = members.filter((member) => member.role === "member").length;

  return (
    <div className="manage-household">
      <section key="household-name" className="manage-section">
        <div className="manage-section-header">
          <div>
            <p className="manage-section-eyebrow">Household</p>
            <h2>Identity</h2>
            <p className="section-description">
              Keep the household name crisp and easy to recognize across invites and shared lists.
            </p>
          </div>
        </div>
        {editingName ? (
          <div className="edit-name-form">
            <input
              type="text"
              value={newName}
              onChange={(e) => setNewName(e.target.value)}
              placeholder="Household name"
              autoFocus
            />
            <button onClick={handleUpdateName} className="btn-primary">Save</button>
            <button onClick={() => setEditingName(false)} className="btn-secondary">Cancel</button>
          </div>
        ) : (
          <div className="name-display">
            <div className="name-display-copy">
              <h3>{activeHousehold.name}</h3>
              <div className="household-summary-chips">
                <span className="household-summary-chip">🏠 {members.length} people</span>
                <span className="household-summary-chip">🛡️ {managerCount} managers</span>
                <span className="household-summary-chip">🛒 {memberCount} shoppers</span>
              </div>
            </div>
            {isManager && (
              <button
                onClick={() => {
                  setNewName(activeHousehold.name);
                  setEditingName(true);
                }}
                className="btn-secondary"
              >
                Edit Name
              </button>
            )}
          </div>
        )}
      </section>

      {isManager && (
        <section key="join-and-invites" className="manage-section">
          <div className="manage-section-header">
            <div>
              <p className="manage-section-eyebrow">Entry Rules</p>
              <h2>Invite Links</h2>
              <p className="section-description">
                Decide how new people can enter, review manual approvals, then create invite links for the flow you want.
              </p>
            </div>
          </div>
          {inviteError && <p className="section-error">{inviteError}</p>}

          <ToggleButtonGroup
            value={joinPolicy}
            ariaLabel="Join policy options"
            className="tbg-group manage-household-join-policy-toggle"
            options={JOIN_POLICY_OPTIONS.map((option) => ({
              ...option,
              disabled: inviteLoading,
            }))}
            onChange={handleUpdateJoinPolicy}
          />

          <div className="pending-requests-summary">
            <span className="pending-requests-summary-label">Pending approvals</span>
            <span className="pending-requests-summary-count">{pendingRequests.length}</span>
          </div>

          {inviteLoading ? (
            <p>Loading invite settings...</p>
          ) : pendingRequests.length === 0 ? (
            <p className="section-description">No pending join requests right now.</p>
          ) : (
            <div className="pending-requests-list">
              {pendingRequests.map((request) => {
                const requesterLabel = getRequesterLabel(request);
                const isBusy = pendingDecisionId === request.id;
                return (
                  <div key={request.id} className="pending-request-card">
                    <div className="pending-request-main">
                      <div className="pending-request-topline">
                        <p className="pending-request-name">{requesterLabel}</p>
                        <span className="pending-request-badge">🕒 Pending</span>
                      </div>
                      <p className="pending-request-meta">
                        @{request.username} • Requested {new Date(request.created_at).toLocaleString()}
                      </p>
                    </div>
                    <div className="pending-request-actions">
                      <button
                        className="btn-secondary btn-small member-role-action"
                        onClick={() => handleJoinRequestDecision(request, "APPROVE")}
                        disabled={isBusy}
                      >
                        {isBusy ? "Working..." : "Approve"}
                      </button>
                      <button
                        className="btn-danger btn-small"
                        onClick={() => handleJoinRequestDecision(request, "DENY")}
                        disabled={isBusy}
                      >
                        Deny
                      </button>
                    </div>
                  </div>
                );
              })}
            </div>
          )}

          <div className="invite-controls">
            <label>
              <span className="invite-control-label">TTL</span>
              <select value={ttlDays} onChange={(e) => setTtlDays(Number(e.target.value))}>
                {[1, 2, 3, 4, 5, 6, 7].map((day) => (
                  <option key={day} value={day}>{day} day{day > 1 ? "s" : ""}</option>
                ))}
              </select>
            </label>
            <label>
              <span className="invite-control-label">Usage</span>
              <select value={singleUseMode} onChange={(e) => setSingleUseMode(e.target.value)}>
                <option value="UNLIMITED">Unlimited</option>
                <option value="ONE_TIME">1 use</option>
              </select>
            </label>
            <button className="btn-primary" onClick={handleCreateInviteLink} disabled={inviteLoading}>
              Create link
            </button>
          </div>

          {inviteLoading ? (
            <p>Loading invite links...</p>
          ) : inviteLinks.length === 0 ? (
            <p className="section-description">No invite links yet.</p>
          ) : (
            <div className="invite-links-list">
              {inviteLinks.map((link) => {
                const status = getLinkStatus(link);
                const isActive = status === "Active";
                const statusMeta = STATUS_METADATA[status] || STATUS_METADATA.Active;
                return (
                  <div key={link.id} className="invite-link-card">
                    <div className="invite-link-main">
                      <div className="invite-link-topline">
                        <p className="invite-link-token">Invite ending in {String(link.token).slice(-4)}</p>
                        <span className={`invite-status-badge is-${statusMeta.tone}`}>
                          {statusMeta.icon} {status}
                        </span>
                      </div>
                      <p className="invite-link-meta">
                        Policy: {link.policy} • Expires {new Date(link.expires_at).toLocaleString()}
                      </p>
                    </div>
                    <div className="invite-link-actions">
                      <button className="btn-secondary btn-small" onClick={() => copyInviteLink(link.token)}>
                        Copy link
                      </button>
                      {isActive ? (
                        <button className="btn-secondary btn-small" onClick={() => handleRevokeInvite(link.id)}>
                          Revoke
                        </button>
                      ) : (
                        <button className="btn-secondary btn-small" onClick={() => handleReviveInvite(link.id)}>
                          Revive
                        </button>
                      )}
                      <button className="btn-danger btn-small" onClick={() => handleDeleteInvite(link.id)}>
                        Delete
                      </button>
                    </div>
                  </div>
                );
              })}
            </div>
          )}
        </section>
      )}

      <section key="members" className="manage-section">
        <div className="manage-section-header">
          <div>
            <p className="manage-section-eyebrow">People</p>
            <h2>Members ({members.length})</h2>
            <p className="section-description">
              Role badges and compact actions make it easier to see who runs the household and who just shops.
            </p>
          </div>
        </div>
        {loading ? (
          <p>Loading members...</p>
        ) : (
          <div className="members-list">
            {members.map((member) => {
              const roleMeta = ROLE_METADATA[member.role] || { icon: "👤", label: member.role };
              const isSelf = member.id === parseInt(userId, 10);

              return (
                <div key={member.id} className="member-card">
                  <div className="member-main">
                    <div className="member-avatar" aria-hidden="true">{roleMeta.icon}</div>
                    <div className="member-info">
                      <div className="member-topline">
                      <span className={`member-role member-role-${member.role}`}>
                        {roleMeta.icon} {roleMeta.label}
                      </span>
                      {isSelf && <span className="member-self-pill">✨ You</span>}
                      </div>
                      <span className="member-name">{member.username}</span>
                      <span className="member-meta">ID #{member.id}</span>
                    </div>
                  </div>
                  {isManager && !isSelf && member.role !== "owner" && (
                    <div className="member-actions">
                      {isOwner && (
                        <button
                          onClick={() => handleUpdateRole(member.id, "owner", member.username)}
                          className="btn-primary btn-small member-owner-action"
                        >
                          Make Owner
                        </button>
                      )}
                      <button
                        onClick={() => handleUpdateRole(
                          member.id,
                          member.role === "admin" ? "member" : "admin",
                          member.username
                        )}
                        className="btn-secondary btn-small member-role-action"
                      >
                        {member.role === "admin" ? "Make Member" : "Make Admin"}
                      </button>
                      <button
                        onClick={() => handleRemoveMember(member.id, member.username)}
                        className="btn-danger btn-small"
                      >
                        Remove
                      </button>
                    </div>
                  )}
                </div>
              );
            })}
          </div>
        )}
      </section>

      {(isManager || isMemberOnly) && (
        <section key="danger-zone" className="manage-section danger-zone">
          <div className="manage-section-header">
            <div>
              <p className="manage-section-eyebrow">Final Actions</p>
              <h2>Danger Zone</h2>
              <p className="section-description">
                {isMemberOnly
                  ? "Leaving removes your access to this household."
                  : "Deleting a household is permanent and will delete all lists, items, and history."}
              </p>
            </div>
            {isMemberOnly ? (
              <button onClick={() => setIsLeaveModalOpen(true)} className="btn-danger">
                Leave Household
              </button>
            ) : (
              <button onClick={handleDeleteHousehold} className="btn-danger">
                Delete Household
              </button>
            )}
          </div>
        </section>
      )}

      <ConfirmSlideModal
        isOpen={isLeaveModalOpen}
        title={`Leave "${activeHousehold?.name || "this household"}"?`}
        description="Slide all the way to confirm. You will lose access to this household."
        confirmLabel="Leave Household"
        onClose={() => setIsLeaveModalOpen(false)}
        onConfirm={handleLeaveHousehold}
      />

      <ConfirmSlideModal
        isOpen={Boolean(pendingRoleChange)}
        title={
          pendingRoleChange?.nextRole === "owner"
            ? `Transfer ownership to ${pendingRoleChange?.memberName || "this member"}?`
            : `Change ${pendingRoleChange?.memberName || "this member"} to ${pendingRoleChange?.nextRole || "member"}?`
        }
        description={
          pendingRoleChange?.nextRole === "owner"
            ? "Slide to confirm. They will become the household owner and you will become an admin."
            : "Slide to confirm this household role change."
        }
        confirmLabel={
          pendingRoleChange?.nextRole === "owner"
            ? "Transfer Ownership"
            : `Make ${pendingRoleChange?.nextRole === "admin" ? "Admin" : "Member"}`
        }
        onClose={() => setPendingRoleChange(null)}
        onConfirm={handleConfirmRoleChange}
      />
    </div>
  );
}
