const householdModel = require("../models/household.model");
const { sendError } = require("../utils/http");
const { inviteCodeLast4 } = require("../utils/redaction");
const { logError } = require("../utils/logger");

// Get all households user belongs to
exports.getUserHouseholds = async (req, res) => {
  try {
    const households = await householdModel.getUserHouseholds(req.user.id);
    res.json(households);
  } catch (error) {
    logError(req, "households.getUserHouseholds", error);
    sendError(res, 500, "Failed to fetch households");
  }
};

// Get household details
exports.getHousehold = async (req, res) => {
  try {
    const household = await householdModel.getHouseholdById(
      req.params.householdId,
      req.user.id
    );

    if (!household) {
      return sendError(res, 404, "Household not found");
    }

    res.json(household);
  } catch (error) {
    logError(req, "households.getHousehold", error);
    sendError(res, 500, "Failed to fetch household");
  }
};

// Create new household
exports.createHousehold = async (req, res) => {
  try {
    const { name } = req.body;

    if (!name || name.trim().length === 0) {
      return sendError(res, 400, "Household name is required");
    }

    if (name.length > 100) {
      return sendError(res, 400, "Household name must be 100 characters or less");
    }

    const household = await householdModel.createHousehold(
      name.trim(),
      req.user.id
    );

    res.status(201).json({
      message: "Household created successfully",
      household
    });
  } catch (error) {
    logError(req, "households.createHousehold", error);
    sendError(res, 500, "Failed to create household");
  }
};

// Update household
exports.updateHousehold = async (req, res) => {
  try {
    const { name } = req.body;

    if (!name || name.trim().length === 0) {
      return sendError(res, 400, "Household name is required");
    }

    if (name.length > 100) {
      return sendError(res, 400, "Household name must be 100 characters or less");
    }

    const household = await householdModel.updateHousehold(
      req.params.householdId,
      { name: name.trim() }
    );

    res.json({
      message: "Household updated successfully",
      household
    });
  } catch (error) {
    logError(req, "households.updateHousehold", error);
    sendError(res, 500, "Failed to update household");
  }
};

// Delete household
exports.deleteHousehold = async (req, res) => {
  try {
    await householdModel.deleteHousehold(req.params.householdId);
    res.json({ message: "Household deleted successfully" });
  } catch (error) {
    logError(req, "households.deleteHousehold", error);
    sendError(res, 500, "Failed to delete household");
  }
};

// Refresh invite code
exports.refreshInviteCode = async (req, res) => {
  try {
    const household = await householdModel.refreshInviteCode(req.params.householdId);
    res.json({
      message: "Invite code refreshed successfully",
      household
    });
  } catch (error) {
    logError(req, "households.refreshInviteCode", error, {
      invite_last4: inviteCodeLast4(req.body?.inviteCode),
    });
    sendError(res, 500, "Failed to refresh invite code");
  }
};

// Join household via invite code
exports.joinHousehold = async (req, res) => {
  const inviteLast4 = inviteCodeLast4(req.params.inviteCode);
  try {
    const { inviteCode } = req.params;
    if (!inviteCode) return sendError(res, 400, "Invite code is required");

    const result = await householdModel.joinHousehold(
      inviteCode.toUpperCase(),
      req.user.id
    );

    if (!result) return sendError(res, 404, "Invalid or expired invite code");


    if (result.alreadyMember) {
      return res.status(200).json({
        message: "You are already a member of this household",
        household: { id: result.id, name: result.name }
      });
    }

    res.status(200).json({
      message: `Successfully joined ${result.name}`,
      household: { id: result.id, name: result.name }
    });
  } catch (error) {
    logError(req, "households.joinHousehold", error, { invite_last4: inviteLast4 });
    sendError(res, 500, "Failed to join household");
  }
};

// Get household members
exports.getMembers = async (req, res) => {
  try {
    const members = await householdModel.getHouseholdMembers(req.params.householdId);
    res.json(members);
  } catch (error) {
    logError(req, "households.getMembers", error);
    sendError(res, 500, "Failed to fetch members");
  }
};

// Update member role
exports.updateMemberRole = async (req, res) => {
  try {
    const { userId } = req.params;
    const { role } = req.body;

    if (!role || !['admin', 'member'].includes(role)) {
      return sendError(res, 400, "Invalid role. Must be 'admin' or 'member'");
    }

    // Can't change own role
    if (parseInt(userId) === req.user.id) {
      return sendError(res, 400, "Cannot change your own role");
    }

    const targetRole = await householdModel.getUserRole(req.params.householdId, userId);
    if (!targetRole) {
      return sendError(res, 404, "Member not found");
    }
    if (targetRole === "owner") {
      return sendError(res, 403, "Owner role cannot be changed");
    }

    const updated = await householdModel.updateMemberRole(
      req.params.householdId,
      userId,
      role
    );

    res.json({
      message: "Member role updated successfully",
      member: updated
    });
  } catch (error) {
    logError(req, "households.updateMemberRole", error);
    sendError(res, 500, "Failed to update member role");
  }
};

// Remove member
exports.removeMember = async (req, res) => {
  try {
    const { userId } = req.params;
    const targetUserId = parseInt(userId);

    // Allow users to remove themselves, or admins to remove others
    if (targetUserId !== req.user.id && !["owner", "admin"].includes(req.household.role)) {
      return sendError(res, 403, "Only admins or owners can remove other members");
    }

    const targetRole = await householdModel.getUserRole(req.params.householdId, userId);
    if (targetRole === "owner") {
      return sendError(res, 403, "Owner cannot be removed");
    }

    await householdModel.removeMember(req.params.householdId, userId);

    res.json({ message: "Member removed successfully" });
  } catch (error) {
    logError(req, "households.removeMember", error);
    sendError(res, 500, "Failed to remove member");
  }
};
