import subprocess
import re
import tempfile


class SMSError(Exception): pass
class SMSCreateError(SMSError): pass
class SMSSendError(SMSError): pass
class SMSDeleteError(SMSError): pass


class SMS:
    def __init__(self, phonenum, msg):
        self.phonenum = phonenum
        
        with tempfile.NamedTemporaryFile(delete=False) as t:
            t.write(bytes(msg, encoding='utf-8'))
            self.msg_file=t.name

        self.sms_id = self._create()


    def _view(self):
        try:
            p = subprocess.run(['mmcli', '-m', 'any', '-s', self.sms_id],
                capture_output=True, text=True, check=True)
        except subprocess.CalledProcessError as e:
            raise SMSCreateError(f'view failed: {e.stderr}') from e

        print(p.stdout)


    def _list(self):
        try:
            p = subprocess.run(['mmcli', '-m', 'any', '--messaging-list-sms'],
                capture_output=True, text=True, check=True)
        except subprocess.CalledProcessError as e:
            raise SMSCreateError(f'list failed: {e.stderr}') from e

        return print(p.stdout)


    def _create(self):
        try:
            p = subprocess.run(['mmcli', '-m', 'any', 
                '--messaging-create-sms', f"number='{self.phonenum}'", 
                        f'--messaging-create-sms-with-text={self.msg_file}'],
                        capture_output=True, text=True, check=True)
        except subprocess.CalledProcessError as e:
            raise SMSCreateError(f'create failed: {e.stderr}') from e

        matches = re.findall(r'([0-9]+)$', p.stdout)
        if not matches:
            raise SMSCreateError('failed to parse sms id from mmcli output')
        return matches[0]


    def _delete(self):
        if not self.sms_id:
            raise SMSDeleteError('no sms id to delete')

        try:
            subprocess.run(
                ['mmcli', '-m', 'any', '--messaging-delete-sms', self.sms_id], 
                capture_output=True, text=True, check=True)
        except subprocess.CalledProcessError as e:
                raise SMSDeleteError(f'delete failed: {e.stderr}') from e

    
    def send(self):
        if not self.sms_id:
            raise SMSSendError('no sms id; cannot send')

        try:
            subprocess.run(['mmcli', '-s', self.sms_id, '--send'], 
                             capture_output=True, text=True, check=True)
            return True
        except subprocess.CalledProcessError as e:
            raise SMSSendError(f'send failed: {e.stderr}') from e
        finally:
            self._delete()
