# -*- coding: utf-8 -*-
import logging
from odoo import models, fields, api, exceptions, _
from odoo.exceptions import UserError
import urllib.parse

_logger = logging.getLogger(__name__)

class EventRentalRequest(models.Model):
    _name = 'event.rental.request'
    _description = 'Event Rental Request'
    _inherit = ['mail.thread', 'mail.activity.mixin']
    _order = 'id desc'

    name = fields.Char(string='Request Number', required=True, copy=False, readonly=True, index=True, default=lambda self: _('New'))
    partner_id = fields.Many2one('res.partner', string='Customer', tracking=True)
    
    # Customer Details (Useful for Guest/Website checkouts)
    customer_name = fields.Char(string='Customer Name', tracking=True)
    customer_email = fields.Char(string='Email', tracking=True)
    customer_phone = fields.Char(string='Mobile Number', tracking=True)
    company_name = fields.Char(string='Company Name')
    customer_address = fields.Text(string='Address')
    
    # Event Details
    event_date = fields.Date(string='Event Date', compute='_compute_event_date', store=True)
    start_date = fields.Datetime(string='Start Date & Time', required=True, tracking=True)
    end_date = fields.Datetime(string='End Date & Time', required=True, tracking=True)
    location = fields.Text(string='Event Location', required=True)
    event_type = fields.Selection([
        ('wedding', 'Wedding'),
        ('birthday', 'Birthday'),
        ('corporate', 'Corporate Event'),
        ('stage', 'Stage Setup'),
        ('festival', 'Festival'),
        ('exhibition', 'Exhibition'),
        ('other', 'Other')
    ], string='Event Type', default='other', required=True)
    
    # Financial details
    delivery_charge = fields.Float(string='Delivery Charge', default=0.0, tracking=True)
    setup_charge = fields.Float(string='Setup Charge', default=0.0, tracking=True)
    amount_total = fields.Float(string='Total Amount', compute='_compute_amount_total', store=True)

    status = fields.Selection([
        ('draft', 'Draft'),
        ('under_review', 'Under Review'),
        ('approved', 'Approved'),
        ('rejected', 'Rejected'),
        ('quotation_sent', 'Quotation Sent'),
        ('confirmed', 'Confirmed'),
        ('delivered', 'Delivered'),
        ('returned', 'Returned'),
        ('completed', 'Completed')
    ], string='Status', default='draft', tracking=True, required=True)

    line_ids = fields.One2many('event.rental.line', 'request_id', string='Rental Lines')
    document_ids = fields.One2many('event.document', 'request_id', string='Uploaded Documents')
    
    # Sales Integration
    sale_order_id = fields.Many2one('sale.order', string='Sales Quotation', readonly=True, copy=False)
    
    # Delivery tracking
    delivery_date = fields.Datetime(string='Delivery Scheduled Date')
    delivery_staff_id = fields.Many2one('res.users', string='Delivery Staff')
    delivery_status = fields.Selection([
        ('pending', 'Pending'),
        ('delivered', 'Delivered'),
        ('picked_up', 'Picked Up'),
        ('returned', 'Returned')
    ], string='Delivery Status', default='pending', tracking=True)

    is_all_available = fields.Boolean(string='All Items Available', compute='_compute_is_all_available')

    @api.depends('start_date')
    def _compute_event_date(self):
        for rec in self:
            if rec.start_date:
                rec.event_date = rec.start_date.date()
            else:
                rec.event_date = False

    @api.depends('line_ids.price_subtotal', 'delivery_charge', 'setup_charge')
    def _compute_amount_total(self):
        for rec in self:
            lines_sum = sum(rec.line_ids.mapped('price_subtotal'))
            rec.amount_total = lines_sum + rec.delivery_charge + rec.setup_charge

    @api.depends('line_ids.is_available')
    def _compute_is_all_available(self):
        for rec in self:
            rec.is_all_available = all(line.is_available for line in rec.line_ids) if rec.line_ids else False

    @api.model_create_multi
    def create(self, vals_list):
        for vals in vals_list:
            if vals.get('name', _('New')) == _('New'):
                vals['name'] = self.env['ir.sequence'].next_by_code('event.rental.request') or _('New')
            # If partner is set, automatically pre-fill customer details if empty
            if vals.get('partner_id'):
                partner = self.env['res.partner'].browse(vals['partner_id'])
                if not vals.get('customer_name'):
                    vals['customer_name'] = partner.name
                if not vals.get('customer_email'):
                    vals['customer_email'] = partner.email
                if not vals.get('customer_phone'):
                    vals['customer_phone'] = partner.phone or partner.mobile
                if not vals.get('customer_address'):
                    vals['customer_address'] = partner.contact_address
        return super(EventRentalRequest, self).create(vals_list)

    def check_availability(self, start_date, end_date, product_id, exclude_request_id=None):
        """
        Check the available inventory of a product for the selected date range.
        Bypassed per request - returning infinite availability.
        """
        return 999999.0

    def _get_or_create_service_product(self, name, default_code):
        product = self.env['product.product'].search([('default_code', '=', default_code)], limit=1)
        if not product:
            product = self.env['product.product'].create({
                'name': name,
                'type': 'service',
                'default_code': default_code,
                'sale_ok': True,
                'purchase_ok': False,
            })
        return product

    def action_approve(self):
        """
        Approve the request. Check availability, find/create customer partner,
        create sales quotation, set status to quotation_sent, and send notification.
        """
        self.ensure_one()
        if not self.line_ids:
            raise UserError(_("Please add at least one rental product line."))

        # Re-check availability bypassed per request
        # for line in self.line_ids:
        #     available_qty = self.check_availability(self.start_date, self.end_date, line.product_id, exclude_request_id=self.id)
        #     if available_qty < line.quantity:
        #         raise UserError(_("Product '%s' is not available in the required quantity (%s) for the selected dates. Only %s units are available.") % (
        #             line.product_id.display_name, line.quantity, available_qty
        #         ))

        # Check/create partner
        partner = self.partner_id
        if not partner:
            partner = self.env['res.partner'].search([('email', '=', self.customer_email)], limit=1)
            if not partner:
                partner = self.env['res.partner'].create({
                    'name': self.customer_name or self.customer_email or _('Guest Customer'),
                    'email': self.customer_email,
                    'phone': self.customer_phone,
                    'company_name': self.company_name,
                    'street': self.customer_address,
                })
            self.partner_id = partner

        # Create Odoo Sales Order
        so_vals = {
            'partner_id': partner.id,
            'origin': self.name,
            'event_rental_request_id': self.id,
        }
        sale_order = self.env['sale.order'].create(so_vals)
        self.sale_order_id = sale_order

        # Rental product lines
        for line in self.line_ids:
            self.env['sale.order.line'].create({
                'order_id': sale_order.id,
                'product_id': line.product_id.id,
                'product_uom_qty': line.quantity,
                'price_unit': line.price_unit,
                'name': _("Rental: %s (Period: %s to %s)") % (line.product_id.display_name, self.start_date, self.end_date),
            })

        # Add Delivery charges
        if self.delivery_charge > 0:
            delivery_product = self._get_or_create_service_product("Delivery Charges", "RENTAL_DELIVERY")
            self.env['sale.order.line'].create({
                'order_id': sale_order.id,
                'product_id': delivery_product.id,
                'product_uom_qty': 1,
                'price_unit': self.delivery_charge,
                'name': _("Delivery Charges for Rental %s") % self.name,
            })

        # Add Setup charges
        if self.setup_charge > 0:
            setup_product = self._get_or_create_service_product("Setup Charges", "RENTAL_SETUP")
            self.env['sale.order.line'].create({
                'order_id': sale_order.id,
                'product_id': setup_product.id,
                'product_uom_qty': 1,
                'price_unit': self.setup_charge,
                'name': _("Setup Charges for Rental %s") % self.name,
            })

        # Set status to approved and then quotation_sent
        self.write({
            'status': 'quotation_sent',
            'delivery_status': 'pending'
        })

        # Send Email Notification
        template = self.env.ref('event_rental.email_template_rental_approved', raise_if_not_found=False)
        if template:
            template.send_mail(self.id, force_send=True)
            self.message_post(body=_("Quotation created and email notification sent to customer."))
        else:
            self.message_post(body=_("Rental Request Approved. Quotation %s generated.") % sale_order.name)

        # Log WhatsApp Notification & Generate Link
        self._log_whatsapp_notification()

    def action_reject(self):
        self.write({'status': 'rejected'})
        self.message_post(body=_("Rental Request has been Rejected."))

    def action_deliver(self):
        self.write({
            'status': 'delivered',
            'delivery_status': 'delivered',
            'delivery_date': fields.Datetime.now()
        })
        self.message_post(body=_("Products have been delivered to the event location."))

    def action_pickup(self):
        self.write({
            'status': 'returned',
            'delivery_status': 'picked_up'
        })
        self.message_post(body=_("Products have been picked up from the location."))

    def action_return(self):
        self.write({
            'status': 'returned',
            'delivery_status': 'returned'
        })
        self.message_post(body=_("Products returned and checked back in inventory."))

    def action_complete(self):
        self.write({'status': 'completed'})
        self.message_post(body=_("Rental Request completed."))

    def action_reset_draft(self):
        self.write({'status': 'draft'})
        self.message_post(body=_("Request reset to Draft."))

    def _log_whatsapp_notification(self):
        """
        Log WhatsApp message details and prepare a quick-action link for the administrator
        """
        if not self.customer_phone:
            return

        message = _("Hello %s, your rental request %s has been approved. Please review the quotation: %s") % (
            self.customer_name,
            self.name,
            self.sale_order_id.get_portal_url() if self.sale_order_id else ''
        )
        
        encoded_message = urllib.parse.quote(message)
        wa_url = f"https://web.whatsapp.com/send?phone={self.customer_phone}&text={encoded_message}"
        
        chatter_body = _(
            "<strong>WhatsApp Notification Queued:</strong><br/>"
            "Recipient Phone: %s<br/>"
            "Message: <em>\"%s\"</em><br/>"
            "<a href=\"%s\" target=\"_blank\" class=\"btn btn-sm btn-primary mt-2\">Send via WhatsApp Web</a>"
        ) % (self.customer_phone, message, wa_url)
        
        self.message_post(body=chatter_body)


class EventRentalLine(models.Model):
    _name = 'event.rental.line'
    _description = 'Event Rental Line'

    request_id = fields.Many2one('event.rental.request', string='Rental Request', ondelete='cascade', required=True)
    product_id = fields.Many2one('product.product', string='Product', domain=[('is_rental', '=', True)], required=True)
    quantity = fields.Float(string='Quantity Required', default=1.0, required=True)
    price_unit = fields.Float(string='Rental Price Unit', compute='_compute_price_unit', readonly=False, store=True)
    price_subtotal = fields.Float(string='Subtotal', compute='_compute_price_subtotal', store=True)
    is_available = fields.Boolean(string='Available', compute='_compute_is_available')

    @api.depends('product_id', 'request_id.start_date', 'request_id.end_date')
    def _compute_price_unit(self):
        for line in self:
            if line.product_id:
                duration = 1.0
                if line.request_id.start_date and line.request_id.end_date:
                    delta = line.request_id.end_date - line.request_id.start_date
                    days = delta.days
                    if delta.seconds > 0 or delta.days == 0:
                        days += 1
                    duration = max(1.0, float(days))
                line.price_unit = line.product_id.rental_price_per_day * duration
            else:
                line.price_unit = 0.0

    @api.depends('quantity', 'price_unit')
    def _compute_price_subtotal(self):
        for line in self:
            line.price_subtotal = line.quantity * line.price_unit

    @api.depends('product_id', 'quantity', 'request_id.start_date', 'request_id.end_date')
    def _compute_is_available(self):
        for line in self:
            line.is_available = True


class EventDocument(models.Model):
    _name = 'event.document'
    _description = 'Event Rental Document'

    request_id = fields.Many2one('event.rental.request', string='Rental Request', ondelete='cascade', required=True)
    partner_id = fields.Many2one('res.partner', string='Customer')
    doc_type = fields.Selection([
        ('aadhaar', 'Aadhaar Card'),
        ('driving_license', 'Driving License'),
        ('passport', 'Passport'),
        ('voter_id', 'Voter ID'),
        ('other', 'Other ID Proof')
    ], string='ID Proof Type', required=True)
    attachment_id = fields.Many2one('ir.attachment', string='Attachment File', required=True)
    verification_status = fields.Selection([
        ('pending', 'Pending Verification'),
        ('verified', 'Verified'),
        ('rejected', 'Rejected')
    ], string='Verification Status', default='pending', required=True)
