import base64
import logging

from odoo import fields, models
from odoo.exceptions import UserError

_logger = logging.getLogger(__name__)


class WooOrder(models.Model):
    _name = 'woo.order'
    _description = 'WooCommerce Order'

    instance_id = fields.Many2one('woo.instance', required=True, ondelete='cascade')
    sale_order_id = fields.Many2one('sale.order')
    woo_order_id = fields.Integer(index=True)
    woo_order_number = fields.Char()
    woo_status = fields.Char()
    invoice_id = fields.Many2one('account.move')
    invoice_synced = fields.Boolean()
    company_id = fields.Many2one(
        'res.company', required=True, default=lambda self: self.env.company,
    )
    state = fields.Selection([
        ('new', 'New'),
        ('confirmed', 'Confirmed'),
        ('shipped', 'Shipped'),
        ('completed', 'Completed'),
        ('cancelled', 'Cancelled'),
    ], default='new')
    shipment_ids = fields.One2many('woo.shipment', 'order_id')

    # ------------------------------------------------------------------
    # Push methods (Task 20)
    # ------------------------------------------------------------------

    def action_push_shipping(self, tracking_number, carrier_id=False):
        """Push shipping/tracking info to WooCommerce and update status."""
        self.ensure_one()
        client = self.instance_id._get_client()

        update_data = {
            'status': 'completed',
        }

        # Build tracking meta
        meta = [
            {'key': '_tracking_number', 'value': tracking_number},
        ]
        if carrier_id:
            carrier = self.env['woo.shipping.carrier'].browse(carrier_id)
            if carrier.exists():
                meta.append({'key': '_tracking_provider', 'value': carrier.name})
                if carrier.tracking_url:
                    url = carrier.tracking_url.replace('{tracking}', tracking_number)
                    meta.append({'key': '_tracking_url', 'value': url})

        update_data['meta_data'] = meta

        client.update_order(self.woo_order_id, update_data)
        self.woo_status = 'completed'
        self.state = 'shipped'

        self.instance_id._log_sync(
            'order', 'odoo_to_woo', self.sale_order_id.name,
            'success', f'Shipping pushed with tracking: {tracking_number}',
        )

    def action_push_completed(self):
        """Mark WC order as completed."""
        self.ensure_one()
        client = self.instance_id._get_client()
        client.update_order(self.woo_order_id, {'status': 'completed'})
        self.woo_status = 'completed'
        self.state = 'completed'

        self.instance_id._log_sync(
            'order', 'odoo_to_woo', self.sale_order_id.name,
            'success', 'Order marked as completed in WC',
        )

    def action_push_invoice_pdf(self):
        """Render invoice PDF and push to WC via custom plugin endpoint."""
        self.ensure_one()
        if not self.invoice_id:
            raise UserError("No invoice linked to this WC order.")

        # Generate PDF report
        report = self.env.ref('account.account_invoices')
        pdf_content, _content_type = report._render_qweb_pdf(
            report.id, [self.invoice_id.id]
        )
        pdf_b64 = base64.b64encode(pdf_content).decode('utf-8')

        # Push to WC via order note or meta
        try:
            client = self.instance_id._get_client()
            client.update_order(self.woo_order_id, {
                'meta_data': [
                    {'key': '_odoo_invoice_ref', 'value': self.invoice_id.name},
                    {'key': '_odoo_invoice_pdf', 'value': pdf_b64},
                ]
            })
            self.invoice_synced = True
            self.instance_id._log_sync(
                'invoice', 'odoo_to_woo', self.invoice_id.name,
                'success', 'Invoice PDF pushed to WC',
            )
        except Exception as e:
            _logger.error("Failed to push invoice PDF to WC: %s", e)
            self.instance_id._log_sync(
                'invoice', 'odoo_to_woo', self.invoice_id.name,
                'failed', str(e),
            )
            raise

    def action_push_delivery_pdf(self, picking):
        """Render delivery slip PDF and push to WC."""
        self.ensure_one()
        report = self.env.ref('stock.action_report_delivery')
        pdf_content, _content_type = report._render_qweb_pdf(
            report.id, [picking.id]
        )
        pdf_b64 = base64.b64encode(pdf_content).decode('utf-8')

        try:
            client = self.instance_id._get_client()
            client.update_order(self.woo_order_id, {
                'meta_data': [
                    {'key': '_odoo_delivery_ref', 'value': picking.name},
                    {'key': '_odoo_delivery_pdf', 'value': pdf_b64},
                ]
            })
            self.instance_id._log_sync(
                'order', 'odoo_to_woo', picking.name,
                'success', 'Delivery PDF pushed to WC',
            )
        except Exception as e:
            _logger.error("Failed to push delivery PDF to WC: %s", e)

    def _push_messages_to_wc(self):
        """Extract customer-visible messages and push as WC order notes."""
        self.ensure_one()
        if not self.sale_order_id:
            return

        client = self.instance_id._get_client()

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

        for msg in messages:
            note_body = msg.body or msg.preview or ''
            if not note_body:
                continue
            try:
                # WC order notes endpoint
                client.post(f'orders/{self.woo_order_id}/notes', {
                    'note': note_body,
                    'customer_note': True,
                })
            except Exception as e:
                _logger.warning(
                    "Failed to push message to WC order %s: %s",
                    self.woo_order_id, e,
                )
