import base64

from backend.config import GOOGLE_API_SUPPORT, OUTLOOK_SUPPORT, _google_service, _outlook_session
from backend.gmail_helpers_runtime import (
    _gmail_extract_plain_text_body,
    _gmail_find_draft_by_message_id,
    _gmail_message_headers,
)
from backend.mail_helpers_runtime import (
    _gmail_message_raw_bytes,
    _normalize_email_body_text,
    _normalize_email_header_value,
    _normalize_mail_folder,
    _outlook_get_mail_item,
)


def _outlook_mail_item_folder_name(item) -> str:
    try:
        parent = getattr(item, "Parent", None)
        name = str(getattr(parent, "Name", "") or "").strip()
    except Exception:
        name = ""
    return _normalize_mail_folder(name, default=name or "Inbox")


def _outlook_mail_item_is_draft(item) -> bool:
    folder_name = _outlook_mail_item_folder_name(item)
    if folder_name == "Drafts":
        return True
    try:
        return not bool(getattr(item, "Sent", False)) and not bool(getattr(item, "ReceivedTime", None))
    except Exception:
        return False


def _outlook_delete_email(message_id: str) -> str:
    if not OUTLOOK_SUPPORT:
        return "Outlook not available: pywin32 not installed."
    if not message_id or not str(message_id).strip():
        return (
            "ERROR: message_id is required. You MUST call outlook_get_inbox or outlook_search_emails first "
            "to obtain the Message ID of the email you want to delete."
        )
    try:
        with _outlook_session() as (_, ns):
            item = _outlook_get_mail_item(ns, message_id)
            if item is None:
                return (
                    f"Outlook email delete error: Message ID '{message_id}' not found. "
                    "Call outlook_get_inbox or outlook_search_emails first to get valid Message IDs."
                )
            subject = str(getattr(item, "Subject", "") or "")
            folder_name = _outlook_mail_item_folder_name(item)
            item.Delete()
            return (
                "Email deleted successfully.\n"
                f"Folder: {folder_name or '-'}\n"
                f"Subject: {subject or '(no subject)'}\n"
                f"Message ID: {str(message_id).strip()}"
            )
    except Exception as e:
        return f"Outlook email delete error: {e}"


def _outlook_update_email(message_id: str, subject: str = "", body: str = "", to: str = "", cc: str = "") -> str:
    if not OUTLOOK_SUPPORT:
        return "Outlook not available: pywin32 not installed."
    if not message_id or not str(message_id).strip():
        return (
            "ERROR: message_id is required. You MUST call outlook_get_inbox or outlook_search_emails first "
            "to obtain the Message ID of the draft you want to update."
        )
    if not any(str(value or "").strip() for value in [subject, body, to, cc]):
        return "ERROR: provide at least one field to update (to, cc, subject, or body)."
    try:
        with _outlook_session() as (_, ns):
            item = _outlook_get_mail_item(ns, message_id)
            if item is None:
                return (
                    f"Outlook email update error: Message ID '{message_id}' not found. "
                    "Call outlook_get_inbox or outlook_search_emails first to get valid Message IDs."
                )
            if not _outlook_mail_item_is_draft(item):
                return "Outlook email update error: only draft emails can be updated. Search in Drafts first."
            if to:
                item.To = to
            if cc:
                item.CC = cc
            if subject:
                item.Subject = subject
            if body:
                item.Body = _normalize_email_body_text(body)
            item.Save()
            return (
                "Email updated successfully.\n"
                "Folder: Drafts\n"
                f"To: {str(getattr(item, 'To', '') or '').strip() or '-'}\n"
                f"Subject: {str(getattr(item, 'Subject', '') or '').strip() or '(no subject)'}\n"
                f"Message ID: {str(getattr(item, 'EntryID', '') or message_id).strip()}"
            )
    except Exception as e:
        return f"Outlook email update error: {e}"


def _gmail_delete_email(message_id: str) -> str:
    if not GOOGLE_API_SUPPORT:
        return "Google API libraries not installed."
    if not message_id or not str(message_id).strip():
        return (
            "ERROR: message_id is required. You MUST call gmail_get_inbox or gmail_search_emails first "
            "to obtain the Message ID of the email you want to delete."
        )
    service = _google_service("gmail", "v1")
    if not service:
        return "Google not authorized. Ask the user to click 'Authorize Google' in Settings → Integrations."
    try:
        msg = service.users().messages().get(
            userId="me",
            id=str(message_id).strip(),
            format="metadata",
            metadataHeaders=["From", "To", "Subject", "Date"],
        ).execute()
        headers = _gmail_message_headers(msg)
        service.users().messages().trash(userId="me", id=str(message_id).strip()).execute()
        return (
            "Email deleted successfully.\n"
            "Folder: Deleted\n"
            f"Subject: {headers.get('Subject', '(no subject)')}\n"
            f"Message ID: {str(message_id).strip()}"
        )
    except Exception as e:
        return f"Gmail email delete error: {e}"


def _gmail_update_email(message_id: str, subject: str = "", body: str = "", to: str = "", cc: str = "") -> str:
    if not GOOGLE_API_SUPPORT:
        return "Google API libraries not installed."
    if not message_id or not str(message_id).strip():
        return (
            "ERROR: message_id is required. You MUST call gmail_get_inbox or gmail_search_emails first "
            "to obtain the Message ID of the draft you want to update."
        )
    if not any(str(value or "").strip() for value in [subject, body, to, cc]):
        return "ERROR: provide at least one field to update (to, cc, subject, or body)."
    service = _google_service("gmail", "v1")
    if not service:
        return "Google not authorized. Ask the user to click 'Authorize Google' in Settings → Integrations."
    try:
        draft = _gmail_find_draft_by_message_id(service, message_id)
        if not draft:
            return "Gmail email update error: only draft emails can be updated. Search in Drafts first."
        message = draft.get("message") or {}
        headers = _gmail_message_headers(message)
        current_payload = message.get("payload") or {}
        final_to = _normalize_email_header_value(to or headers.get("To") or "")
        final_cc = _normalize_email_header_value(cc or headers.get("Cc") or "")
        final_subject = _normalize_email_header_value(subject or headers.get("Subject") or "")
        final_body = _normalize_email_body_text(body or _gmail_extract_plain_text_body(current_payload) or "", strip=True)

        import email.mime.text

        mime_msg = email.mime.text.MIMEText(final_body)
        if final_to:
            mime_msg["to"] = final_to
        if final_subject:
            mime_msg["subject"] = final_subject
        if final_cc:
            mime_msg["cc"] = final_cc
        raw = _gmail_message_raw_bytes(mime_msg)
        updated = service.users().drafts().update(
            userId="me",
            id=draft.get("id", ""),
            body={
                "message": {
                    "raw": raw,
                    "threadId": message.get("threadId", ""),
                }
            },
        ).execute()
        updated_message = updated.get("message") or {}
        return (
            "Email updated successfully.\n"
            "Folder: Drafts\n"
            f"To: {final_to or '-'}\n"
            f"Subject: {final_subject or '(no subject)'}\n"
            f"Message ID: {str(updated_message.get('id') or message_id).strip()}"
        )
    except Exception as e:
        return f"Gmail email update error: {e}"