import base64

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


def _outlook_send_email(to: str, subject: str, body: str, cc: str = "", attachments: str = "") -> str:
    if not OUTLOOK_SUPPORT:
        return "Outlook not available: pywin32 not installed."
    if not to or not to.strip() or "@" not in to:
        return (
            "ERROR: Invalid or missing recipient address. "
            "A valid email address (e.g. user@example.com) is required. "
            "If you only have a name, use outlook_get_inbox or outlook_search_emails to find the address first."
        )
    try:
        with _outlook_session() as (outlook, _):
            mail = outlook.CreateItem(0)
            mail.To = to
            if cc:
                mail.CC = cc
            mail.Subject = subject
            mail.Body = _normalize_email_body_text(body)
            if attachments:
                for raw_path in attachments.split(","):
                    fpath = _resolve_attachment_path(raw_path.strip())
                    if fpath:
                        mail.Attachments.Add(str(fpath))
            mail.Send()
        return f"Email sent to {to} — Subject: {subject}"
    except Exception as e:
        return f"Outlook send error: {e}"


def _outlook_reply_email(message_id: str, body: 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."
    if not body or not str(body).strip():
        return "ERROR: reply body is required."
    try:
        with _outlook_session() as (_, ns):
            item = _outlook_get_mail_item(ns, message_id)
            if item is None:
                return f"Outlook reply error: email not found for ID '{message_id}'."
            reply = item.Reply()
            reply.Body = _normalize_email_body_text(body, strip=True)
            reply.Send()
        return "Reply sent successfully."
    except Exception as e:
        return f"Outlook reply error: {e}"


def _outlook_save_draft_email(message_id: str, body: 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."
    if not body or not str(body).strip():
        return "ERROR: draft body is required."
    try:
        with _outlook_session() as (_, ns):
            original = _outlook_get_mail_item(ns, message_id)
            if original is None:
                return f"Outlook draft error: email not found for ID '{message_id}'."
            reply = original.Reply()
            reply.Body = _normalize_email_body_text(body, strip=True)
            reply.Save()
        return "Draft saved successfully."
    except Exception as e:
        return f"Outlook draft save error: {e}"


def _gmail_reply_email(message_id: str, body: 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."
    if not body or not str(body).strip():
        return "ERROR: reply body is required."
    service = _google_service("gmail", "v1")
    if not service:
        return "Google not authorized."
    try:
        import email.mime.text

        original = service.users().messages().get(
            userId="me",
            id=str(message_id).strip(),
            format="metadata",
            metadataHeaders=["From", "To", "Subject", "Message-ID", "References"],
        ).execute()
        headers = _gmail_message_headers(original)
        thread_id = original.get("threadId", "")
        reply_to = _normalize_email_header_value(headers.get("From", ""))
        subject = _normalize_email_header_value(headers.get("Subject", ""))
        if subject and not subject.lower().startswith("re:"):
            subject = "Re: " + subject
        orig_msg_id = _normalize_email_header_value(headers.get("Message-Id") or headers.get("Message-ID", ""))
        mime_msg = email.mime.text.MIMEText(_normalize_email_body_text(body, strip=True))
        mime_msg["to"] = reply_to
        mime_msg["subject"] = subject
        if orig_msg_id:
            mime_msg["In-Reply-To"] = orig_msg_id
            mime_msg["References"] = orig_msg_id
        raw = _gmail_message_raw_bytes(mime_msg)
        service.users().messages().send(
            userId="me",
            body={"raw": raw, "threadId": thread_id},
        ).execute()
        return "Reply sent successfully."
    except Exception as e:
        return f"Gmail reply error: {e}"


def _gmail_save_draft_email(message_id: str, body: 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."
    if not body or not str(body).strip():
        return "ERROR: draft body is required."
    service = _google_service("gmail", "v1")
    if not service:
        return "Google not authorized."
    try:
        import email.mime.text

        original = service.users().messages().get(
            userId="me",
            id=str(message_id).strip(),
            format="metadata",
            metadataHeaders=["From", "To", "Subject", "Message-ID"],
        ).execute()
        headers = _gmail_message_headers(original)
        thread_id = original.get("threadId", "")
        reply_to = _normalize_email_header_value(headers.get("From", ""))
        subject = _normalize_email_header_value(headers.get("Subject", ""))
        if subject and not subject.lower().startswith("re:"):
            subject = "Re: " + subject
        orig_msg_id = _normalize_email_header_value(headers.get("Message-Id") or headers.get("Message-ID", ""))
        mime_msg = email.mime.text.MIMEText(_normalize_email_body_text(body, strip=True))
        mime_msg["to"] = reply_to
        mime_msg["subject"] = subject
        if orig_msg_id:
            mime_msg["In-Reply-To"] = orig_msg_id
        raw = _gmail_message_raw_bytes(mime_msg)
        service.users().drafts().create(
            userId="me",
            body={"message": {"raw": raw, "threadId": thread_id}},
        ).execute()
        return "Draft saved successfully."
    except Exception as e:
        return f"Gmail draft save error: {e}"


def _gmail_send_email(to: str, subject: str, body: str, cc: str = "", attachments: str = "") -> str:
    if not GOOGLE_API_SUPPORT:
        return "Google API libraries not installed."
    if not to or not to.strip() or "@" not in to:
        return (
            "ERROR: Invalid or missing recipient address. "
            "A valid email address (e.g. user@example.com) is required. "
            "If you only have a name, use gmail_search_emails or gmail_get_inbox to find the address first."
        )
    service = _google_service("gmail", "v1")
    if not service:
        return "Google not authorized. Ask the user to click 'Authorize Google' in Settings → Integrations."
    try:
        import email.mime.base
        import email.mime.multipart
        import email.mime.text
        import mimetypes

        normalized_to = _normalize_email_header_value(to)
        normalized_subject = _normalize_email_header_value(subject)
        normalized_cc = _normalize_email_header_value(cc)
        normalized_body = _normalize_email_body_text(body)

        att_paths = []
        if attachments:
            for raw_path in attachments.split(","):
                fpath = _resolve_attachment_path(raw_path.strip())
                if fpath:
                    att_paths.append(fpath)

        if att_paths:
            mime_msg = email.mime.multipart.MIMEMultipart()
            mime_msg.attach(email.mime.text.MIMEText(normalized_body))
            for fpath in att_paths:
                ctype = mimetypes.guess_type(str(fpath))[0] or "application/octet-stream"
                maintype, subtype = ctype.split("/", 1)
                with open(fpath, "rb") as f:
                    att = email.mime.base.MIMEBase(maintype, subtype)
                    att.set_payload(f.read())
                import email.encoders

                email.encoders.encode_base64(att)
                att.add_header("Content-Disposition", "attachment", filename=fpath.name)
                mime_msg.attach(att)
        else:
            mime_msg = email.mime.text.MIMEText(normalized_body)

        mime_msg["to"] = normalized_to
        mime_msg["subject"] = normalized_subject
        if normalized_cc:
            mime_msg["cc"] = normalized_cc
        raw = _gmail_message_raw_bytes(mime_msg)
        sent = service.users().messages().send(
            userId="me", body={"raw": raw}
        ).execute()
        return f"Email sent successfully (Message ID: {sent.get('id', '?')})."
    except Exception as e:
        return f"Gmail send error: {e}"