import re
import time
from datetime import datetime

from django.conf import settings
from django.db import transaction

import olympia.core.logger
from olympia import amo
from olympia.addons.models import Addon
from olympia.amo.celery import task
from olympia.amo.decorators import use_primary_db
from olympia.users.utils import get_task_user

from .models import Block, BlockSubmission, KintoImport
from .utils import block_activity_log_save


log = olympia.core.logger.getLogger('z.amo.blocklist')

bracket_open_regex = re.compile(r'(?<!\\){')
bracket_close_regex = re.compile(r'(?<!\\)}')


@task
@use_primary_db
def process_blocksubmission(multi_block_submit_id, **kw):
    obj = BlockSubmission.objects.get(pk=multi_block_submit_id)
    if obj.action == BlockSubmission.ACTION_ADDCHANGE:
        # create the blocks from the guids in the multi_block
        obj.save_to_block_objects()
    elif obj.action == BlockSubmission.ACTION_DELETE:
        # delete the blocks
        obj.delete_block_objects()


@task
@use_primary_db
@transaction.atomic
def import_block_from_blocklist(record):
    kinto_id = record.get('id')
    using_db = 'replica' if 'replica' in settings.DATABASES else 'default'
    log.debug('Processing block id: [%s]', kinto_id)
    kinto = KintoImport.objects.create(kinto_id=kinto_id, record=record)

    guid = record.get('guid')
    if not guid:
        kinto.update(outcome=KintoImport.OUTCOME_MISSINGGUID)
        log.error('Kinto %s: GUID is falsey, skipping.', kinto_id)
        return
    version_range = record.get('versionRange', [{}])[0]
    target_application = version_range.get('targetApplication') or [{}]
    target_GUID = target_application[0].get('guid')
    if target_GUID and target_GUID != amo.FIREFOX.guid:
        kinto.update(outcome=KintoImport.OUTCOME_NOTFIREFOX)
        log.error(
            'Kinto %s: targetApplication (%s) is not Firefox, skipping.',
            kinto_id, target_GUID)
        return
    block_kw = {
        'min_version': version_range.get('minVersion', '0'),
        'max_version': version_range.get('maxVersion', '*'),
        'url': record.get('details', {}).get('bug'),
        'reason': record.get('details', {}).get('why', ''),
        'kinto_id': kinto_id,
        'include_in_legacy': True,
        'updated_by': get_task_user(),
    }
    modified_date = datetime.fromtimestamp(
        record.get('last_modified', time.time() * 1000) / 1000)

    if guid.startswith('/'):
        # need to escape the {} brackets or mysql chokes.
        guid_regexp = bracket_open_regex.sub(r'\{', guid[1:-1])
        guid_regexp = bracket_close_regex.sub(r'\}', guid_regexp)
        log.debug(
            'Kinto %s: Attempting to create Blocks for addons matching [%s]',
            kinto_id, guid_regexp)
        addons_guids_qs = Addon.unfiltered.using(using_db).filter(
            guid__regex=guid_regexp).values_list('guid', flat=True)
        # We need to mark this id in a way so we know its from a
        # regex guid - otherwise we might accidentally overwrite it.
        block_kw['kinto_id'] = '*' + block_kw['kinto_id']
        regex = True
    else:
        log.debug(
            'Kinto %s: Attempting to create a Block for guid [%s]',
            kinto_id, guid)
        addons_guids_qs = Addon.unfiltered.using(using_db).filter(
            guid=guid).values_list('guid', flat=True)
        regex = False
    for guid in addons_guids_qs:
        (block, created) = Block.objects.update_or_create(
            guid=guid,
            defaults=dict(guid=guid, **block_kw))
        block_activity_log_save(block, change=not created)
        if created:
            log.debug('Kinto %s: Added Block for [%s]', kinto_id, block.guid)
            block.update(modified=modified_date)
        else:
            log.debug('Kinto %s: Updated Block for [%s]', kinto_id, block.guid)
    if addons_guids_qs:
        kinto.update(outcome=(KintoImport.OUTCOME_REGEXBLOCKS if regex else
                              KintoImport.OUTCOME_BLOCK))
    else:
        kinto.update(outcome=KintoImport.OUTCOME_NOMATCH)
        log.debug(
            'Kinto %s: No addon found', kinto_id)

@@ -1256,16 +1256,23 @@
    kinto
+_import
  = Kinto
@@ -1281,23 +1281,8 @@
 port
-.objects.create
 (kin
@@ -1373,32 +1373,34 @@
    kinto
-.update(
+_import.
 outcome
-=
+ = 
 KintoImp
@@ -1418,24 +1418,51 @@
 _MISSINGGUID
+%0A        kinto_import.save(
 )%0A        lo
@@ -1782,32 +1782,34 @@
    kinto
-.update(
+_import.
 outcome
-=
+ = 
 KintoImp
@@ -1830,16 +1830,43 @@
 TFIREFOX
+%0A        kinto_import.save(
 )%0A      
@@ -3552,28 +3552,16 @@
 id=guid,
-%0A           
  default
@@ -3932,25 +3932,40 @@
 into
-.update(outcome=(
+_import.outcome = (%0A            
 Kint
@@ -4006,34 +4006,16 @@
 ex else%0A
-                  
         
@@ -4043,17 +4043,25 @@
 ME_BLOCK
-)
+%0A        
 )%0A    el
@@ -4081,24 +4081,26 @@
 into
-.update(
+_import.
 outcome
-=
+ = 
 Kint
@@ -4122,17 +4122,16 @@
 _NOMATCH
-)
 %0A       
@@ -4137,37 +4137,24 @@
   log.debug(
-%0A            
 'Kinto %25s: N
@@ -4167,20 +4167,44 @@
 n found', kinto_id)%0A
+    kinto_import.save()%0A

Refactor blocklist import task to avoid extra db queries