# -*- coding: utf-8 -*-
"""Browser-mediated S-MDF signing for the cloud POS.

In a hosted deployment the Odoo server has no route to the taxpayer's till:
the S-MDF Agent listens on the cashier's loopback, behind the shop's router.
The cashier's browser is the only party that can reach both, so it carries the
signature between them:

    browser  --/nacef/pos/sign/payload-->  Odoo      (what must be signed)
    browser  --http://127.0.0.1:10016-->   connector --> S-MDF Agent :10006
    browser  --/nacef/pos/sign/confirm-->  Odoo      (the signature)

Only the transport moves. Every fiscally meaningful step — the E0302 guard,
the gapless reference (E0402), schema validation (E0803), the inalterability
chain (E1101) and the audit trail (E0901) — stays on the server, where the
client cannot influence it.
"""
from odoo import http
from odoo.exceptions import UserError
from odoo.http import request


class NacefPosSignController(http.Controller):

    def _order(self, order_id):
        """Fetch the order as the calling cashier, not as sudo.

        Reading it through the user's own rights is what keeps one tenant's
        cashier from signing another company's ticket: record rules apply.
        """
        order = request.env["pos.order"].browse(int(order_id))
        order.check_access_rights("write")
        order.check_access_rule("write")
        if not order.exists():
            raise UserError("Ticket introuvable.")
        return order

    @http.route("/nacef/pos/fiscal/state", type="json", auth="user")
    def state(self, order_ids, **kw):
        """Fiscal state of freshly synced orders, keyed by server id.

        The frontend cannot read this off the sync response: Odoo 17's
        ``create_from_ui`` returns only ``id``, ``pos_reference`` and
        ``account_move``, so every nacef_* field is undefined there. Asking
        explicitly keeps us independent of that response shape.
        """
        orders = request.env["pos.order"].browse(
            [int(i) for i in (order_ids or [])]).exists()
        if not orders:
            return []
        orders.check_access_rights("read")
        orders.check_access_rule("read")
        return [order._nacef_ui_payload() for order in orders]

    @http.route("/nacef/pos/sign/payload", type="json", auth="user")
    def payload(self, order_id, payment_source=None, **kw):
        """Return the A3 ticket the till's S-MDF must sign."""
        order = self._order(order_id)
        return {
            "order_id": order.id,
            "fiscal_reference": order.nacef_fiscal_reference,
            "ticket": order._nacef_signature_payload(
                payment_source=payment_source),
        }

    @http.route("/nacef/pos/sign/confirm", type="json", auth="user")
    def confirm(self, order_id, response, **kw):
        """Seal the order with the signature obtained on the till."""
        order = self._order(order_id)
        order._nacef_confirm_signature(response)
        return {
            "order_id": order.id,
            "signed": order.nacef_signed,
            "fiscal_reference": order.nacef_fiscal_reference,
            "ticket_identifier": order.nacef_ticket_identifier,
            "qr_code": order.nacef_qr_code or False,
            "mention": order._nacef_mention(),
        }
