import re


def parse_error(msg):
    """ Parses MS SQL Server error messages into a dictionary.

    The message information is returned as a dictionary with keys:
        - SQLSTATE
        - DRIVER
        - DESCRIPTION = The detailed error description.
        - CODE = The SQL Server error code
        - CMD
        - SOLUTION = Possible solutions to prevent the error.
        - MSG = All error information in a single, multi-line string.
        - SHORT = Short description (one-liner)

    See URL below for SQL Server error codes:
        https://technet.microsoft.com/en-us/library/cc645603(v=sql.105).aspx

    Args:
        msg = String error message returned by DB-API (e.g. pyodbc).
    """
    regex = (
        r'\[(?P<SQLSTATE>.*?)\] (?P<DRIVER>\[.*\])(?P<DESC>.*?) '
        r'\((?P<CODE>[0-9]+?)\) \((?P<CMD>.+?)\)'
    )
    m = re.match(regex, msg)
    if m:
        info = {
            'SQLSTATE': m.group('SQLSTATE'),
            'DRIVER': m.group('DRIVER').strip(),
            'DESCRIPTION': m.group('DESC').strip(),
            'CODE': int(m.group('CODE')),
            'CMD': m.group('CMD'),
            'SOLUTION': None,
        }
        info['SHORT'] = (
            'SQL Server failed with error {}.'.format(info['CODE'])
        )

        # Add potential solutions to the info dict, if we have any.
        if info['CODE'] in (5120, 5121, 5123, 5133):
            # Access denied!
            info['SOLUTION'] = (
                'This SQL Server MDF file is NOT attachable. '
                'Possible solutions:\n'
                '  1. Ensure you have full read/write access to '
                'the MDF file AND its parent folder.\n'
                '  2. Check file is not already attached '
                '(using SQL Server Management Studio.)\n'
                '  3. Delete the corresponding LDF file.\n'
                '  4. Copy MDF file to a new location.\n')

        elif info['CODE'] == 823:
            info['SOLUTION'] = (
                'The MDF file is corrupt or not a genuine database file. Try '
                'to re-create the current file or use a different file.')

        elif info['CODE'] == 5118:
            info['SOLUTION'] = (
                'SQL Server cannot read MDF files in compressed folders. '
                'Ensure the target folder is not compressed (text appears '
                'blue in Windows Explorer.)  Edit the folder properties to '
                'uncompress it and its contents.')

        elif "Server does not exist or access denied" in info['DESCRIPTION']:
            info['SOLUTION'] = (
                'Could not access SQL Server on your computer.\n'
                'Potential solutions:\n'
                '  1. Install SQL Server Express With Tools (2014+) from:\n'
                '     https://www.microsoft.com/en-us/server-cloud/products/'
                'sql-server-editions/sql-server-express.aspx.\n'
                '  2. Contact Qraken team for further assistance.\n\n'
            )
        else:
            info['SOLUTION'] = (
                'No known solutions available.'
            )

        info['MSG'] = (
            # '\nError details\n-------------\n'
            '  SQL Driver:     {DRIVER}\n'
            '  SQL state code: {SQLSTATE}\n'
            '  Error code:     {CODE}\n\n'
            'Long description\n----------------\n{DESCRIPTION}\n'
            # 'Possible solutions:\n-------------------\n{SOLUTION}\n'
        ).format(**info)

        return info
    else:
        return None