"""Backend for SyncTech Backup & Restore.

[SyncTech Backup & Restore](https://www.synctech.com.au/sms-backup-restore/)
for Android is a free app for backing up your SMS and MMS messages. It uses an
XML format as backup format, which this backend reads and converts to the
standardized Message format.
"""

import datetime
import logging
from collections.abc import Iterator
from pathlib import Path

import bs4

from .data import MYSELF, Message

logger = logging.getLogger(__name__)


def is_named_number(num: str) -> str:
    try:
        int(num.removeprefix('+').replace(' ', ''))
        return False
    except ValueError:
        return True


def normalize_phone_number(num: str) -> str:
    if is_named_number(num):
        return num

    num = num.replace(' ', '')
    if num.startswith('00'):
        num = '+' + num.removeprefix('00')
    if len(num) == 8:
        num = '+45' + num
    elif len(num) >= 10 and num[0] != '+':
        num = '+' + num
    return num


def sms_soup_to_message(soup: bs4.BeautifulSoup) -> Message:
    # TODO: Require myself
    sent_at = datetime.datetime.fromtimestamp(int(soup['date']) / 1000)

    phone_num = normalize_phone_number(soup['address'])

    if is_named_number(phone_num):
        contact_name = phone_num
        phone_num = None
    else:
        contact_name = soup.get('contact_name') or phone_num
    if contact_name == '(Unknown)':
        contact_name = None

    if soup['type'] == '2':
        sender = MYSELF
    else:
        sender = contact_name or phone_num

    text = soup['body']

    chat_id_parts = ['SMS', contact_name or phone_num]
    chat_id = ' '.join(p for p in chat_id_parts if p)
    return Message(sent_at, sender, text, chat_id=chat_id)


def select_newest_file_in_dir(path: Path) -> Path:
    return max(
        (p for p in path.iterdir() if p.suffix == '.xml' and 'sms' in p.name),
        key=lambda p: p.stat().st_atime_ns,
    )


def parse_messages_in_backup_xml_file(path: Path) -> Iterator[Message]:
    if path.is_dir():
        logger.info('%s is a dir. Finding newest backup in directory', path)
        path = select_newest_file_in_dir(path)
        logger.info('Found: %s', path)

    logger.info('Parsing %s', path)

    with open(path) as f:
        soup = bs4.BeautifulSoup(f, 'lxml-xml')

    for sms in soup.find_all('sms'):
        yield sms_soup_to_message(sms)
        del sms