# -*- coding: utf-8 -*-
import logging
import click

from cg.constants import PRIORITY_OPTIONS, STATUS_OPTIONS
from cg.store import Store

LOG = logging.getLogger(__name__)


@click.group()
@click.pass_context
def add(context):
    """Add new things to the database."""
    context.obj['db'] = Store(context.obj['database'])


@add.command()
@click.argument('internal_id')
@click.argument('name')
@click.option('-cg', '--customer-group', 'customer_group_id', required=False,
              help='internal ID for the customer group of the customer, a new group will be '
                   'created if left out')
@click.option('-ia', '--invoice-address', 'invoice_address', required=True,
              help='Street adress, Post code, City')
@click.option('-ir', '--invoice-reference', 'invoice_reference', required=True,
              help='Invoice reference (text)')
@click.pass_context
def customer(context, internal_id: str, name: str, customer_group_id: str, invoice_address: str,
             invoice_reference: str):
    """Add a new customer with a unique INTERNAL_ID and NAME."""
    existing = context.obj['db'].customer(internal_id)
    if existing:
        LOG.error(f"{existing.name}: customer already added")
        context.abort()

    customer_group = context.obj['db'].customer_group(customer_group_id)
    if not customer_group:
        customer_group = context.obj['db'].add_customer_group(internal_id=internal_id, name=name)

    new_customer = context.obj['db'].add_customer(internal_id=internal_id, name=name,
                                                  customer_group=customer_group,
                                                  invoice_address=invoice_address,
                                                  invoice_reference=invoice_reference)
    context.obj['db'].add_commit(new_customer)
    message = f"customer added: {new_customer.internal_id} ({new_customer.id})"
    LOG.info(message)


@add.command()
@click.option('-a', '--admin', is_flag=True, help='make the user an admin')
@click.option('-c', '--customer', 'customer_id', required=True,
              help='internal ID for the customer of the user')
@click.argument('email')
@click.argument('name')
@click.pass_context
def user(context, admin, customer_id, email, name):
    """Add a new user with an EMAIL (login) and a NAME (full)."""
    customer_obj = context.obj['db'].customer(customer_id)
    existing = context.obj['db'].user(email)
    if existing:
        LOG.error(f"{existing.name}: user already added")
        context.abort()
    new_user = context.obj['db'].add_user(customer_obj, email, name, is_admin=admin)
    context.obj['db'].add_commit(new_user)
    LOG.info(f"user added: {new_user.email} ({new_user.id})")


@add.command()
@click.option('-l', '--lims', 'lims_id', help='LIMS id for the sample')
@click.option('-d', '--downsampled', type=int, help='how many reads is the sample downsampled to?')
@click.option('-o', '--order', help='name of the order the sample belongs to')
@click.option('-s', '--sex', type=click.Choice(['male', 'female', 'unknown']), required=True,
              help='sample pedigree sex')
@click.option('-a', '--application', required=True, help='application tag name')
@click.option('-p', '--priority', type=click.Choice(PRIORITY_OPTIONS), default='standard',
              help='set the priority for the samples')
@click.argument('customer_id')
@click.argument('name')
@click.pass_context
def sample(context, lims_id, downsampled, sex, order, application, priority, customer_id, name):
    """Add a sample for CUSTOMER_ID with a NAME (display)."""
    status = context.obj['db']
    customer_obj = status.customer(customer_id)
    if customer_obj is None:
        LOG.error('customer not found')
        context.abort()
    application_obj = status.application(application)
    if application_obj is None:
        LOG.error('application not found')
        context.abort()
    new_record = status.add_sample(
        name=name,
        sex=sex,
        internal_id=lims_id,
        order=order,
        downsampled_to=downsampled,
        priority=priority,
    )
    new_record.application_version = status.current_application_version(application)
    new_record.customer = customer_obj
    status.add_commit(new_record)
    LOG.info(f"{new_record.internal_id}: new sample added")


@add.command()
@click.option('--priority', type=click.Choice(PRIORITY_OPTIONS), default='standard',
              help='analysis priority')
@click.option('-p', '--panel', 'panels', multiple=True, required=True, help='default gene panels')
@click.argument('customer_id')
@click.argument('name')
@click.pass_context
def family(context, priority, panels, customer_id, name):
    """Add a family to CUSTOMER_ID with a NAME."""
    status = context.obj['db']
    customer_obj = status.customer(customer_id)
    if customer_obj is None:
        LOG.error(f"{customer_id}: customer not found")
        context.abort()

    for panel_id in panels:
        panel_obj = status.panel(panel_id)
        if panel_obj is None:
            LOG.error(f"{panel_id}: panel not found")
            context.abort()

    new_family = status.add_family(
        name=name,
        panels=panels,
        priority=priority,
    )
    new_family.customer = customer_obj
    status.add_commit(new_family)
    LOG.info(f"{new_family.internal_id}: new family added")


@add.command()
@click.option('-m', '--mother', help='sample ID for mother of sample')
@click.option('-f', '--father', help='sample ID for father of sample')
@click.option('-s', '--status', type=click.Choice(STATUS_OPTIONS),
              required=True)
@click.argument('family_id')
@click.argument('sample_id')
@click.pass_context
def relationship(context, mother, father, status, family_id, sample_id):
    """Create a link between a FAMILY_ID and a SAMPLE_ID."""
    status_db = context.obj['db']
    mother_obj = None
    father_obj = None
    family_obj = status_db.family(family_id)
    if family_obj is None:
        LOG.error('%s: family not found', family_id)
        context.abort()

    sample_obj = status_db.sample(sample_id)
    if sample_obj is None:
        LOG.error('%s: sample not found', sample_id)
        context.abort()

    if mother:
        mother_obj = status_db.sample(mother)
        if mother_obj is None:
            LOG.error('%s: mother not found', mother)
            context.abort()

    if father:
        father_obj = status_db.sample(father)
        if father_obj is None:
            LOG.error('%s: father not found', father)
            context.abort()

    new_record = status_db.relate_sample(family_obj, sample_obj, status, mother=mother_obj,
                                         father=father_obj)
    status_db.add_commit(new_record)
    LOG.info(f"related {family_obj.internal_id} to {sample_obj.internal_id}")
