"""
Gmail morning briefing integration.

Pulls relevant email highlights for the dashboard morning briefing:
  - Unread count by category
  - Important/starred messages
  - Calendar invites and meeting-related emails
  - Actionable emails (flagged, needs reply)

Uses the Gmail API via google_auth module.
"""

import logging
import base64
import re
from datetime import datetime, date, timedelta

logger = logging.getLogger("gmail-briefing")


class GmailBriefing:
    """Generate email briefing data for the dashboard."""

    def __init__(self):
        self._service = None
        self._available = None

    @property
    def service(self):
        """Lazy-load Gmail service."""
        if self._service is None:
            try:
                from google_auth import build_gmail_service
                self._service = build_gmail_service()
            except Exception as e:
                logger.warning(f"Gmail service unavailable: {e}")
                self._service = False
        return self._service if self._service is not False else None

    @property
    def available(self):
        """Check if Gmail API is available."""
        if self._available is None:
            self._available = self.service is not None
            if self._available:
                logger.info("Gmail briefing: ACTIVE")
            else:
                logger.info("Gmail briefing: INACTIVE (Google auth not configured)")
        return self._available

    def get_unread_summary(self):
        """
        Get unread email summary by category.

        Returns dict:
        {
            "total_unread": int,
            "primary": int,
            "updates": int,
            "social": int,
            "promotions": int,
        }
        """
        if not self.available:
            return None

        try:
            categories = {
                "primary": "is:unread category:primary",
                "updates": "is:unread category:updates",
                "social": "is:unread category:social",
                "promotions": "is:unread category:promotions",
            }

            counts = {}
            total = 0
            for cat, query in categories.items():
                result = self.service.users().messages().list(
                    userId="me", q=query, maxResults=1
                ).execute()
                count = result.get("resultSizeEstimate", 0)
                counts[cat] = count
                total += count

            return {
                "total_unread": total,
                **counts,
            }

        except Exception as e:
            logger.error(f"Unread summary failed: {e}")
            return None

    def get_important_emails(self, max_results=5):
        """
        Get recent important/starred unread emails.

        Returns list of dicts:
        [{"from": str, "subject": str, "snippet": str, "date": str}, ...]
        """
        if not self.available:
            return []

        try:
            # Search for important unread emails from today/yesterday
            result = self.service.users().messages().list(
                userId="me",
                q="is:unread (is:important OR is:starred) -category:promotions -category:social",
                maxResults=max_results,
            ).execute()

            messages = []
            for msg_ref in result.get("messages", []):
                try:
                    msg = self.service.users().messages().get(
                        userId="me",
                        id=msg_ref["id"],
                        format="metadata",
                        metadataHeaders=["From", "Subject", "Date"],
                    ).execute()

                    headers = {
                        h["name"]: h["value"]
                        for h in msg.get("payload", {}).get("headers", [])
                    }

                    # Clean up the "From" field
                    from_raw = headers.get("From", "Unknown")
                    from_clean = self._clean_from(from_raw)

                    messages.append({
                        "from": from_clean,
                        "subject": headers.get("Subject", "(no subject)"),
                        "snippet": msg.get("snippet", "")[:120],
                        "date": headers.get("Date", ""),
                        "id": msg_ref["id"],
                    })
                except Exception as e:
                    logger.debug(f"Failed to fetch message {msg_ref['id']}: {e}")
                    continue

            return messages

        except Exception as e:
            logger.error(f"Important emails fetch failed: {e}")
            return []

    def get_meeting_emails(self, days_ahead=1):
        """
        Get emails with calendar invites or meeting-related content.

        Returns list of meeting-related email summaries.
        """
        if not self.available:
            return []

        try:
            # Search for calendar invites and meeting-related emails
            today = date.today()
            after_date = today.strftime("%Y/%m/%d")
            before_date = (today + timedelta(days=days_ahead + 1)).strftime("%Y/%m/%d")

            result = self.service.users().messages().list(
                userId="me",
                q=f"(has:attachment filename:ics OR subject:invite OR subject:meeting) after:{after_date} before:{before_date}",
                maxResults=10,
            ).execute()

            meetings = []
            for msg_ref in result.get("messages", []):
                try:
                    msg = self.service.users().messages().get(
                        userId="me",
                        id=msg_ref["id"],
                        format="metadata",
                        metadataHeaders=["From", "Subject", "Date"],
                    ).execute()

                    headers = {
                        h["name"]: h["value"]
                        for h in msg.get("payload", {}).get("headers", [])
                    }

                    meetings.append({
                        "from": self._clean_from(headers.get("From", "")),
                        "subject": headers.get("Subject", "Meeting invite"),
                        "snippet": msg.get("snippet", "")[:100],
                    })
                except Exception:
                    continue

            return meetings

        except Exception as e:
            logger.error(f"Meeting emails fetch failed: {e}")
            return []

    def get_needs_reply(self, max_results=3):
        """
        Get emails that likely need a reply (sent directly to Bill,
        from real people, unread, in primary inbox).
        """
        if not self.available:
            return []

        try:
            result = self.service.users().messages().list(
                userId="me",
                q="is:unread category:primary to:me -from:noreply -from:no-reply -from:notifications",
                maxResults=max_results,
            ).execute()

            emails = []
            for msg_ref in result.get("messages", []):
                try:
                    msg = self.service.users().messages().get(
                        userId="me",
                        id=msg_ref["id"],
                        format="metadata",
                        metadataHeaders=["From", "Subject"],
                    ).execute()

                    headers = {
                        h["name"]: h["value"]
                        for h in msg.get("payload", {}).get("headers", [])
                    }

                    emails.append({
                        "from": self._clean_from(headers.get("From", "")),
                        "subject": headers.get("Subject", "(no subject)"),
                        "snippet": msg.get("snippet", "")[:100],
                    })
                except Exception:
                    continue

            return emails

        except Exception as e:
            logger.error(f"Needs-reply fetch failed: {e}")
            return []

    def generate_briefing(self):
        """
        Generate a complete email briefing for the morning card.

        Returns dict:
        {
            "available": bool,
            "unread": {...},
            "important": [...],
            "needs_reply": [...],
            "meetings": [...],
            "summary_text": str,
        }
        """
        if not self.available:
            return {"available": False}

        try:
            unread = self.get_unread_summary()
            important = self.get_important_emails(5)
            needs_reply = self.get_needs_reply(3)
            meetings = self.get_meeting_emails(1)

            # Build a concise summary text for WhatsApp
            lines = []
            if unread:
                total = unread["total_unread"]
                primary = unread["primary"]
                lines.append(f"Inbox: {total} unread ({primary} primary)")

            if needs_reply:
                lines.append(f"Needs reply ({len(needs_reply)}):")
                for e in needs_reply:
                    lines.append(f"  — {e['from']}: {e['subject'][:50]}")

            if important and not needs_reply:
                lines.append(f"Important ({len(important)}):")
                for e in important[:3]:
                    lines.append(f"  — {e['from']}: {e['subject'][:50]}")

            if meetings:
                lines.append(f"Meeting invites: {len(meetings)}")

            return {
                "available": True,
                "unread": unread,
                "important": important,
                "needs_reply": needs_reply,
                "meetings": meetings,
                "summary_text": "\n".join(lines) if lines else "Inbox clear!",
                "generated": datetime.now().isoformat(),
            }

        except Exception as e:
            logger.error(f"Briefing generation failed: {e}")
            return {"available": False, "error": str(e)}

    @staticmethod
    def _clean_from(from_raw):
        """Extract clean name from email From header."""
        # "Bill Syrros <syrros@gmail.com>" → "Bill Syrros"
        match = re.match(r'^"?([^"<]+)"?\s*<', from_raw)
        if match:
            return match.group(1).strip()
        # Just an email address
        match = re.match(r'<(.+)>', from_raw)
        if match:
            return match.group(1)
        return from_raw.strip()


# Module-level singleton
_briefing = None


def get_gmail_briefing():
    """Get the singleton GmailBriefing instance."""
    global _briefing
    if _briefing is None:
        _briefing = GmailBriefing()
    return _briefing
