#!/usr/bin/env python3
"""GET endpoint for todo data + version polling (tag/campaign model).

Query params:
  version_only=1   → {"version": N}  (cheap polling)
  events_for=<id>  → {"version": N, "events": [...]}  (lazy per-todo activity log)
  (default)        → {"version", "todos", "tag_types", "tags", "campaigns"}
"""

import cgi
import json
import sqlite3
import sys

sys.path.insert(0, '/opt/ngon/apps')
from managers.auth_manager import AuthManager

import os
DB = os.environ.get('TODO_DB', '/opt/ngon/data/todo.db')
MASTER_CONFIG = os.environ.get('MASTER_CONFIG', '/opt/ngon/config/master_config.json')

# Latitude north of this is North Dakota; south is Texas. The two states' sites
# share longitudes (~-103) but are ~18° apart in latitude, so lat is the robust split.
ND_LAT_THRESHOLD = 40.0


def get_version(conn):
    row = conn.execute("SELECT value FROM meta WHERE key='version'").fetchone()
    return int(row[0]) if row else 0


def site_regions():
    """Map site name -> 'TX'/'ND' using the centroid latitude of its config polygon.
    Sites with no coordinates (Spares, Out of Service) are omitted (no region)."""
    out = {}
    try:
        with open(MASTER_CONFIG) as f:
            cfg = json.load(f)
    except Exception:
        return out
    for name, site in (cfg.get('sites') or {}).items():
        coords = ((site.get('location') or {}).get('coordinates')) or []
        if not coords:
            continue
        lats = [p[1] for p in coords if len(p) >= 2]
        if not lats:
            continue
        clat = sum(lats) / len(lats)
        out[name] = 'ND' if clat > ND_LAT_THRESHOLD else 'TX'
    return out


def build_tag_regions(tag_types, tags):
    """tag_id -> 'TX'/'ND' for location tags. Top-level (site) tags match the site
    name; pods inherit their parent site's region."""
    loc_type_ids = {tt['id'] for tt in tag_types
                    if tt.get('name') == 'location' or tt.get('seeded_from') == 'master_config'}
    if not loc_type_ids:
        return {}
    regions = site_regions()
    out = {}
    for t in tags:
        if t['tag_type_id'] in loc_type_ids and not t['parent_id'] and t['name'] in regions:
            out[t['id']] = regions[t['name']]
    for t in tags:
        if t['tag_type_id'] in loc_type_ids and t['parent_id'] and t['parent_id'] in out:
            out[t['id']] = out[t['parent_id']]
    return out


def main():
    form = cgi.FieldStorage()
    auth = AuthManager('todo')
    auth_required, should_exit, headers = auth.require_auth(form)

    print("Content-Type: application/json")
    if headers:
        print(headers)
    print("")

    if auth_required or should_exit:
        print(json.dumps({"error": "unauthorized"}))
        return

    try:
        conn = sqlite3.connect(DB)
        conn.row_factory = sqlite3.Row
        version = get_version(conn)

        if form.getvalue('version_only'):
            print(json.dumps({"version": version}))
            conn.close()
            return

        events_for = form.getvalue('events_for')
        if events_for:
            events = [dict(r) for r in conn.execute(
                "SELECT id, todo_id, type, body, created_by, created_at "
                "FROM todo_events WHERE todo_id=? ORDER BY created_at ASC, id ASC",
                (int(events_for),))]
            conn.close()
            print(json.dumps({"version": version, "events": events}))
            return

        tag_types = [dict(r) for r in conn.execute(
            "SELECT id, name, label, color, is_hierarchical, seeded_from, position "
            "FROM tag_types ORDER BY position, id")]
        tags = [dict(r) for r in conn.execute(
            "SELECT id, tag_type_id, name, parent_id, external_key, position, archived "
            "FROM tags ORDER BY tag_type_id, position, name")]
        campaigns = [dict(r) for r in conn.execute(
            "SELECT id, name, description, due_date, status, color, "
            "created_by, created_at, completed_at FROM campaigns ORDER BY id")]

        todos = [dict(r) for r in conn.execute(
            "SELECT id, text, status, position, due_date, campaign_id, completed, "
            "created_by, created_at, completed_by, completed_at "
            "FROM items ORDER BY position ASC, id ASC")]

        # attach tag_ids + note count per todo (single pass each)
        tag_map = {}
        for r in conn.execute("SELECT todo_id, tag_id FROM todo_tags"):
            tag_map.setdefault(r['todo_id'], []).append(r['tag_id'])
        note_counts = {}
        for r in conn.execute(
                "SELECT todo_id, COUNT(*) AS n FROM todo_events WHERE type='note' GROUP BY todo_id"):
            note_counts[r['todo_id']] = r['n']
        for t in todos:
            t['tag_ids'] = tag_map.get(t['id'], [])
            t['note_count'] = note_counts.get(t['id'], 0)

        conn.close()
        print(json.dumps({
            "version": version,
            "todos": todos,
            "tag_types": tag_types,
            "tags": tags,
            "campaigns": campaigns,
            "tag_regions": build_tag_regions(tag_types, tags),
        }))
    except Exception as e:
        print(json.dumps({"error": str(e)}))


if __name__ == "__main__":
    main()
