const Branch = require("../models/branchModel");
const User = require("../models/userModel");
const { errorResponse } = require("../utils/errorResponseHandler");
const { logUserAction } = require("../utils/userActionLogger");


const createBranch = async (req, res) => {
  try {
    const {
      branchId,
      branchCode,
      branchName,
      branchType,
      openingDate,
      manager,
      parentBranchId,
      address,
      contact,
      operationalHours,
      ifscCode,
      swiftCode,
      services,
      facilities,
      compliance,
      emergencyContacts,
      notes,
      status,
    } = req.body;

    const orgId = req.user?.orgId || req.query.orgId || req.body.orgId;

    //  Required validation
    if (
      !branchId ||
      !branchName ||
      !manager ||
      !address?.city ||
      !address?.state ||
      !contact?.phone
    ) {
      return errorResponse(res, "Missing required branch fields", 400);
    }

    //  Validate manager (must be user with role=manager)
    // const managerUser = await User.findOne({
    //   _id: manager,
    //   role: "manager",
    //   orgId: req.user.orgId,
    //   isDeleted: false,
    // });

    // if (!managerUser) {
    //   return errorResponse(res, "Invalid branch manager", 400);
    // }

    //  Prevent duplicate branchId per org
    const exists = await Branch.findOne({
      branchId,
      orgId: orgId,
      isDeleted: false,
    });

    if (exists) {
      return errorResponse(res, "Branch with this ID already exists", 409);
    }

    const branch = await Branch.create({
      branchId,
      branchCode,
      branchName,
      branchType,
      openingDate,
      manager,
      parentBranchId,
      address,
      contact,
      operationalHours,
      ifscCode,
      swiftCode,
      services,
      facilities,
      compliance,
      emergencyContacts,
      notes,
      status: status || "Active",
      orgId: orgId,
      createdBy: req.user._id,
    });

    await logUserAction({
      userId: req.user._id,
      action: "CREATE",
      model: "Branch",
      details: { branchId: branch._id, branchName },
      req,
    });

    return res.status(201).json({
      success: true,
      message: "Branch created successfully",
      data: branch,
    });
  } catch (error) {
    console.error("Create Branch Error:", error);
    return errorResponse(res, "Failed to create branch", 500, error);
  }
};

const getBranches = async (req, res) => {
  try {
    let { page = 1, limit = 10, search = "", status,  } = req.query;
     console.log("REQ.USER:", req.user);
    page = Number(page);
    limit = Number(limit);
    const skip = (page - 1) * limit;
    const orgId = req.user?.orgId || req.query.orgId || req.body.orgId;


    const query = {
      orgId: orgId,
      isDeleted: false,
    };

    //  Status filter
    if (status && ["Active", "Inactive"].includes(status)) {
      query.status = status;
    }

    //  Search across real schema fields
    if (search) {
      query.$or = [
        { branchId: { $regex: search, $options: "i" } },
        { branchName: { $regex: search, $options: "i" } },
        { "address.city": { $regex: search, $options: "i" } },
        { "address.state": { $regex: search, $options: "i" } },
        { "address.country": { $regex: search, $options: "i" } },
        { "contact.phone": { $regex: search, $options: "i" } },
        { "contact.email": { $regex: search, $options: "i" } },
        { ifscCode: { $regex: search, $options: "i" } },
      ];
    }

    const [branches, total] = await Promise.all([
      Branch.find(query)
        .populate("manager", "firstName lastName email phone role")
        .populate("parentBranchId", "branchId branchName")
        .sort({ createdAt: -1 })
        .skip(skip)
        .limit(limit)
        .lean(),

      Branch.countDocuments(query),
    ]);

    return res.status(200).json({
      success: true,
      total,
      page,
      limit,
      totalPages: Math.ceil(total / limit),
      data: branches,
    });
  } catch (error) {
    console.error("Fetch Branch Error:", error);
    return errorResponse(res, "Failed to fetch branches", 500, error);
  }
};



const getBranchById = async (req, res) => {
  try {
    
    //  Validate ObjectId early (prevents DB crash)
    // if (!id || !id.match(/^[0-9a-fA-F]{24}$/)) {
    //   return errorResponse(res, "Invalid branch ID", 400);
    // }

    //  Org-level + soft-delete protection
    const orgId = req.user?.orgId || req.query.orgId || req.body.orgId;
    const branch = await Branch.findOne({
      _id: req.params.id,
      orgId: orgId,
      isDeleted: false,
    })
      .populate("manager", "firstName lastName email phone role")
      .populate("parentBranchId", "branchId branchName")
      .lean();

    if (!branch) {
      return errorResponse(res, "Branch not found", 404);
    }

    //  Optional audit log
    await logUserAction({
      userId: req.user._id,
      action: "READ",
      model: "Branch",
      details: { branchId: branch._id },
      req,
    });

    return res.status(200).json({
      success: true,
      data: branch,
    });
  } catch (error) {
    console.error("Get Branch By ID Error:", error);
    return errorResponse(res, "Failed to fetch branch details", 500, error);
  }
};

const updateBranch = async (req, res) => {
  try {
    const { id } = req.params;
    const orgId = req.user?.orgId || req.query.orgId || req.body.orgId;

    const branch = await Branch.findOne({
      _id: id,
      orgId: orgId,
      isDeleted: false,
    });

    if (!branch) {
      return errorResponse(res, "Branch not found", 404);
    }

    const allowedFields = [
      "branchCode",
      "branchName",
      "branchType",
      "openingDate",
      "manager",
      "parentBranchId",
      "address",
      "contact",
      "operationalHours",
      "ifscCode",
      "swiftCode",
      "services",
      "facilities",
      "compliance",
      "emergencyContacts",
      "notes",
      "status",
    ];

    for (const field of allowedFields) {
      if (req.body[field] !== undefined) {
        branch[field] = req.body[field];
      }
    }


    // need to check this below code later..
    //  Validate manager if changed
    // if (req.body.manager) {
    //   const managerUser = await User.findOne({
    //     _id: req.body.manager,
    //     role: "manager",
    //     orgId: req.user.orgId,
    //     isDeleted: false,
    //   });

    //   if (!managerUser) {
    //     return errorResponse(res, "Invalid manager selected", 400);
    //   }
    // }

    branch.updatedBy = req.user._id;
    await branch.save();

    await logUserAction({
      userId: req.user._id,
      action: "UPDATE",
      model: "Branch",
      details: { branchId: branch._id },
      req,
    });

    return res.status(200).json({
      success: true,
      message: "Branch updated successfully",
      data: branch,
    });
  } catch (error) {
    console.error("Update Branch Error:", error);
    return errorResponse(res, "Failed to update branch", 500, error);
  }
};


const deleteBranch = async (req, res) => {
  try {
    const { id } = req.params;
    const orgId = req.user?.orgId || req.query.orgId || req.body.orgId;

    const branch = await Branch.findOne({
      _id: id,
      orgId: orgId,
      isDeleted: false,
    });

    if (!branch) {
      return errorResponse(res, "Branch not found", 404);
    }

    branch.isDeleted = true;
    branch.updatedBy = req.user._id;
    await branch.save();

    await logUserAction({
      userId: req.user._id,
      action: "DELETE",
      model: "Branch",
      details: { branchId: branch._id },
      req,
    });

    return res.status(200).json({
      success: true,
      message: "Branch deleted successfully",
    });
  } catch (error) {
    console.error("Delete Branch Error:", error);
    return errorResponse(res, "Failed to delete branch", 500, error);
  }
};

module.exports = {
  createBranch,
  getBranches,
  updateBranch,
  deleteBranch,
  getBranchById,
};
