# coding: utf-8



from django.db import connection
from metrics_framework.decorators import metric

from idm.core.models import System

INCONSISTENCIES_COUNT_SQL = """
WITH RECURSIVE rec AS (
  SELECT
    parent_id AS ancestor,
    id AS descendant,
    ARRAY[id] AS descendants
  FROM upravlyator_rolenode WHERE system_id=%s AND parent_id IS NOT NULL

  UNION ALL

  SELECT
    parent_id AS ancestor,
    descendant,
    descendants || ancestor AS descendants
  FROM upravlyator_rolenode
  JOIN rec ON id = ancestor
  WHERE not (ancestor = any(descendants)) AND system_id=%s AND parent_id IS NOT NULL
),
self_rec AS (
  SELECT id AS ancestor, id AS descendant, ARRAY[]::integer[] AS descendants
  FROM upravlyator_rolenode WHERE system_id=%s
),
all_rec AS (
    SELECT * FROM rec
    UNION ALL
    SELECT * FROM self_rec
)
SELECT COUNT(*)
FROM all_rec
LEFT JOIN upravlyator_rolenodeclosure closure
    ON ancestor=closure.parent_id AND descendant=closure.child_id
WHERE closure.id IS NULL;
"""

INCONSISTENT_PATHS_SQL = """
WITH RECURSIVE rec AS (
  SELECT
    id,
    0::bigint as level,
    '/' AS slug_path,
    '/' AS value_path
  FROM upravlyator_rolenode
  WHERE level = 0 AND system_id = %s

  UNION ALL

  SELECT
    node.id AS id,  
    node.level AS level,
    rec.slug_path || node.slug || '/' AS slug_path,
    CASE node.level %% 2
      WHEN 0 THEN rec.value_path || node.slug || '/'
      ELSE rec.value_path
    END AS value_path
  FROM upravlyator_rolenode node
  JOIN rec ON node.parent_id = rec.id
  WHERE node.level = rec.level + 1 AND system_id = %s
)
SELECT COUNT(*)
FROM rec JOIN upravlyator_rolenode node
ON node.id = rec.id 
WHERE node.system_id = %s AND (node.slug_path <> rec.slug_path OR node.value_path <> rec.value_path)
"""


@metric('closure_inconsistencies_count')
def compute_closure_inconsistencies_count():
    result = []
    for system in System.objects.all():
        with connection.cursor() as cursor:
            cursor.execute(INCONSISTENCIES_COUNT_SQL, [system.pk] * 3)
            value = cursor.fetchone()[0]
            result.append({'value': value, 'slug': system.slug})

    return result


@metric('closure_inconsistent_paths')
def compute_closure_inconsistent_paths():
    result = []
    for system in System.objects.all():
        with connection.cursor() as cursor:
            cursor.execute(INCONSISTENT_PATHS_SQL, [system.pk] * 3)
            value = cursor.fetchone()[0]
            result.append({'value': value, 'slug': system.slug})

    return result
