from odoo import api, fields, models


class XenoLeaveApprovalStep(models.Model):
    _name = "xeno.leave.approval.step"
    _description = "Per-leave approval chain step (snapshot at submission time)"
    _order = "leave_id, step_order"

    leave_id = fields.Many2one(
        "hr.leave", required=True, ondelete="cascade", index=True)
    step_order = fields.Integer(required=True)
    label = fields.Char(required=True)
    approver_user_id = fields.Many2one(
        "res.users", string="Approver",
        help="Specific approver for this step. Blank means any Time Off "
             "Officer/Administrator may act on it.")
    state = fields.Selection(
        [("pending", "Pending"), ("approved", "Approved"), ("rejected", "Rejected")],
        default="pending", required=True)
    decided_by = fields.Many2one("res.users", readonly=True)
    decided_at = fields.Datetime(readonly=True)

    # ---- surfaced for the "Approval Chain Status" HR monitor page, so it
    # doesn't need to join through hr.leave in the view itself.
    leave_employee_id = fields.Many2one(
        related="leave_id.employee_id", string="Employee", store=True)
    leave_department_id = fields.Many2one(
        related="leave_id.employee_id.department_id", string="Department", store=True)
    leave_type_id = fields.Many2one(
        related="leave_id.holiday_status_id", string="Leave Type", store=True)
    leave_state = fields.Selection(
        related="leave_id.state", string="Leave Status", store=True)
    leave_request_date_from = fields.Date(
        related="leave_id.request_date_from", string="Start Date", store=True)
    leave_number_of_days = fields.Float(
        related="leave_id.number_of_days", string="Days", store=True)

    xeno_total_steps = fields.Integer(
        compute="_compute_xeno_chain_meta", store=True,
        string="Total Steps",
        help="How many steps this leave's whole chain has, so the pending "
             "one can show '2 of 3' rather than just its own step_order.")
    xeno_waiting_since = fields.Datetime(
        compute="_compute_xeno_chain_meta", store=True,
        string="Waiting Since",
        help="When this step actually became the current one: the leave's "
             "own submission time for step 1, or whenever the previous "
             "step was decided for any later step.")
    xeno_is_self_block = fields.Boolean(
        compute="_compute_xeno_chain_meta", store=True,
        string="Stuck (self-approval)",
        help="This step's specific approver is the same person who "
             "requested the leave -- xeno_leave's own self-approval guard "
             "will never let them clear it, so it needs an HR Force "
             "Approve/Reject or a different approver configured.",
    )

    @api.depends(
        "leave_id.xeno_approval_step_ids.state",
        "leave_id.xeno_approval_step_ids.step_order",
        "leave_id.xeno_approval_step_ids.decided_at",
        "leave_id.create_date",
        "step_order", "approver_user_id", "leave_id.employee_id.user_id",
    )
    def _compute_xeno_chain_meta(self):
        for step in self:
            siblings = step.leave_id.xeno_approval_step_ids
            step.xeno_total_steps = len(siblings)
            if step.step_order <= 1:
                step.xeno_waiting_since = step.leave_id.create_date
            else:
                prior_decided = siblings.filtered(
                    lambda s: s.step_order < step.step_order and s.decided_at
                ).mapped("decided_at")
                step.xeno_waiting_since = max(prior_decided) if prior_decided \
                    else step.leave_id.create_date
            step.xeno_is_self_block = bool(
                step.approver_user_id
                and step.leave_id.employee_id.user_id
                and step.approver_user_id == step.leave_id.employee_id.user_id
            )
