import React, { useContext, useEffect, useState } from "react";
import {
  createGroupInviteLink,
  deleteGroupInviteLink,
  deleteHousehold,
  getGroupInviteLinks,
  getGroupJoinPolicy,
  getHouseholdMembers,
  refreshInviteCode,
  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" },
];

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 [showInviteCode, setShowInviteCode] = useState(false);
  const [joinPolicy, setJoinPolicyValue] = useState("NOT_ACCEPTING");
  const [inviteLinks, setInviteLinks] = useState([]);
  const [inviteLoading, setInviteLoading] = useState(false);
  const [inviteError, setInviteError] = useState("");
  const [ttlDays, setTtlDays] = useState(7);
  const [singleUseMode, setSingleUseMode] = useState("UNLIMITED");
  const [isLeaveModalOpen, setIsLeaveModalOpen] = useState(false);

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

  useEffect(() => {
    loadMembers();
    if (isManager) {
      loadJoinAndInvites();
    }
  }, [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] = await Promise.all([
        getGroupJoinPolicy(activeHousehold.id),
        getGroupInviteLinks(activeHousehold.id),
      ]);
      setJoinPolicyValue(policyResponse.data.joinPolicy || "NOT_ACCEPTING");
      setInviteLinks(linksResponse.data.links || []);
    } 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 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 handleRefreshInvite = async () => {
    if (!confirm("Generate a new invite code? The old code will no longer work.")) return;

    try {
      await refreshInviteCode(activeHousehold.id);
      await refreshHouseholds();
      toast.success("Generated new invite code", "Generated a new invite code");
    } catch (error) {
      const message = getApiErrorMessage(error, "Failed to refresh invite code");
      toast.error("Refresh invite code failed", `Refresh invite code failed: ${message}`);
    }
  };

  const handleUpdateRole = async (memberId, currentRole, memberName) => {
    if (currentRole === "owner") return;
    const newRole = currentRole === "admin" ? "member" : "admin";

    try {
      await updateMemberRole(activeHousehold.id, memberId, newRole);
      await loadMembers();
      toast.success("Updated member role", `Updated role for ${memberName} to ${newRole}`);
    } catch (error) {
      const message = getApiErrorMessage(error, "Failed to update member role");
      toast.error("Update member role failed", `Update member role failed: ${message}`);
    }
  };

  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 copyInviteCode = async () => {
    const copied = await copyTextToClipboard(activeHousehold.invite_code);
    if (copied) {
      toast.info("Copied invite code", "Copied invite code to clipboard");
      return;
    }

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

  return (
    <div className="manage-household">
      <section key="household-name" className="manage-section">
        <h2>Household Name</h2>
        {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">
            <h3>{activeHousehold.name}</h3>
            {isManager && (
              <button
                onClick={() => {
                  setNewName(activeHousehold.name);
                  setEditingName(true);
                }}
                className="btn-secondary"
              >
                Edit Name
              </button>
            )}
          </div>
        )}
      </section>

      {isManager && (
        <section key="invite-code" className="manage-section">
          <h2>Legacy Invite Code</h2>
          <p className="section-description">
            Share this code for legacy join-by-code flows.
          </p>
          <div className="invite-actions">
            <button onClick={() => setShowInviteCode(!showInviteCode)} className="btn-secondary">
              {showInviteCode ? "Hide Code" : "Show Code"}
            </button>
            {showInviteCode && (
              <React.Fragment key="invite-code-display">
                <code className="invite-code">{activeHousehold.invite_code}</code>
                <button onClick={copyInviteCode} className="btn-secondary">Copy</button>
              </React.Fragment>
            )}
            <button onClick={handleRefreshInvite} className="btn-secondary">
              Generate New Code
            </button>
          </div>
        </section>
      )}

      {isManager && (
        <section key="join-and-invites" className="manage-section">
          <h2>Join and Invites</h2>
          {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="invite-controls">
            <label>
              TTL
              <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>
              Usage
              <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";
                return (
                  <div key={link.id} className="invite-link-card">
                    <div>
                      <p className="invite-link-token">Token ending in {String(link.token).slice(-4)}</p>
                      <p className="invite-link-meta">
                        Status: <strong>{status}</strong> | Policy: {link.policy} | TTL: until {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">
        <h2>Members ({members.length})</h2>
        {loading ? (
          <p>Loading members...</p>
        ) : (
          <div className="members-list">
            {members.map((member) => (
              <div key={member.id} className="member-card">
                <div className="member-info">
                  <span className="member-role">{member.role}</span>
                  <span className="member-name">
                    {member.username} [{member.id}] {member.id === parseInt(userId, 10) ? "(You)" : ""}
                  </span>
                </div>
                {isManager && member.id !== parseInt(userId, 10) && member.role !== "owner" && (
                  <div className="member-actions">
                    <button
                      onClick={() => handleUpdateRole(member.id, member.role, member.username)}
                      className="btn-secondary btn-small"
                    >
                      {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">
          <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>
          {isMemberOnly ? (
            <button onClick={() => setIsLeaveModalOpen(true)} className="btn-danger">
              Leave Household
            </button>
          ) : (
            <button onClick={handleDeleteHousehold} className="btn-danger">
              Delete Household
            </button>
          )}
        </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}
      />
    </div>
  );
}
