# (c) cavaliba.com - tests / helper

import yaml
from app_data import crypto
from app_data.data import Instance
from app_data.loader import load_broker
from app_user.models import SireneGroup, SirenePermission, SireneUser
from app_user.role import role_get_by_name

# ---------------------------------------------------------------------------
# IAM
# ---------------------------------------------------------------------------


def add_admin_user(login="adminuser"):
    user = SireneUser.objects.create(login=login, firstname=login)
    user.save()
    role = role_get_by_name("role_admin")
    role.users.add(user)
    role.save()

def add_user_with_perm(login="unittest", perms=[]):
    user = SireneUser.objects.create(login=login, firstname=login)
    user.save()
    role = SireneGroup(keyname="role_unittest", is_role=True)
    role.save()
    for perm_name in perms:
        perm, created = SirenePermission.objects.get_or_create(keyname=perm_name)
        role.permissions.add(perm)
    role.users.add(user)
    role.save()

def add_user(login="testuser01"):
    user = SireneUser.objects.create(login=login, firstname=login)
    user.save()

def add_group(name="testgroup01"):
    r = SireneGroup(keyname=name, is_role=False)
    r.save()
    return r

def add_role(name="testrole01"):
    r = SireneGroup(keyname=name, is_role=True)
    r.save()
    return r


# ---------------------------------------------------------------------------
# site, app
# ---------------------------------------------------------------------------

def add_test_sites(count=5):
    yaml_entries = []
    for i in range(1, count + 1):
        yaml_entries.append(f'''- classname: site
  keyname: site{i:02d}
  displayname: Site {i:02d}''')
    yaml_str = '\n'.join(yaml_entries)
    datalist = yaml.safe_load(yaml_str)
    aaa = {'perms': ['p_data_create', 'p_data_site_admin']}
    _ = load_broker(datalist=datalist, aaa=aaa)

def add_test_apps(count=5):
    yaml_entries = []
    for i in range(1, count + 1):
        yaml_entries.append(f'''- classname: app
  keyname: app{i:02d}
  displayname: App {i:02d}''')
    yaml_str = '\n'.join(yaml_entries)
    datalist = yaml.safe_load(yaml_str)
    aaa = {'perms': ['p_data_create', 'p_data_app_admin']}
    _ = load_broker(datalist=datalist, aaa=aaa)

# ---------------------------------------------------------------------------
# schema
# ---------------------------------------------------------------------------

def add_schema(classname='unittest',
               action='create',
               displayname=None,
               options=None,
               field_definition=None,
               verbose=False):
    if displayname is None:
        displayname = classname

    yaml_entry = {
        'classname': '_schema',
        '_action': action,
        'keyname': classname,
        'displayname': displayname
    }

    if options:
        yaml_entry['_options'] = options

    if field_definition:
        yaml_entry.update(field_definition)

    datalist = [yaml_entry]
    aaa = {'perms': [
        'p_schema_write',
    ]}
    load_broker(datalist=datalist, aaa=aaa)

    from app_data.schema import Schema
    return Schema.from_name(classname)



def add_instance(classname=None,
                 keyname=None,
                 action='create',
                 fields=None,
                 verbose=False):
    yaml_entry = {
        'classname': classname,
        '_action': action,
        'keyname': keyname
        }

    if fields:
        yaml_entry.update(fields)

    datalist = [yaml_entry]

    aaa = {'perms': [
        'p_data_admin',
    ]}

    load_broker(datalist=datalist, aaa=aaa)



def add_schema_field(classname='test', fields={}, verbose=False):
    yaml_entry = {
        'classname': '_schema',
        'keyname': classname
    }

    # Add the field definitions directly to the schema entry
    # field_definition should be a dict like: {'field1': {...}, 'field2': {...}}
    yaml_entry.update(fields)

    datalist = [yaml_entry]

    aaa = {'perms': [
        'p_schema_write',
    ]}
    load_broker(datalist=datalist, aaa=aaa)





# ---------------------------------------------------------------------------
# pipeline
# ---------------------------------------------------------------------------


def run_pipeline(pipeline_name, schema_names, aaa=None, dryrun=False):
    from app_data.models import DataTask
    from app_data.tasks import submit_pipeline

    if aaa is None:
        aaa = {'perms': ['p_data_admin', 'p_pipeline_run']}

    handle, err = submit_pipeline(
        pipeline_name=pipeline_name,
        schema_names=schema_names,
        dryrun=dryrun,
        aaa=aaa,
        owner_type="test",
        owner_id="system",
        sync=True,
    )
    if not handle:
        return 0, 0, [err or "submit_pipeline failed"]

    dt = DataTask.objects.get(handle=handle)
    output = dt.output or {}

    total_ok = output.get("total_ok", 0)
    total_discarded = output.get("total_discarded", 0)
    errors = []
    for entry in output.get("results", []):
        errors.extend(entry.get("errors", []))

    return total_ok, total_discarded, errors


def add_pipeline_noop():

    datalist = yaml.safe_load('''
        - classname: _pipeline
          keyname: pipeline_noop
          displayname: pipeline_noop
          description: pipeline_noop
          is_enabled: True
          content: |
                csv_delimiter: '|'
                classname: test1
                keyfield: keyname
                tasks:
                - field_noop
        ''')
    aaa = {'perms': ['p_pipeline_create']}
    load_broker(datalist=datalist, aaa=aaa)




# ---------------------------------------------------------------------------
# api_key
# ---------------------------------------------------------------------------

def add_apikey_admin():

    secret = crypto.hash_create("mysecret")

    instance = Instance(classname="_apikey", keyname="test")
    data = {
        "secret": secret,
        "ip_filter": "*",
        "is_readonly": False,
        "is_enabled": True,
        "acl": "role:role_admin",
    }
    instance.merge_import(data)
    instance.create()

    return {"X-Cavaliba-Key": "test mysecret"}
