import logging
from datetime import timedelta

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

_logger = logging.getLogger(__name__)


class ManualRenewalWizard(models.TransientModel):
    _name = 'manual.renewal.wizard'
    _description = 'Manual Rental Renewal Wizard'

    order_id = fields.Many2one(
        'sale.order',
        string="Rental Order",
        required=True,
        readonly=True,
    )
    partner_id = fields.Many2one(
        related='order_id.partner_id',
        string="Customer",
    )
    current_start_date = fields.Datetime(
        string="Current Start Date",
        readonly=True,
    )
    current_return_date = fields.Datetime(
        string="Current Return Date",
        readonly=True,
    )
    new_start_date = fields.Datetime(
        string="New Start Date",
        required=True,
    )
    new_return_date = fields.Datetime(
        string="New Return Date",
        required=True,
    )
    amount_preview = fields.Float(
        string="Estimated Renewal Amount",
        compute='_compute_amount_preview',
    )

    payment_token_id = fields.Many2one(
        'payment.token',
        string="Card on File",
        domain="[('partner_id', '=', partner_id)]",
        help="Select a stored card to charge automatically. "
             "Leave empty to open the manual payment wizard.",
    )
    use_card_on_file = fields.Boolean(
        string="Charge Card on File",
        default=False,
        compute='_compute_use_card_on_file',
        store=True,
        readonly=False,
    )

    previous_start_date = fields.Datetime(
        string="Previous Start (rollback)",
        readonly=True,
    )
    previous_return_date = fields.Datetime(
        string="Previous Return (rollback)",
        readonly=True,
    )
    renewal_invoice_id = fields.Many2one(
        'account.move',
        string="Renewal Invoice",
        readonly=True,
    )
    renewal_log_id = fields.Many2one(
        'rental.renewal.log',
        string="Renewal Log",
        readonly=True,
    )

    @api.depends('order_id', 'new_start_date', 'new_return_date')
    def _compute_amount_preview(self):
        for wizard in self:
            if wizard.order_id:
                wizard.amount_preview = wizard.order_id._get_renewal_amount()
            else:
                wizard.amount_preview = 0.0

    @api.depends('payment_token_id')
    def _compute_use_card_on_file(self):
        for wizard in self:
            wizard.use_card_on_file = bool(wizard.payment_token_id)

    def action_confirm_renewal(self):
        """Confirm the manual renewal: extend dates, create invoice, and collect payment."""
        self.ensure_one()
        order = self.order_id

        if not order.is_rental_order:
            raise UserError(_("This is not a rental order."))

        if self.new_return_date <= self.new_start_date:
            raise UserError(_("New return date must be after the new start date."))

        old_start = order.rental_start_date
        old_return = order.rental_return_date

        self.write({
            'previous_start_date': old_start,
            'previous_return_date': old_return,
        })

        order.write({
            'rental_start_date': self.new_start_date,
            'rental_return_date': self.new_return_date,
        })
        order._recompute_rental_prices()

        invoice = order._create_renewal_invoice()
        if not invoice:
            raise UserError(_("Could not create renewal invoice."))

        renewal_log = self.env['rental.renewal.log'].create({
            'order_id': order.id,
            'renewal_number': order.rental_renewal_count + 1,
            'previous_start_date': old_start,
            'previous_return_date': old_return,
            'new_start_date': self.new_start_date,
            'new_return_date': self.new_return_date,
            'invoice_id': invoice.id,
            'renewal_type': 'manual',
            'state': 'draft',
            'payment_status': 'pending',
        })

        self.write({
            'renewal_invoice_id': invoice.id,
            'renewal_log_id': renewal_log.id,
        })

        order.write({
            'rental_renewal_count': order.rental_renewal_count + 1,
            'rental_reminder_sent': False,
        })

        if self.use_card_on_file and self.payment_token_id:
            invoice.action_post()
            ok = order._collect_token_payment_for_invoice(invoice)
            if ok:
                renewal_log.write({
                    'state': 'done',
                    'payment_status': 'paid',
                })
                order._send_renewal_confirmation_email(renewal_log, True)
                return {'type': 'ir.actions.act_window_close'}
            else:
                renewal_log.write({
                    'state': 'done',
                    'payment_status': 'failed',
                })
                order._send_renewal_confirmation_email(renewal_log, False)
                order._notify_staff_manual_payment(invoice)
                return {'type': 'ir.actions.act_window_close'}

        invoice.action_post()
        renewal_log.write({'state': 'done'})
        order._send_renewal_confirmation_email(renewal_log, False)

        inv = invoice.with_user(self.env.user)
        return inv.action_open_poynt_payment_wizard()

    def action_cancel_renewal(self):
        """Cancel the renewal: revert dates and void the invoice."""
        self.ensure_one()
        order = self.order_id

        if self.renewal_invoice_id:
            inv = self.renewal_invoice_id
            if inv.state == 'posted' and inv.payment_state in ('not_paid', 'partial'):
                inv.button_draft()
            if inv.state == 'draft':
                inv.button_cancel()

        if self.previous_start_date and self.previous_return_date:
            order.write({
                'rental_start_date': self.previous_start_date,
                'rental_return_date': self.previous_return_date,
            })
            order._recompute_rental_prices()

        if self.renewal_log_id:
            self.renewal_log_id.write({
                'state': 'failed',
                'payment_status': 'failed',
                'notes': 'Cancelled by user.',
            })

        if order.rental_renewal_count > 0:
            order.rental_renewal_count -= 1

        order.message_post(body=_("Manual renewal cancelled and reverted."))
        return {'type': 'ir.actions.act_window_close'}
