const Policy = require("../models/policyModel");
const { errorResponse } = require("../utils/errorResponseHandler");
const { logUserAction } = require("../utils/userActionLogger");


const createPolicy = async (req, res) => {
  try {
    const userId = req.user._id;
    const orgId = req.user.orgId;

    const {
      policyId,
      name,
      category,
      description,
      effectiveDate,
      expiryDate,
      status,
    } = req.body;

    if (!policyId || !name || !category || !effectiveDate) {
      return errorResponse(res, "Required fields are missing", 400);
    }

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

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

    const policy = await Policy.create({
      policyId,
      name,
      category,
      description,
      effectiveDate,
      expiryDate: expiryDate || null,
      status: status || "Active",
      orgId,
      createdBy: userId,
      updatedBy: userId,
    });

    await logUserAction({
      userId,
      action: "CREATE",
      model: "Policy",
      details: { policyId: policy._id },
      req,
    });

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

const getPolicyById = async (req, res) => {
  try {
    const policy = await Policy.findOne({
      _id: req.params.id,
      orgId: req.user.orgId,
      isDeleted: false,
    })
      .populate("createdBy", "firstName lastName email")
      .populate("updatedBy", "firstName lastName email");

    if (!policy) return errorResponse(res, "Policy not found", 404);

    await logUserAction({
      userId: req.user._id,
      action: "READ",
      model: "Policy",
      details: { policyId: policy._id },
      req,
    });

    return res.json({
      success: true,
      data: policy,
    });
  } catch (error) {
    return errorResponse(res, "Failed to fetch policy", 500, error);
  }
};


const getPolicies = async (req, res) => {
  try {
    let { page = 1, limit = 10, search = "", status, category } = req.query;

    page = parseInt(page);
    limit = parseInt(limit);
    const skip = (page - 1) * limit;

    const query = {
      orgId: req.user.orgId,
      isDeleted: false,
    };

    if (status) query.status = status;
    if (category) query.category = category;

    if (search) {
      query.$or = [
        { policyId: { $regex: search, $options: "i" } },
        { name: { $regex: search, $options: "i" } },
        { category: { $regex: search, $options: "i" } },
      ];
    }

    const [policies, total] = await Promise.all([
      Policy.find(query)
        .sort({ updatedAt: -1 })
        .skip(skip)
        .limit(limit)
        .populate("createdBy", "firstName lastName")
        .populate("updatedBy", "firstName lastName"),

      Policy.countDocuments(query),
    ]);

    await logUserAction({
      userId: req.user._id,
      action: "READ",
      model: "Policy",
      details: { page, limit, count: policies.length },
      req,
    });

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


const updatePolicy = async (req, res) => {
  try {
    const updatedData = {
      ...req.body,
      updatedBy: req.user._id,
    };

    const policy = await Policy.findOneAndUpdate(
      {
        _id: req.params.id,
        orgId: req.user.orgId,
        isDeleted: false,
      },
      updatedData,
      { new: true, runValidators: true }
    );

    if (!policy) return errorResponse(res, "Policy not found", 404);

    await logUserAction({
      userId: req.user._id,
      action: "UPDATE",
      model: "Policy",
      details: { policyId: policy._id, updatedFields: updatedData },
      req,
    });

    return res.json({
      success: true,
      message: "Policy updated successfully",
      data: policy,
    });
  } catch (error) {
    return errorResponse(res, "Failed to update policy", 500, error);
  }
};


const updatePolicyStatus = async (req, res) => {
  try {
    const { status } = req.body;

    if (!["Active", "Inactive", "Archived"].includes(status)) {
      return errorResponse(res, "Invalid status value", 400);
    }

    const policy = await Policy.findOneAndUpdate(
      {
        _id: req.params.id,
        orgId: req.user.orgId,
        isDeleted: false,
      },
      { status, updatedBy: req.user._id },
      { new: true }
    );

    if (!policy) return errorResponse(res, "Policy not found", 404);

    await logUserAction({
      userId: req.user._id,
      action: "STATUS_UPDATE",
      model: "Policy",
      details: { policyId: policy._id, status },
      req,
    });

    return res.json({
      success: true,
      message: "Policy status updated",
      data: policy,
    });
  } catch (error) {
    return errorResponse(res, "Failed to update policy status", 500, error);
  }
};

const deletePolicy = async (req, res) => {
  try {
    const policy = await Policy.findOneAndUpdate(
      {
        _id: req.params.id,
        orgId: req.user.orgId,
        isDeleted: false,
      },
      { isDeleted: true, updatedBy: req.user._id },
      { new: true }
    );

    if (!policy) return errorResponse(res, "Policy not found", 404);

    await logUserAction({
      userId: req.user._id,
      action: "DELETE",
      model: "Policy",
      details: { policyId: policy._id },
      req,
    });

    return res.json({
      success: true,
      message: "Policy deleted successfully",
      data: policy,
    });
  } catch (error) {
    return errorResponse(res, "Failed to delete policy", 500, error);
  }
};

module.exports = {
  createPolicy,
  getPolicyById,
  getPolicies,
  updatePolicy,
  updatePolicyStatus,
  deletePolicy,
};
