"""Google Sheets sync client.

Appends emails to spreadsheets after a successful Mailchimp import. Each
spreadsheet is mapped to one or more tags via the sheet_mappings table.

Auth: a Google Cloud service account JSON key, mounted into the container at
the path given by GOOGLE_SHEETS_CREDENTIALS_PATH (default /app/secrets/google-sheets.json).
If the file is missing or not valid JSON (e.g. still the placeholder), sync is
silently disabled — the Mailchimp import still succeeds and the run record
notes that sheets are not configured.
"""

import json
import logging
import os
from pathlib import Path

logger = logging.getLogger(__name__)

CREDENTIALS_PATH = os.environ.get(
    "GOOGLE_SHEETS_CREDENTIALS_PATH", "/app/secrets/google-sheets.json"
)
SCOPES = ["https://www.googleapis.com/auth/spreadsheets"]


def _load_client():
    """Return an authorized gspread client, or None if credentials aren't configured.

    Imports are local so the app can boot even if google libs fail to install.
    """
    path = Path(CREDENTIALS_PATH)
    if not path.exists():
        return None

    try:
        with open(path, "r") as f:
            content = f.read().strip()
    except Exception as e:
        logger.warning(f"Could not read credentials file: {e}")
        return None

    # Reject the placeholder
    if not content or not content.startswith("{"):
        return None

    try:
        from google.oauth2.service_account import Credentials
        import gspread
    except ImportError as e:
        logger.warning(f"gspread/google-auth not installed: {e}")
        return None

    try:
        info = json.loads(content)
        creds = Credentials.from_service_account_info(info, scopes=SCOPES)
        return gspread.authorize(creds)
    except Exception as e:
        logger.warning(f"Could not authorize gspread client: {e}")
        return None


def is_configured():
    """True if credentials file exists and contains JSON. Cheap check for UI."""
    path = Path(CREDENTIALS_PATH)
    if not path.exists():
        return False
    try:
        with open(path) as f:
            content = f.read().strip()
        return content.startswith("{")
    except Exception:
        return False


def get_service_account_email():
    """Return the service account email from the credentials JSON, or None."""
    if not is_configured():
        return None
    try:
        with open(CREDENTIALS_PATH) as f:
            return json.load(f).get("client_email")
    except Exception:
        return None


def test_sheet_access(spreadsheet_id, worksheet_name="Sheet1"):
    """Open a sheet and return (ok, message) describing the result."""
    client = _load_client()
    if not client:
        return False, "Sheets not configured (no credentials)"
    try:
        ss = client.open_by_key(spreadsheet_id)
        ws = ss.worksheet(worksheet_name)
        return True, f"Opened '{ss.title}' / '{ws.title}'"
    except Exception as e:
        return False, str(e)


def append_emails(spreadsheet_id, emails, worksheet_name="Sheet1"):
    """Append a list of emails as new rows in the given worksheet.

    Returns dict: {"appended": int, "status": "success"|"error"|"skipped", "error": str|None}
    """
    if not emails:
        return {"appended": 0, "status": "skipped", "error": "no emails to append"}

    client = _load_client()
    if not client:
        return {"appended": 0, "status": "skipped", "error": "credentials not configured"}

    try:
        ss = client.open_by_key(spreadsheet_id)
        ws = ss.worksheet(worksheet_name)
        # Wrap each email as its own row; insert at the bottom of the data range.
        rows = [[e] for e in emails]
        ws.append_rows(rows, value_input_option="RAW")
        return {"appended": len(emails), "status": "success", "error": None}
    except Exception as e:
        logger.exception("append_emails failed")
        return {"appended": 0, "status": "error", "error": str(e)}


def sync_imported_contacts(contacts, mappings):
    """For each enabled mapping, append the emails of contacts that have the
    mapping's tag.

    contacts: list of dicts with "email" and "tags" keys (tags can be list or str).
    mappings: list of dicts from get_enabled_sheet_mappings().

    Returns: list of result dicts per mapping (suitable for storing as JSON in
    import_runs.sheet_sync_results).
    """
    results = []
    if not mappings or not contacts:
        return results

    for m in mappings:
        tag = m["tag"]
        matching = [
            c["email"]
            for c in contacts
            if tag in (c.get("tags") or [])
        ]
        if not matching:
            results.append({
                "tag": tag,
                "spreadsheet_id": m["spreadsheet_id"],
                "worksheet_name": m["worksheet_name"],
                "appended": 0,
                "status": "skipped",
                "error": "no contacts with this tag",
            })
            continue

        outcome = append_emails(m["spreadsheet_id"], matching, m["worksheet_name"])
        results.append({
            "tag": tag,
            "spreadsheet_id": m["spreadsheet_id"],
            "worksheet_name": m["worksheet_name"],
            **outcome,
        })

    return results
