"""Zimbra calendar operations."""

import time

from .api import soap

MAIL_NS = "urn:zimbraMail"


def events(start=None, end=None, folder_id="10", limit=50):
    """Get calendar events in a date range.

    Args:
        start: Start time in ms since epoch. Defaults to start of today.
        end: End time in ms since epoch. Defaults to 30 days from start.
        folder_id: Calendar folder ID (default "10" = Calendar).
        limit: Max events to return.
    """
    now = time.time()
    if start is None:
        # Start of today
        import datetime
        today = datetime.date.today()
        start = int(datetime.datetime.combine(today, datetime.time.min).timestamp() * 1000)
    if end is None:
        end = start + (30 * 24 * 60 * 60 * 1000)  # 30 days

    result = soap(MAIL_NS, "SearchRequest", {
        "query": f"inid:\"{folder_id}\"",
        "types": "appointment",
        "sortBy": "dateAsc",
        "limit": limit,
        "calExpandInstStart": start,
        "calExpandInstEnd": end,
    })
    resp = result.get("SearchResponse", {})
    appts = resp.get("appt", [])

    output = []
    for appt in appts:
        instances = appt.get("inst", [{}])
        organizer = appt.get("or", {})
        for inst in instances:
            output.append({
                "id": appt.get("id"),
                "name": appt.get("name", ""),
                "location": appt.get("loc", ""),
                "start": inst.get("s"),
                "duration": appt.get("dur"),
                "all_day": appt.get("allDay", False),
                "status": appt.get("status", ""),
                "organizer": organizer.get("a", ""),
                "folder": appt.get("l"),
                "fragment": appt.get("fr", ""),
            })
    return output


def event_details(event_id):
    """Get full details of a calendar event."""
    result = soap(MAIL_NS, "GetMsgRequest", {
        "m": {"id": str(event_id), "html": 0},
    })
    m = result.get("GetMsgResponse", {}).get("m", [{}])[0]

    inv = (m.get("inv", [{}])[0]).get("comp", [{}])[0] if m.get("inv") else {}

    attendees = []
    for at in inv.get("at", []):
        attendees.append({
            "name": at.get("d", ""),
            "email": at.get("a", ""),
            "role": at.get("role", ""),
            "status": at.get("ptst", ""),
        })

    start = inv.get("s", [{}])[0] if inv.get("s") else {}
    end_time = inv.get("e", [{}])[0] if inv.get("e") else {}

    return {
        "id": m.get("id"),
        "subject": inv.get("name", ""),
        "location": inv.get("loc", ""),
        "start": start.get("d", ""),
        "end": end_time.get("d", ""),
        "all_day": inv.get("allDay", False),
        "status": inv.get("status", ""),
        "organizer": inv.get("or", {}).get("a", ""),
        "attendees": attendees,
        "description": inv.get("descHtml", inv.get("desc", "")),
        "recurrence": bool(inv.get("recur")),
        "alarm": bool(inv.get("alarm")),
    }


def create_event(subject, start, end, location="", description="",
                 attendees=None, all_day=False, folder_id="10"):
    """Create a calendar event.

    Args:
        subject: Event title.
        start: Start datetime string (YYYYMMDD or YYYYMMDDTHHmmss).
        end: End datetime string.
        location: Event location.
        description: Event description.
        attendees: List of email addresses.
        all_day: Whether this is an all-day event.
        folder_id: Calendar folder ID.
    """
    comp = {
        "name": subject,
        "loc": location,
        "status": "CONF",
        "s": [{"d": start}],
        "e": [{"d": end}],
    }

    if all_day:
        comp["allDay"] = "1"

    if description:
        comp["desc"] = {"_content": description}

    if attendees:
        comp["at"] = [{"a": addr, "role": "REQ", "ptst": "NE", "rsvp": "1"}
                       for addr in attendees]

    msg = {
        "l": folder_id,
        "inv": {"comp": [comp]},
        "su": {"_content": subject},
        "mp": {"ct": "text/plain", "content": {"_content": description}},
    }

    if attendees:
        msg["e"] = [{"t": "t", "a": addr} for addr in attendees]

    result = soap(MAIL_NS, "CreateAppointmentRequest", {"m": msg})
    resp = result.get("CreateAppointmentResponse", {})
    return {"success": True, "id": resp.get("calItemId", ""), "inv_id": resp.get("invId", "")}


def update_event(event_id, inv_id="0", subject=None, start=None, end=None,
                 location=None, description=None, attendees=None):
    """Update an existing calendar event."""
    # Fetch current event
    current = event_details(event_id)

    comp = {
        "name": subject if subject is not None else current["subject"],
        "loc": location if location is not None else current["location"],
        "status": "CONF",
        "s": [{"d": start}] if start else [{"d": current["start"]}],
        "e": [{"d": end}] if end else [{"d": current["end"]}],
    }

    desc = description if description is not None else current["description"]
    if desc:
        comp["desc"] = {"_content": desc}

    if attendees is not None:
        comp["at"] = [{"a": addr, "role": "REQ", "ptst": "NE", "rsvp": "1"}
                       for addr in attendees]

    msg = {
        "inv": {"comp": [comp]},
        "su": {"_content": comp["name"]},
        "mp": {"ct": "text/plain", "content": {"_content": desc or ""}},
    }

    result = soap(MAIL_NS, "ModifyAppointmentRequest", {
        "id": str(event_id),
        "comp": "0",
        "m": msg,
    })
    return {"success": True, "id": event_id}


def delete_event(event_id):
    """Delete a calendar event."""
    soap(MAIL_NS, "ItemActionRequest", {
        "action": {"id": str(event_id), "op": "trash"},
    })
    return {"success": True, "id": event_id}
