from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
from datetime import timedelta
import pytz

class RestaurantReservation(models.Model):
    _name = 'restaurant.reservation'
    _description = 'Restaurant Table Reservation'
    _order = 'start_time desc'

    name = fields.Char(string='Reservation Reference', required=True, copy=False, readonly=True, default=lambda self: _('New'))
    customer_name = fields.Char(string='Customer Name', required=True)
    phone = fields.Char(string='Phone Number', required=True)
    email = fields.Char(string='Email', required=True)
    num_people = fields.Integer(string='Number of People', default=1)
    
    floor_id = fields.Many2one('restaurant.floor', string='Floor')
    table_id = fields.Many2one('restaurant.table', string='Primary Table')
    table_ids = fields.Many2many('restaurant.table', string='Tables')
    
    is_admin_override = fields.Boolean(string='Admin Override', default=False, help="Skip all validation and availability checks")
    override_reason = fields.Text(string='Override Reason')
    overridden_by_id = fields.Many2one('res.users', string='Overridden By', readonly=True)
    
    start_time = fields.Datetime(string='Start Time', required=True)
    end_time = fields.Datetime(string='End Time', required=True)

    whatsapp_url = fields.Char(compute='_compute_whatsapp_url')

    def _compute_whatsapp_url(self):
        for rec in self:
            if rec.phone and rec.customer_name and rec.start_time:
                msg = f"Hello {rec.customer_name}, your reservation {rec.name or ''} for {rec.start_time.strftime('%I:%M %p')} is confirmed!"
                rec.whatsapp_url = f"https://wa.me/{rec.phone}?text={msg.replace(' ', '%20')}"
            else:
                rec.whatsapp_url = False

    def action_whatsapp(self):
        self.ensure_one()
        if self.whatsapp_url:
            return {
                'type': 'ir.actions.act_url',
                'url': self.whatsapp_url,
                'target': 'new',
            }
        return False
    
    state = fields.Selection([
        ('draft', 'Draft'),
        ('confirmed', 'Confirmed'),
        ('completed', 'Completed'),
        ('cancelled', 'Cancelled')
    ], string='Status', default='draft', tracking=True)

    @api.model
    def create(self, vals):
        if vals.get('name', _('New')) == _('New'):
            vals['name'] = self.env['ir.sequence'].next_by_code('restaurant.reservation') or _('New')
        if vals.get('is_admin_override'):
            vals['overridden_by_id'] = self.env.user.id
        return super(RestaurantReservation, self).create(vals)

    def write(self, vals):
        if vals.get('is_admin_override'):
            vals['overridden_by_id'] = self.env.user.id
        return super(RestaurantReservation, self).write(vals)

    @api.constrains('is_admin_override', 'override_reason')
    def _check_override_reason(self):
        for rec in self:
            if rec.is_admin_override and not rec.override_reason:
                raise ValidationError(_("Please provide a reason for the admin override."))

    @api.constrains('table_ids', 'start_time', 'end_time', 'state', 'is_admin_override')
    def _check_overlap(self):
        for rec in self:
            if rec.is_admin_override:
                continue
            if rec.state in ['confirmed', 'completed']:
                tables = rec.table_ids or rec.table_id
                if not tables:
                    continue
                overlap = self.search([
                    ('id', '!=', rec.id),
                    ('table_ids', 'in', tables.ids),
                    ('state', '=', 'confirmed'),
                    ('start_time', '<', rec.end_time),
                    ('end_time', '>', rec.start_time),
                ])
                if overlap:
                    raise ValidationError(_('One or more tables are already reserved for the selected time slot.'))

    @api.constrains('start_time', 'end_time', 'is_admin_override')
    def _check_opening_hours(self):
        restaurant_tz = pytz.timezone('America/Toronto')
        for rec in self:
            if rec.is_admin_override:
                continue
            local_start = pytz.utc.localize(rec.start_time).astimezone(restaurant_tz)
            local_end = pytz.utc.localize(rec.end_time).astimezone(restaurant_tz)
            
            res_date = local_start.date()
            day = str(local_start.weekday()) # 0=Mon, 6=Sun
            time_start = local_start.hour + local_start.minute / 60.0
            time_end = local_end.hour + local_end.minute / 60.0
            
            # 1. Check for Holiday/Override
            holiday = self.env['reservation.holiday'].sudo().search([('date', '=', res_date)], limit=1)
            
            if holiday:
                if holiday.is_closed:
                    raise ValidationError(_("Reservations are closed on %s for %s.") % (res_date.strftime('%B %d, %Y'), holiday.name))
                
                # Check holiday override hours if specified
                if holiday.opening_time or holiday.closing_time:
                    opening = holiday.opening_time or 0.0
                    closing = holiday.closing_time or 24.0
                    if time_start < opening or time_end > closing:
                        raise ValidationError(_("Special hours for %s (%s): %s to %s.") % (
                            holiday.name,
                            res_date.strftime('%B %d'),
                            self._float_to_time_str(opening),
                            self._float_to_time_str(closing)
                        ))
                return # If holiday found and validated, skip regular schedule

            # 2. Check Regular Schedule
            schedule = self.env['reservation.schedule'].sudo().search([('day', '=', day)], limit=1)
            
            if not schedule:
                continue

            if schedule.is_closed:
                raise ValidationError(_("Reservations are closed for %s.") % dict(schedule._fields['day'].selection).get(day))

            if time_start < schedule.opening_time or time_end > schedule.closing_time:
                raise ValidationError(_("Reservations for %s must be between %s and %s.") % (
                    dict(schedule._fields['day'].selection).get(day),
                    self._float_to_time_str(schedule.opening_time),
                    self._float_to_time_str(schedule.closing_time)
                ))

            if schedule.has_break:
                if time_start < schedule.break_end_time and time_end > schedule.break_start_time:
                    raise ValidationError(_("The restaurant has a break between %s and %s on %s.") % (
                        self._float_to_time_str(schedule.break_start_time),
                        self._float_to_time_str(schedule.break_end_time),
                        dict(schedule._fields['day'].selection).get(day)
                    ))

    @api.onchange('start_time', 'table_id')
    def _onchange_start_time(self):
        if self.start_time and self.table_id:
            duration = float(self.table_id.reservation_slot_duration or 1.0)
            self.end_time = self.start_time + timedelta(hours=duration)
        elif self.start_time:
            self.end_time = self.start_time + timedelta(hours=1)

    def action_confirm(self):
        self.ensure_one()
        self.write({'state': 'confirmed'})
        self._send_confirmation_notification()
        # Auto-open WhatsApp on confirmation
        if self.whatsapp_url:
            return {
                'type': 'ir.actions.act_url',
                'url': self.whatsapp_url,
                'target': 'new',
            }

    def action_complete(self):
        self.write({'state': 'completed'})

    def action_cancel(self):
        self.write({'state': 'cancelled'})

    def _send_confirmation_notification(self):
        """ Placeholder for WhatsApp/SMS logic """
        for rec in self:
            # Logic for WhatsApp/SMS can be added here
            # e.g., self.env['sms.api']._send_sms(rec.phone, "Your table is confirmed!")
            pass

    @api.model
    def _auto_complete_reservations(self):
        """ Scheduled action to mark past reservations as completed """
        now = fields.Datetime.now()
        past_reservations = self.search([
            ('state', '=', 'confirmed'),
            ('end_time', '<', now)
        ])
        past_reservations.write({'state': 'completed'})
