import logging

from odoo import _, http
from odoo.exceptions import UserError
from odoo.http import request
from odoo.tools import html_escape

from ..models.leave_email import _BASE_TYPE_LABELS

_logger = logging.getLogger(__name__)

_PAGE = """<!DOCTYPE html><html><head><meta charset="utf-8">
<title>Leave Request</title></head>
<body style="font-family:Arial,Helvetica,sans-serif;background:#f8f9fa;">
<div style="max-width:480px;margin:80px auto;text-align:center;padding:2rem;
            background:#fff;border:1px solid #d8e1e4;border-radius:8px;">
<h2 style="color:%(color)s;margin-top:0;">%(message)s</h2>
</div></body></html>"""

# Result card for the two actual decision outcomes (approve/reject) --
# every other page on this controller (malformed link, expired, already
# processed, etc.) keeps the plain _PAGE above, since those aren't a
# decision result and mostly don't have full leave details on hand.
_RESULT_PAGE = """<!DOCTYPE html><html><head><meta charset="utf-8">
<title>Leave Request</title></head>
<body style="font-family:Arial,Helvetica,sans-serif;background:#3d5afe;margin:0;padding:48px 16px;">
<div style="max-width:420px;margin:0 auto;background:#f2f3f5;border-radius:14px;
            padding:32px 28px;text-align:center;box-shadow:0 6px 24px rgba(0,0,0,0.18);">
  <div style="font-weight:800;font-size:1.25rem;letter-spacing:0.03em;color:#1a2233;margin-bottom:18px;">
    LEAVE REQUESTING APPROVAL
  </div>
  <div style="border-top:1px solid #d8dce3;margin-bottom:18px;"></div>
  <div style="font-size:0.9rem;color:#4b5563;line-height:1.9;">
    Employee Name:<br/>
    <strong style="color:#1a2233;">%(employee)s</strong><br/>
    Leave Name:<br/>
    <strong style="color:#1a2233;">%(leave_name)s</strong><br/>
    Leave Type:<br/>
    <strong style="color:#1a2233;">%(leave_type)s</strong><br/>
    Reason:<br/>
    <strong style="color:#1a2233;">%(reason)s</strong><br/>
    Leave Date:<br/>
    <strong style="color:#1a2233;">%(dates)s</strong>
  </div>
  <div style="font-weight:800;font-size:1.15rem;color:%(color)s;margin-top:22px;">
    Result: %(result)s Completed
  </div>
</div></body></html>"""


def _xeno_leave_type_full_name(name):
    """'Sick Leave . SL' -> 'Sick Leave' -- the inverse of leave_email.py's
    _xeno_leave_abbr (which keeps the trailing code instead)."""
    if name and "." in name:
        return name.rsplit(".", 1)[0].strip()
    return (name or "").strip()


class XenoLeaveEmailController(http.Controller):

    def _page(self, message, ok=True):
        color = "#1f7a4d" if ok else "#b21f22"
        return request.make_response(
            _PAGE % {"color": color, "message": message},
            headers=[("Content-Type", "text/html; charset=utf-8")],
        )

    def _result_page(self, leave, result_word, ok=True):
        L = leave.sudo()
        emp = L.employee_id
        basis_label = _BASE_TYPE_LABELS.get(L.xeno_request_unit) or _("Full-day Leave")
        date_from, date_to = L.request_date_from, L.request_date_to
        if date_from and date_to and date_from != date_to:
            dates = "%s - %s" % (date_from.strftime("%d/%m/%Y"), date_to.strftime("%d/%m/%Y"))
        elif date_from:
            dates = date_from.strftime("%d/%m/%Y")
        else:
            dates = ""
        color = "#1f9d55" if ok else "#d32f2f"
        return request.make_response(
            _RESULT_PAGE % {
                "employee": html_escape("%s %s" % (emp.xeno_employee_code or "", emp.name)).strip(),
                "leave_name": html_escape(_xeno_leave_type_full_name(L.holiday_status_id.name)),
                "leave_type": html_escape(basis_label),
                "reason": html_escape(L.name or "-"),
                "dates": html_escape(dates),
                "color": color,
                "result": result_word,
            },
            headers=[("Content-Type", "text/html; charset=utf-8")],
        )

    @http.route(
        "/odoo/leave/email_action",
        type="http", auth="public", website=False, sitemap=False, csrf=False,
    )
    def email_action(self, leave_id=None, step_id=None, action=None,
                      user_id=None, exp=None, token=None, **kw):
        """Approve/Reject a leave straight from the notification email.
        Authorization is the signed token itself (see hr.leave.
        _xeno_verify_email_token) -- it proves this exact link was issued by
        us for this exact leave/step/action/user and hasn't expired, which
        replaces "are you logged in" for a recipient who almost certainly
        isn't. The actual business permission (is this user allowed to act
        on this step right now) still runs through the same
        action_approve/action_refuse checks as the in-app buttons.
        """
        env = request.env
        Leave = env["hr.leave"].sudo()

        try:
            leave_id, step_id, user_id, exp = int(leave_id), int(step_id), int(user_id), int(exp)
        except (TypeError, ValueError):
            return self._page(_("This link is malformed."), ok=False)

        if action not in ("approve", "reject"):
            return self._page(_("This link is malformed."), ok=False)

        # This is a public, unauthenticated route (there's no logged-in
        # user whose res.lang would normally drive translation) -- once we
        # have a leave_id, switch context to whichever language the leave's
        # own employee is set up with, so the approver sees this page in
        # their own language rather than always the system default.
        leave_lang = Leave.browse(leave_id).employee_id.sudo().user_id.lang
        if leave_lang:
            env = env(context=dict(env.context, lang=leave_lang))
            Leave = env["hr.leave"].sudo()

        if not Leave._xeno_verify_email_token(leave_id, step_id, action, user_id, exp, token):
            return self._page(_("This link is invalid or has expired."), ok=False)

        leave = Leave.browse(leave_id)
        step = env["xeno.leave.approval.step"].sudo().browse(step_id)
        user = env["res.users"].sudo().browse(user_id)
        if not (leave.exists() and step.exists() and user.exists()) or step.leave_id != leave:
            return self._page(_("This leave request no longer exists."), ok=False)

        if step.state != "pending":
            return self._page(_("This leave request has already been processed."))

        if leave._xeno_current_pending_step() != step:
            return self._page(_(
                "This step was already handled (possibly by someone else) "
                "or is no longer awaiting action."))

        leave_as_user = leave.with_user(user)
        try:
            if action == "approve":
                leave_as_user.action_approve(check_state=False)
                return self._result_page(leave, _("Approved"), ok=True)
            leave_as_user.action_refuse()
            return self._result_page(leave, _("Rejected"), ok=False)
        except UserError as e:
            return self._page(str(e), ok=False)
        except Exception:
            _logger.exception("xeno_leave email_action failed for leave %s step %s", leave_id, step_id)
            return self._page(_(
                "Something went wrong processing this request. Please use the app instead."
            ), ok=False)
