from django.core.exceptions import ValidationError, ObjectDoesNotExist
from django.urls import reverse as url_reverse
import re

from .models import Storage, Component

class QrCode:
    prefix = ''
    detail_view = ''
    model  = None

    def __init__(self, prefix, detail_view, model):
        self.prefix = prefix
        self.detail_view = detail_view
        self.model = model

class QrCodeValidator:

    qr_patterns = {
        'stor_uuid': QrCode('stor_uuid', 'parts-stocks-detail', Storage),
        'comp_uuid': QrCode('comp_uuid', 'parts-components-detail', Component),
    }

    def __init__(self):
        self.qr_regex = re.compile(r'^\[(?P<prefix>[a-zA-Z_]+)\](?P<uuid>[a-fA-F0-9\-]+)')
        self.redirect_url = None

    def _get_model_from_qr(self, qr):
        matches = self.qr_regex.match(qr)
        if matches is None:
            raise ValidationError("QR Code does not match expected pattern")
        
        qr_type = matches.group('prefix')
        qr_uuid = matches.group('uuid')
        url_name = self.qr_patterns[qr_type].detail_view

        model = None
        try:
            model = self.qr_patterns[qr_type].model
        except:
            model = None
        if model is None:
            raise ValidationError('QR Pattern not registered')
        return (model,qr_uuid, url_name)
    
    def get_redirect_url(self, data):
        model, uuid, url_name = self._get_model_from_qr(data)

        _ = model.objects.get(id=uuid)
        return url_reverse(url_name, kwargs={'uuid':uuid})

    def validate(self, data, *args, **kwargs):
        try:
           _ = self.get_redirect_url(data)
        except ObjectDoesNotExist as err:
            raise ValidationError('Object with given UUID could not be found')

    def __call__(self, *args, **kwargs):
        self.validate(*args, **kwargs)