import logging

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

_logger = logging.getLogger(__name__)


class WooReturn(models.Model):
    _name = 'woo.return'
    _description = 'WooCommerce Return'

    instance_id = fields.Many2one('woo.instance', required=True, ondelete='cascade')
    order_id = fields.Many2one('woo.order', required=True)
    picking_id = fields.Many2one('stock.picking')
    reason = fields.Text()
    line_ids = fields.One2many('woo.return.line', 'return_id')
    state = fields.Selection([
        ('requested', 'Requested'),
        ('approved', 'Approved'),
        ('received', 'Received'),
        ('refunded', 'Refunded'),
        ('rejected', 'Rejected'),
    ], default='requested')
    company_id = fields.Many2one(
        'res.company', required=True, default=lambda self: self.env.company,
    )

    # ------------------------------------------------------------------
    # Workflow methods (Task 24)
    # ------------------------------------------------------------------

    def action_approve(self):
        """Approve the return — create a reverse stock.picking."""
        self.ensure_one()
        if self.state != 'requested':
            raise UserError("Only requested returns can be approved.")

        sale_order = self.order_id.sale_order_id
        if not sale_order:
            raise UserError("No sale order linked to this WC order.")

        # Find the outbound delivery picking
        delivery_picking = self.env['stock.picking'].search([
            ('origin', '=', sale_order.name),
            ('picking_type_code', '=', 'outgoing'),
            ('state', '=', 'done'),
        ], limit=1)

        if delivery_picking:
            # Create return picking via stock.return.picking wizard
            return_wizard = self.env['stock.return.picking'].with_context(
                active_id=delivery_picking.id,
                active_model='stock.picking',
            ).create({})

            # Update quantities based on return lines
            for wizard_line in return_wizard.product_return_moves:
                return_line = self.line_ids.filtered(
                    lambda l: l.product_id == wizard_line.product_id
                )
                if return_line:
                    wizard_line.quantity = return_line[0].quantity
                else:
                    wizard_line.quantity = 0

            # Remove lines with 0 quantity
            return_wizard.product_return_moves.filtered(
                lambda l: l.quantity == 0
            ).unlink()

            if return_wizard.product_return_moves:
                result = return_wizard.action_create_returns()
                if result and result.get('res_id'):
                    self.picking_id = result['res_id']

        self.state = 'approved'

        # Push status to WC
        try:
            client = self.instance_id._get_client()
            client.update_order(self.order_id.woo_order_id, {
                'meta_data': [
                    {'key': '_return_status', 'value': 'approved'},
                ]
            })
        except Exception as e:
            _logger.warning("Failed to push return approval to WC: %s", e)

        self.instance_id._log_sync(
            'order', 'odoo_to_woo', self.order_id.sale_order_id.name,
            'success', 'Return approved',
        )

    def action_reject(self):
        """Reject the return request."""
        self.ensure_one()
        if self.state != 'requested':
            raise UserError("Only requested returns can be rejected.")

        self.state = 'rejected'

        try:
            client = self.instance_id._get_client()
            client.update_order(self.order_id.woo_order_id, {
                'meta_data': [
                    {'key': '_return_status', 'value': 'rejected'},
                ]
            })
        except Exception as e:
            _logger.warning("Failed to push return rejection to WC: %s", e)

        self.instance_id._log_sync(
            'order', 'odoo_to_woo', self.order_id.sale_order_id.name,
            'success', 'Return rejected',
        )

    def action_receive(self):
        """Mark return items as received."""
        self.ensure_one()
        if self.state != 'approved':
            raise UserError("Only approved returns can be marked as received.")

        # Validate the return picking if it exists
        if self.picking_id and self.picking_id.state not in ('done', 'cancel'):
            self.picking_id.button_validate()

        self.state = 'received'

    def action_refund(self):
        """Create a credit note and sync refund to WooCommerce."""
        self.ensure_one()
        if self.state not in ('received', 'approved'):
            raise UserError("Return must be received or approved before refunding.")

        invoice = self.order_id.invoice_id
        if not invoice:
            raise UserError("No invoice found for this WC order.")

        # Create credit note (reversal)
        reversal_wizard = self.env['account.move.reversal'].with_context(
            active_model='account.move',
            active_ids=[invoice.id],
        ).create({
            'reason': self.reason or 'WooCommerce Return',
            'journal_id': invoice.journal_id.id,
        })
        reversal_result = reversal_wizard.reverse_moves()

        credit_note = False
        if reversal_result and reversal_result.get('res_id'):
            credit_note = self.env['account.move'].browse(reversal_result['res_id'])
        elif reversal_result and reversal_result.get('domain'):
            credit_note = self.env['account.move'].search(
                reversal_result['domain'], limit=1,
            )

        if credit_note:
            credit_note.action_post()

        # Sync refund to WC
        try:
            client = self.instance_id._get_client()
            # Calculate refund amount from return lines
            refund_amount = sum(
                line.quantity * line.product_id.list_price
                for line in self.line_ids
            )
            refund_data = {
                'amount': str(refund_amount),
                'reason': self.reason or 'Return/Refund',
            }
            # Create WC refund
            client.post(
                f'orders/{self.order_id.woo_order_id}/refunds',
                refund_data,
            )
            client.update_order(self.order_id.woo_order_id, {
                'meta_data': [
                    {'key': '_return_status', 'value': 'refunded'},
                ]
            })
        except Exception as e:
            _logger.error("Failed to sync refund to WC: %s", e)

        self.state = 'refunded'
        self.instance_id._log_sync(
            'order', 'odoo_to_woo', self.order_id.sale_order_id.name,
            'success', f'Refund processed',
        )


class WooReturnLine(models.Model):
    _name = 'woo.return.line'
    _description = 'WooCommerce Return Line'

    return_id = fields.Many2one('woo.return', required=True, ondelete='cascade')
    product_id = fields.Many2one('product.product', required=True)
    quantity = fields.Float(default=1.0)
    reason = fields.Selection([
        ('defective', 'Defective'),
        ('wrong_item', 'Wrong Item'),
        ('not_needed', 'Not Needed'),
        ('damaged', 'Damaged'),
        ('other', 'Other'),
    ])
    company_id = fields.Many2one(
        'res.company', default=lambda self: self.env.company,
    )
