# ics.py
#
# Copyright 2020-2025 Fabio Comuni, et al.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import time
import html
from datetime import datetime, timedelta
from dateutil.tz import UTC
from icalendar import Calendar  # type: ignore

from .. import local
from ..models import Meta
from ..utils import bind_list


def import_ics(content: str, url: str):
    """Import data from ICS

    all dates will be converted to UTC and stored in db without tzinfo,
    because sqlite3 driver spits errors otherwise.
    """

    cal = Calendar.from_ical(content)

    _db = local.getDb()

    meta_title = None
    meta_end = datetime(1970, 1, 1, 0, 0, 0)
    meta_start = datetime(3100, 12, 12, 23, 59, 59)

    found_event_ids = []

    for c in cal.walk():
        if c.name == "VCALENDAR":
            meta_title = c.get('X-WR-CALNAME')

        if c.name == "VEVENT":
            fulltextsearch = []
            eventid = c['UID']
            found_event_ids.append(eventid)
            if c.get('DTSTART'):
                start = c['DTSTART'].dt.astimezone(UTC).replace(tzinfo=None)
            else:
                start = c['DTSTAMP'].dt.astimezone(UTC).replace(tzinfo=None)
            if c.get('DURATION'):
                end = start + c['DURATION'].dt
            elif c.get('DTEND'):
                end = c['DTEND'].dt.astimezone(UTC).replace(tzinfo=None)
            else:
                end = start + timedelta(hours=1)
            evtdate = start.date()
            room = c.get('LOCATION')
            slug = None
            title = c.get('SUMMARY', "")
            subtitle = None
            track = None
            evtype = None
            abstract = None
            description = c.get('DESCRIPTION', "")

            if title == "" and description == "":
                title = "Untitled event"
            if title == "" and description != "":
                title = description[:20]
                if len(description) > 20:
                    title = title + "…"

            if room:
                room = html.unescape(room)
            if room == "":
                room = None

            if start < meta_start:
                meta_start = start
            if end > meta_end:
                meta_end = end

            fulltextsearch += [s for s in [title, subtitle, abstract, description, room, track] if s is not None]

            links = []
            _url = c.get('URL')
            if _url:
                links.append((eventid, _url, _url))

            _db.execute("""INSERT OR REPLACE INTO events
                           (id, date, start, end, room, slug, title, subtitle, track, type, abstract, description, starred)
                           VALUES (?,?,?,?,?,?,?,?,?,?,?,?, (SELECT starred FROM events WHERE id=?))""",
                        (eventid, evtdate, start, end, room, slug, title, subtitle, track, evtype, abstract, description, eventid))
            # _db.executemany("INSERT OR REPLACE INTO persons (id, name) VALUES (?, ?)", persons)
            # _db.executemany("""INSERT OR REPLACE INTO event_person (event_id, person_id)
            #                    VALUES (?, ?) ON CONFLICT DO NOTHING""",
            #                 [ (eventid, p[0]) for p in persons ])
            _db.executemany("""INSERT OR REPLACE INTO links
                                (event_id, href, name) VALUES (?,?,?)""", links)
            fulltextsearchstr = ' '.join(fulltextsearch)
            _db.execute("""INSERT OR REPLACE INTO fts_event (event_id, text) VALUES (?, ?)""", (eventid, fulltextsearchstr))

    _db.execute(f"""DELETE FROM events WHERE id NOT IN ({bind_list(found_event_ids)})""", found_event_ids)
    _db.execute(f"""DELETE FROM fts_event WHERE event_id NOT IN ({bind_list(found_event_ids)})""", found_event_ids)
    _db.commit()

    with Meta() as m:
        m.url = url
        m.title = meta_title
        m.last_update = time.time()  # timestamp
        m.start = meta_start.date()
        m.end = meta_end.date()
