from datetime import datetime, timedelta

import pytz

from odoo import fields, http
from odoo.http import request


class McsAppointmentController(http.Controller):
    def _type_or_404(self, appointment_type_id):
        appointment_type = (
            request.env["mcs.appointment.type"]
            .sudo()
            .search(
                [
                    ("id", "=", appointment_type_id),
                    ("active", "=", True),
                    ("website_published", "=", True),
                ],
                limit=1,
            )
        )
        if not appointment_type:
            return request.not_found()
        return appointment_type

    def _display_slots(self, appointment_type, day):
        tz = appointment_type._timezone()
        slots = []
        for slot in appointment_type.get_available_slots(day):
            start_utc = pytz.UTC.localize(slot["start"])
            stop_utc = pytz.UTC.localize(slot["stop"])
            slots.append(
                {
                    "start": fields.Datetime.to_string(slot["start"]),
                    "stop": fields.Datetime.to_string(slot["stop"]),
                    "label": "%s - %s"
                    % (
                        start_utc.astimezone(tz).strftime("%I:%M %p"),
                        stop_utc.astimezone(tz).strftime("%I:%M %p"),
                    ),
                }
            )
        return slots

    @http.route(["/appointments"], type="http", auth="public", website=True)
    def appointments(self, **kwargs):
        types = request.env["mcs.appointment.type"].sudo().search(
            request.env["mcs.appointment.type"]._public_domain()
        )
        return request.render(
            "mcs_appointment_booking.appointment_type_list",
            {"appointment_types": types},
        )

    @http.route(
        ["/appointments/<int:appointment_type_id>"],
        type="http",
        auth="public",
        website=True,
    )
    def appointment_type(self, appointment_type_id, date=None, **kwargs):
        appointment_type = self._type_or_404(appointment_type_id)
        if hasattr(appointment_type, "status_code"):
            return appointment_type
        today = fields.Date.context_today(request.env.user)
        selected_day = fields.Date.to_date(date) if date else today
        max_day = today + timedelta(days=appointment_type.max_schedule_days)
        if selected_day < today:
            selected_day = today
        if selected_day > max_day:
            selected_day = max_day
        day_options = [today + timedelta(days=index) for index in range(appointment_type.max_schedule_days)]
        return request.render(
            "mcs_appointment_booking.appointment_type_page",
            {
                "appointment_type": appointment_type,
                "selected_day": selected_day,
                "day_options": day_options,
                "slots": self._display_slots(appointment_type, selected_day),
            },
        )

    @http.route(
        ["/appointments/<int:appointment_type_id>/book"],
        type="http",
        auth="public",
        website=True,
        methods=["POST"],
    )
    def appointment_book(self, appointment_type_id, **post):
        appointment_type = self._type_or_404(appointment_type_id)
        if hasattr(appointment_type, "status_code"):
            return appointment_type

        start = fields.Datetime.from_string(post.get("start"))
        stop = fields.Datetime.from_string(post.get("stop"))
        booking = request.env["mcs.appointment.booking"].sudo().create(
            {
                "appointment_type_id": appointment_type.id,
                "customer_name": (post.get("customer_name") or "").strip(),
                "customer_email": (post.get("customer_email") or "").strip(),
                "customer_phone": (post.get("customer_phone") or "").strip(),
                "start": start,
                "stop": stop,
                "notes": (post.get("notes") or "").strip(),
            }
        )
        booking.action_confirm()
        return request.redirect("/appointments/confirmed/%s" % booking.access_token)

    @http.route(
        ["/appointments/confirmed/<string:token>"],
        type="http",
        auth="public",
        website=True,
    )
    def appointment_confirmed(self, token, **kwargs):
        booking = (
            request.env["mcs.appointment.booking"]
            .sudo()
            .search([("access_token", "=", token)], limit=1)
        )
        if not booking:
            return request.not_found()
        return request.render(
            "mcs_appointment_booking.appointment_confirmed",
            {"booking": booking},
        )
