# -*- coding: utf-8 -*-
# Copyright 2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)

import logging

from odoo import http
from odoo.exceptions import AccessDenied
from odoo.http import request

_logger = logging.getLogger(__name__)


class WooApiController(http.Controller):
    """REST endpoints consumed by the WooCommerce WordPress plugin."""

    def _authenticate_instance(self):
        """
        Validate Bearer token from Authorization header against woo.instance.odoo_api_key.
        Returns the matching woo.instance or raises AccessDenied.
        """
        auth_header = request.httprequest.headers.get('Authorization', '')
        if not auth_header.startswith('Bearer '):
            raise AccessDenied()

        api_key = auth_header[len('Bearer '):]
        if not api_key:
            raise AccessDenied()

        instance = request.env['woo.instance'].sudo().search([
            ('odoo_api_key', '=', api_key),
        ], limit=1)

        if not instance:
            raise AccessDenied()

        return instance

    def _find_woo_order(self, instance, order_id):
        """Look up a woo.order by WC order ID for a given instance."""
        return request.env['woo.order'].sudo().search([
            ('instance_id', '=', instance.id),
            ('woo_order_id', '=', int(order_id)),
        ], limit=1)

    # -------------------------------------------------------------------------
    # Endpoints
    # -------------------------------------------------------------------------

    @http.route(
        '/woo/api/order/documents',
        type='jsonrpc', auth='none', csrf=False, methods=['POST'],
    )
    def order_documents(self, order_id=None, **kw):
        """
        Fetch invoice and delivery PDF URLs for a WooCommerce order.

        Expected payload: {"order_id": <woo_order_id>}
        Returns: {"invoices": [...], "deliveries": [...]}
        """
        try:
            instance = self._authenticate_instance()
        except AccessDenied:
            return {'error': 'Unauthorized', 'code': 401}

        if not order_id:
            return {'error': 'order_id is required', 'code': 400}

        woo_order = self._find_woo_order(instance, order_id)
        if not woo_order:
            return {'order_id': order_id, 'invoices': [], 'deliveries': []}

        invoices = []
        if woo_order.invoice_id:
            inv = woo_order.invoice_id
            invoices.append({
                'id': inv.id,
                'name': inv.name,
                'state': inv.state,
                'amount_total': inv.amount_total,
                'date': str(inv.invoice_date) if inv.invoice_date else '',
            })

        deliveries = []
        if woo_order.sale_order_id:
            pickings = request.env['stock.picking'].sudo().search([
                ('origin', '=', woo_order.sale_order_id.name),
                ('picking_type_code', '=', 'outgoing'),
            ])
            for picking in pickings:
                deliveries.append({
                    'id': picking.id,
                    'name': picking.name,
                    'state': picking.state,
                    'tracking_number': picking.woo_tracking_number or '',
                    'scheduled_date': str(picking.scheduled_date) if picking.scheduled_date else '',
                })

        return {
            'order_id': order_id,
            'invoices': invoices,
            'deliveries': deliveries,
        }

    @http.route(
        '/woo/api/order/status',
        type='jsonrpc', auth='none', csrf=False, methods=['POST'],
    )
    def order_status(self, order_id=None, **kw):
        """
        Fetch order status and timeline data for a WooCommerce order.

        Expected payload: {"order_id": <woo_order_id>}
        Returns: {"status": ..., "timeline": [...]}
        """
        try:
            instance = self._authenticate_instance()
        except AccessDenied:
            return {'error': 'Unauthorized', 'code': 401}

        if not order_id:
            return {'error': 'order_id is required', 'code': 400}

        woo_order = self._find_woo_order(instance, order_id)
        if not woo_order:
            return {
                'order_id': order_id,
                'status': None,
                'odoo_state': None,
                'timeline': [],
            }

        # Build timeline from tracking messages
        timeline = []
        if woo_order.sale_order_id:
            messages = request.env['mail.message'].sudo().search([
                ('res_id', '=', woo_order.sale_order_id.id),
                ('model', '=', 'sale.order'),
            ], order='create_date asc')
            for msg in messages:
                timeline.append({
                    'date': str(msg.create_date),
                    'type': msg.message_type,
                    'body': msg.preview or '',
                })

        # Add shipment events
        for shipment in woo_order.shipment_ids:
            timeline.append({
                'date': str(shipment.shipped_date) if shipment.shipped_date else '',
                'type': 'shipment',
                'body': f'Shipped via {shipment.carrier_id.name if shipment.carrier_id else "carrier"} — tracking: {shipment.tracking_number or "N/A"}',
            })

        return {
            'order_id': order_id,
            'status': woo_order.woo_status,
            'odoo_state': woo_order.state,
            'odoo_order_ref': woo_order.sale_order_id.name if woo_order.sale_order_id else '',
            'timeline': timeline,
        }

    @http.route(
        '/woo/api/order/messages',
        type='jsonrpc', auth='none', csrf=False, methods=['POST'],
    )
    def order_messages(self, order_id=None, **kw):
        """
        Fetch customer-visible messages for a WooCommerce order.

        Expected payload: {"order_id": <woo_order_id>}
        Returns: {"messages": [...]}
        """
        try:
            instance = self._authenticate_instance()
        except AccessDenied:
            return {'error': 'Unauthorized', 'code': 401}

        if not order_id:
            return {'error': 'order_id is required', 'code': 400}

        woo_order = self._find_woo_order(instance, order_id)
        if not woo_order or not woo_order.sale_order_id:
            return {'order_id': order_id, 'messages': []}

        # Get customer-visible messages
        messages = request.env['mail.message'].sudo().search([
            ('res_id', '=', woo_order.sale_order_id.id),
            ('model', '=', 'sale.order'),
            ('message_type', 'in', ['comment', 'email']),
            ('subtype_id.internal', '=', False),
        ], order='create_date asc')

        result = []
        for msg in messages:
            result.append({
                'date': str(msg.create_date),
                'author': msg.author_id.name if msg.author_id else '',
                'body': msg.body or '',
            })

        return {
            'order_id': order_id,
            'messages': result,
        }

    @http.route(
        '/woo/api/return/create',
        type='jsonrpc', auth='none', csrf=False, methods=['POST'],
    )
    def return_create(self, order_id=None, reason=None, items=None, **kw):
        """
        Submit a return request from the WooCommerce plugin.

        Expected payload: {
            "order_id": <woo_order_id>,
            "reason": "<return reason>",
            "items": [{"product_id": ..., "quantity": ..., "reason": ...}, ...]
        }
        Returns: {"success": True, "return_id": <id>} or {"error": ...}
        """
        try:
            instance = self._authenticate_instance()
        except AccessDenied:
            return {'error': 'Unauthorized', 'code': 401}

        if not order_id:
            return {'error': 'order_id is required', 'code': 400}

        woo_order = self._find_woo_order(instance, order_id)
        if not woo_order:
            return {'error': 'Order not found', 'code': 404}

        items = items or []
        if not items:
            return {'error': 'At least one return item is required', 'code': 400}

        # Create woo.return
        woo_return = request.env['woo.return'].sudo().create({
            'instance_id': instance.id,
            'order_id': woo_order.id,
            'reason': reason or '',
            'company_id': instance.company_id.id,
        })

        # Create return lines
        for item in items:
            wc_product_id = item.get('product_id')
            quantity = item.get('quantity', 1)
            item_reason = item.get('reason', 'other')

            # Find mapped Odoo product
            product = False
            if wc_product_id:
                pm = request.env['woo.product.map'].sudo().search([
                    ('instance_id', '=', instance.id),
                    ('woo_product_id', '=', wc_product_id),
                    ('state', '=', 'mapped'),
                ], limit=1)
                if pm:
                    product = pm.product_id

            if not product:
                # Try SKU from the item
                sku = item.get('sku', '')
                if sku:
                    product = request.env['product.product'].sudo().search([
                        ('default_code', '=', sku),
                    ], limit=1)

            if product:
                request.env['woo.return.line'].sudo().create({
                    'return_id': woo_return.id,
                    'product_id': product.id,
                    'quantity': quantity,
                    'reason': item_reason if item_reason in dict(
                        request.env['woo.return.line']._fields['reason'].selection
                    ) else 'other',
                    'company_id': instance.company_id.id,
                })

        instance._log_sync(
            'order', 'woo_to_odoo',
            woo_order.sale_order_id.name if woo_order.sale_order_id else f'WC#{order_id}',
            'success', f'Return request created with {len(items)} item(s)',
        )

        return {
            'success': True,
            'return_id': woo_return.id,
            'message': 'Return request received.',
        }
