# -*- coding: utf-8 -*-
# Copyright (c) 2018, earthians and contributors
# For license information, please see license.txt

from __future__ import unicode_literals
import math
import frappe
import json
from frappe import _
from frappe.utils.formatters import format_value
from frappe.utils import time_diff_in_hours, rounded, cstr
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_income_account
from erpnext.healthcare.doctype.fee_validity.fee_validity import create_fee_validity
from erpnext.healthcare.doctype.lab_test.lab_test import create_multiple

@frappe.whitelist()
def get_healthcare_services_to_invoice(patient, company):
	patient = frappe.get_doc('Patient', patient)
	items_to_invoice = []
	if patient:
		validate_customer_created(patient)
		# Customer validated, build a list of billable services
		items_to_invoice += get_appointments_to_invoice(patient, company)
		items_to_invoice += get_encounters_to_invoice(patient, company)
		items_to_invoice += get_lab_tests_to_invoice(patient, company)
		items_to_invoice += get_clinical_procedures_to_invoice(patient, company)
		items_to_invoice += get_inpatient_services_to_invoice(patient, company)
		items_to_invoice += get_therapy_plans_to_invoice(patient, company)
		items_to_invoice += get_therapy_sessions_to_invoice(patient, company)

		return items_to_invoice


def validate_customer_created(patient):
	if not frappe.db.get_value('Patient', patient.name, 'customer'):
		msg = _("Please set a Customer linked to the Patient")
		msg +=  " <b><a href='/app/Form/Patient/{0}'>{0}</a></b>".format(patient.name)
		frappe.throw(msg, title=_('Customer Not Found'))


def get_appointments_to_invoice(patient, company):
	appointments_to_invoice = []
	patient_appointments = frappe.get_list(
			'Patient Appointment',
			fields = '*',
			filters = {'patient': patient.name, 'company': company, 'invoiced': 0, 'status': ['not in', 'Cancelled']},
			order_by = 'appointment_date'
		)

	for appointment in patient_appointments:
		# Procedure Appointments
		if appointment.procedure_template:
			if frappe.db.get_value('Clinical Procedure Template', appointment.procedure_template, 'is_billable'):
				appointments_to_invoice.append({
					'reference_type': 'Patient Appointment',
					'reference_name': appointment.name,
					'service': appointment.procedure_template
				})
		# Consultation Appointments, should check fee validity
		else:
			if frappe.db.get_single_value('Healthcare Settings', 'enable_free_follow_ups') and \
				frappe.db.exists('Fee Validity Reference', {'appointment': appointment.name}):
					continue # Skip invoicing, fee validty present
			practitioner_charge = 0
			income_account = None
			service_item = None
			if appointment.practitioner:
				details = get_service_item_and_practitioner_charge(appointment)
				service_item = details.get('service_item')
				practitioner_charge = details.get('practitioner_charge')
				income_account = get_income_account(appointment.practitioner, appointment.company)
			appointments_to_invoice.append({
				'reference_type': 'Patient Appointment',
				'reference_name': appointment.name,
				'service': service_item,
				'rate': practitioner_charge,
				'income_account': income_account
			})

	return appointments_to_invoice


def get_encounters_to_invoice(patient, company):
	if not isinstance(patient, str):
		patient = patient.name
	encounters_to_invoice = []
	encounters = frappe.get_list(
		'Patient Encounter',
		fields=['*'],
		filters={'patient': patient, 'company': company, 'invoiced': False, 'docstatus': 1}
	)
	if encounters:
		for encounter in encounters:
			if not encounter.appointment:
				practitioner_charge = 0
				income_account = None
				service_item = None
				if encounter.practitioner:
					if encounter.inpatient_record and \
						frappe.db.get_single_value('Healthcare Settings', 'do_not_bill_inpatient_encounters'):
						continue

					details = get_service_item_and_practitioner_charge(encounter)
					service_item = details.get('service_item')
					practitioner_charge = details.get('practitioner_charge')
					income_account = get_income_account(encounter.practitioner, encounter.company)

				encounters_to_invoice.append({
					'reference_type': 'Patient Encounter',
					'reference_name': encounter.name,
					'service': service_item,
					'rate': practitioner_charge,
					'income_account': income_account
				})

	return encounters_to_invoice


def get_lab_tests_to_invoice(patient, company):
	lab_tests_to_invoice = []
	lab_tests = frappe.get_list(
		'Lab Test',
		fields=['name', 'template'],
		filters={'patient': patient.name, 'company': company, 'invoiced': False, 'docstatus': 1}
	)
	for lab_test in lab_tests:
		item, is_billable = frappe.get_cached_value('Lab Test Template', lab_test.template, ['item', 'is_billable'])
		if is_billable:
			lab_tests_to_invoice.append({
				'reference_type': 'Lab Test',
				'reference_name': lab_test.name,
				'service': item
			})

	lab_prescriptions = frappe.db.sql(
		'''
			SELECT
				lp.name, lp.lab_test_code
			FROM
				`tabPatient Encounter` et, `tabLab Prescription` lp
			WHERE
				et.patient=%s
				and lp.parent=et.name
				and lp.lab_test_created=0
				and lp.invoiced=0
		''', (patient.name), as_dict=1)

	for prescription in lab_prescriptions:
		item, is_billable = frappe.get_cached_value('Lab Test Template', prescription.lab_test_code, ['item', 'is_billable'])
		if prescription.lab_test_code and is_billable:
			lab_tests_to_invoice.append({
				'reference_type': 'Lab Prescription',
				'reference_name': prescription.name,
				'service': item
			})

	return lab_tests_to_invoice


def get_clinical_procedures_to_invoice(patient, company):
	clinical_procedures_to_invoice = []
	procedures = frappe.get_list(
		'Clinical Procedure',
		fields='*',
		filters={'patient': patient.name, 'company': company, 'invoiced': False}
	)
	for procedure in procedures:
		if not procedure.appointment:
			item, is_billable = frappe.get_cached_value('Clinical Procedure Template', procedure.procedure_template, ['item', 'is_billable'])
			if procedure.procedure_template and is_billable:
				clinical_procedures_to_invoice.append({
					'reference_type': 'Clinical Procedure',
					'reference_name': procedure.name,
					'service': item
				})

		# consumables
		if procedure.invoice_separately_as_consumables and procedure.consume_stock \
			and procedure.status == 'Completed' and not procedure.consumption_invoiced:

			service_item = frappe.db.get_single_value('Healthcare Settings', 'clinical_procedure_consumable_item')
			if not service_item:
				frappe.throw(_('Please configure Clinical Procedure Consumable Item in {0}').format(
					frappe.utils.get_link_to_form('Healthcare Settings', 'Healthcare Settings')),
					title=_('Missing Configuration'))

			clinical_procedures_to_invoice.append({
				'reference_type': 'Clinical Procedure',
				'reference_name': procedure.name,
				'service': service_item,
				'rate': procedure.consumable_total_amount,
				'description': procedure.consumption_details
			})

	procedure_prescriptions = frappe.db.sql(
		'''
			SELECT
				pp.name, pp.procedure
			FROM
				`tabPatient Encounter` et, `tabProcedure Prescription` pp
			WHERE
				et.patient=%s
				and pp.parent=et.name
				and pp.procedure_created=0
				and pp.invoiced=0
				and pp.appointment_booked=0
		''', (patient.name), as_dict=1)

	for prescription in procedure_prescriptions:
		item, is_billable = frappe.get_cached_value('Clinical Procedure Template', prescription.procedure, ['item', 'is_billable'])
		if is_billable:
			clinical_procedures_to_invoice.append({
				'reference_type': 'Procedure Prescription',
				'reference_name': prescription.name,
				'service': item
			})

	return clinical_procedures_to_invoice


def get_inpatient_services_to_invoice(patient, company):
	services_to_invoice = []
	inpatient_services = frappe.db.sql(
		'''
			SELECT
				io.*
			FROM
				`tabInpatient Record` ip, `tabInpatient Occupancy` io
			WHERE
				ip.patient=%s
				and ip.company=%s
				and io.parent=ip.name
				and io.left=1
				and io.invoiced=0
		''', (patient.name, company), as_dict=1)

	for inpatient_occupancy in inpatient_services:
		service_unit_type = frappe.db.get_value('Healthcare Service Unit', inpatient_occupancy.service_unit, 'service_unit_type')
		service_unit_type = frappe.get_cached_doc('Healthcare Service Unit Type', service_unit_type)
		if service_unit_type and service_unit_type.is_billable:
			hours_occupied = time_diff_in_hours(inpatient_occupancy.check_out, inpatient_occupancy.check_in)
			qty = 0.5
			if hours_occupied > 0:
				actual_qty = hours_occupied / service_unit_type.no_of_hours
				floor = math.floor(actual_qty)
				decimal_part = actual_qty - floor
				if decimal_part > 0.5:
					qty = rounded(floor + 1, 1)
				elif decimal_part < 0.5 and decimal_part > 0:
					qty = rounded(floor + 0.5, 1)
				if qty <= 0:
					qty = 0.5
			services_to_invoice.append({
				'reference_type': 'Inpatient Occupancy',
				'reference_name': inpatient_occupancy.name,
				'service': service_unit_type.item, 'qty': qty
			})

	return services_to_invoice


def get_therapy_plans_to_invoice(patient, company):
	therapy_plans_to_invoice = []
	therapy_plans = frappe.get_list(
		'Therapy Plan',
		fields=['therapy_plan_template', 'name'],
		filters={
			'patient': patient.name,
			'invoiced': 0,
			'company': company,
			'therapy_plan_template': ('!=', '')
		}
	)
	for plan in therapy_plans:
		therapy_plans_to_invoice.append({
			'reference_type': 'Therapy Plan',
			'reference_name': plan.name,
			'service': frappe.db.get_value('Therapy Plan Template', plan.therapy_plan_template, 'linked_item')
		})

	return therapy_plans_to_invoice


def get_therapy_sessions_to_invoice(patient, company):
	therapy_sessions_to_invoice = []
	therapy_plans = frappe.db.get_all('Therapy Plan', {'therapy_plan_template': ('!=', '')})
	therapy_plans_created_from_template = []
	for entry in therapy_plans:
		therapy_plans_created_from_template.append(entry.name)

	therapy_sessions = frappe.get_list(
		'Therapy Session',
		fields='*',
		filters={
			'patient': patient.name,
			'invoiced': 0,
			'company': company,
			'therapy_plan': ('not in', therapy_plans_created_from_template)
		}
	)
	for therapy in therapy_sessions:
		if not therapy.appointment:
			if therapy.therapy_type and frappe.db.get_value('Therapy Type', therapy.therapy_type, 'is_billable'):
				therapy_sessions_to_invoice.append({
					'reference_type': 'Therapy Session',
					'reference_name': therapy.name,
					'service': frappe.db.get_value('Therapy Type', therapy.therapy_type, 'item')
				})

	return therapy_sessions_to_invoice

@frappe.whitelist()
def get_service_item_and_practitioner_charge(doc):
	if isinstance(doc, str):
		doc = json.loads(doc)
		doc = frappe.get_doc(doc)

	service_item = None
	practitioner_charge = None
	department = doc.medical_department if doc.doctype == 'Patient Encounter' else doc.department

	is_inpatient = doc.inpatient_record

	if doc.get('appointment_type'):
		service_item, practitioner_charge = get_appointment_type_service_item(doc.appointment_type, department, is_inpatient)

	if not service_item and not practitioner_charge:
		service_item, practitioner_charge = get_practitioner_service_item(doc.practitioner, is_inpatient)
		if not service_item:
			service_item = get_healthcare_service_item(is_inpatient)

	if not service_item:
		throw_config_service_item(is_inpatient)

	if not practitioner_charge:
		throw_config_practitioner_charge(is_inpatient, doc.practitioner)

	return {'service_item': service_item, 'practitioner_charge': practitioner_charge}


def get_appointment_type_service_item(appointment_type, department, is_inpatient):
	from erpnext.healthcare.doctype.appointment_type.appointment_type import get_service_item_based_on_department

	item_list = get_service_item_based_on_department(appointment_type, department)
	service_item = None
	practitioner_charge = None

	if item_list:
		if is_inpatient:
			service_item = item_list.get('inpatient_visit_charge_item')
			practitioner_charge = item_list.get('inpatient_visit_charge')
		else:
			service_item = item_list.get('op_consulting_charge_item')
			practitioner_charge = item_list.get('op_consulting_charge')

	return service_item, practitioner_charge


def throw_config_service_item(is_inpatient):
	service_item_label = _('Out Patient Consulting Charge Item')
	if is_inpatient:
		service_item_label = _('Inpatient Visit Charge Item')

	msg = _(('Please Configure {0} in ').format(service_item_label) \
		+ '''<b><a href='/app/Form/Healthcare Settings'>Healthcare Settings</a></b>''')
	frappe.throw(msg, title=_('Missing Configuration'))


def throw_config_practitioner_charge(is_inpatient, practitioner):
	charge_name = _('OP Consulting Charge')
	if is_inpatient:
		charge_name = _('Inpatient Visit Charge')

	msg = _(('Please Configure {0} for Healthcare Practitioner').format(charge_name) \
		+ ''' <b><a href='/app/Form/Healthcare Practitioner/{0}'>{0}</a></b>'''.format(practitioner))
	frappe.throw(msg, title=_('Missing Configuration'))


def get_practitioner_service_item(practitioner, is_inpatient):
	service_item = None
	practitioner_charge = None

	if is_inpatient:
		service_item, practitioner_charge = frappe.db.get_value('Healthcare Practitioner', practitioner, ['inpatient_visit_charge_item', 'inpatient_visit_charge'])
	else:
		service_item, practitioner_charge = frappe.db.get_value('Healthcare Practitioner', practitioner, ['op_consulting_charge_item', 'op_consulting_charge'])

	return service_item, practitioner_charge


def get_healthcare_service_item(is_inpatient):
	service_item = None

	if is_inpatient:
		service_item = frappe.db.get_single_value('Healthcare Settings', 'inpatient_visit_charge_item')
	else:
		service_item = frappe.db.get_single_value('Healthcare Settings', 'op_consulting_charge_item')

	return service_item


def get_practitioner_charge(practitioner, is_inpatient):
	if is_inpatient:
		practitioner_charge = frappe.db.get_value('Healthcare Practitioner', practitioner, 'inpatient_visit_charge')
	else:
		practitioner_charge = frappe.db.get_value('Healthcare Practitioner', practitioner, 'op_consulting_charge')
	if practitioner_charge:
		return practitioner_charge
	return False


def manage_invoice_submit_cancel(doc, method):
	if doc.items:
		for item in doc.items:
			if item.get('reference_dt') and item.get('reference_dn'):
				if frappe.get_meta(item.reference_dt).has_field('invoiced'):
					set_invoiced(item, method, doc.name)

	if method=='on_submit' and frappe.db.get_single_value('Healthcare Settings', 'create_lab_test_on_si_submit'):
		create_multiple('Sales Invoice', doc.name)


def set_invoiced(item, method, ref_invoice=None):
	invoiced = False
	if method=='on_submit':
		validate_invoiced_on_submit(item)
		invoiced = True

	if item.reference_dt == 'Clinical Procedure':
		service_item = frappe.db.get_single_value('Healthcare Settings', 'clinical_procedure_consumable_item')
		if service_item == item.item_code:
			frappe.db.set_value(item.reference_dt, item.reference_dn, 'consumption_invoiced', invoiced)
		else:
			frappe.db.set_value(item.reference_dt, item.reference_dn, 'invoiced', invoiced)
	else:
		frappe.db.set_value(item.reference_dt, item.reference_dn, 'invoiced', invoiced)

	if item.reference_dt == 'Patient Appointment':
		if frappe.db.get_value('Patient Appointment', item.reference_dn, 'procedure_template'):
			dt_from_appointment = 'Clinical Procedure'
		else:
			dt_from_appointment = 'Patient Encounter'
		manage_doc_for_appointment(dt_from_appointment, item.reference_dn, invoiced)

	elif item.reference_dt == 'Lab Prescription':
		manage_prescriptions(invoiced, item.reference_dt, item.reference_dn, 'Lab Test', 'lab_test_created')

	elif item.reference_dt == 'Procedure Prescription':
		manage_prescriptions(invoiced, item.reference_dt, item.reference_dn, 'Clinical Procedure', 'procedure_created')


def validate_invoiced_on_submit(item):
	if item.reference_dt == 'Clinical Procedure' and \
		frappe.db.get_single_value('Healthcare Settings', 'clinical_procedure_consumable_item') == item.item_code:
		is_invoiced = frappe.db.get_value(item.reference_dt, item.reference_dn, 'consumption_invoiced')
	else:
		is_invoiced = frappe.db.get_value(item.reference_dt, item.reference_dn, 'invoiced')
	if is_invoiced:
		frappe.throw(_('The item referenced by {0} - {1} is already invoiced').format(
			item.reference_dt, item.reference_dn))


def manage_prescriptions(invoiced, ref_dt, ref_dn, dt, created_check_field):
	created = frappe.db.get_value(ref_dt, ref_dn, created_check_field)
	if created:
		# Fetch the doc created for the prescription
		doc_created = frappe.db.get_value(dt, {'prescription': ref_dn})
		frappe.db.set_value(dt, doc_created, 'invoiced', invoiced)


def check_fee_validity(appointment):
	if not frappe.db.get_single_value('Healthcare Settings', 'enable_free_follow_ups'):
		return

	validity = frappe.db.exists('Fee Validity', {
		'practitioner': appointment.practitioner,
		'patient': appointment.patient,
		'valid_till': ('>=', appointment.appointment_date)
	})
	if not validity:
		return

	validity = frappe.get_doc('Fee Validity', validity)
	return validity


def manage_fee_validity(appointment):
	fee_validity = check_fee_validity(appointment)

	if fee_validity:
		if appointment.status == 'Cancelled' and fee_validity.visited > 0:
			fee_validity.visited -= 1
			frappe.db.delete('Fee Validity Reference', {'appointment': appointment.name})
		elif fee_validity.status == 'Completed':
			return
		else:
			fee_validity.visited += 1
			fee_validity.append('ref_appointments', {
				'appointment': appointment.name
			})
		fee_validity.save(ignore_permissions=True)
	else:
		fee_validity = create_fee_validity(appointment)
	return fee_validity


def manage_doc_for_appointment(dt_from_appointment, appointment, invoiced):
	dn_from_appointment = frappe.db.get_value(
		dt_from_appointment,
		filters={'appointment': appointment}
	)
	if dn_from_appointment:
		frappe.db.set_value(dt_from_appointment, dn_from_appointment, 'invoiced', invoiced)


@frappe.whitelist()
def get_drugs_to_invoice(encounter):
	encounter = frappe.get_doc('Patient Encounter', encounter)
	if encounter:
		patient = frappe.get_doc('Patient', encounter.patient)
		if patient:
			if patient.customer:
				items_to_invoice = []
				for drug_line in encounter.drug_prescription:
					if drug_line.drug_code:
						qty = 1
						if frappe.db.get_value('Item', drug_line.drug_code, 'stock_uom') == 'Nos':
							qty = drug_line.get_quantity()

						description = ''
						if drug_line.dosage and drug_line.period:
							description = _('{0} for {1}').format(drug_line.dosage, drug_line.period)

						items_to_invoice.append({
							'drug_code': drug_line.drug_code,
							'quantity': qty,
							'description': description
						})
				return items_to_invoice
			else:
				validate_customer_created(patient)


@frappe.whitelist()
def get_children(doctype, parent=None, company=None, is_root=False):
	parent_fieldname = 'parent_' + doctype.lower().replace(' ', '_')
	fields = [
		'name as value',
		'is_group as expandable',
		'lft',
		'rgt'
	]

	filters = [["ifnull(`{0}`,'')".format(parent_fieldname),
		'=', '' if is_root else parent]]

	if is_root:
		fields += ['service_unit_type'] if doctype == 'Healthcare Service Unit' else []
		filters.append(['company', '=', company])
	else:
		fields += ['service_unit_type', 'allow_appointments', 'inpatient_occupancy',
			'occupancy_status'] if doctype == 'Healthcare Service Unit' else []
		fields += [parent_fieldname + ' as parent']

	service_units = frappe.get_list(doctype, fields=fields, filters=filters)
	for each in service_units:
		if each['expandable'] == 1:  # group node
			available_count = frappe.db.count('Healthcare Service Unit',  filters={
				'parent_healthcare_service_unit': each['value'],
				'inpatient_occupancy': 1})

			if available_count > 0:
				occupied_count = frappe.db.count('Healthcare Service Unit',  {
					'parent_healthcare_service_unit': each['value'],
					'inpatient_occupancy': 1,
					'occupancy_status': 'Occupied'})
				# set occupancy status of group node
				each['occupied_of_available'] = str(
					occupied_count) + ' Occupied of ' + str(available_count)

	return service_units


@frappe.whitelist()
def get_patient_vitals(patient, from_date=None, to_date=None):
	if not patient: return

	vitals = frappe.db.get_all('Vital Signs', filters={
			'docstatus': 1,
			'patient': patient
		}, order_by='signs_date, signs_time', fields=['*'])

	if len(vitals):
		return vitals
	return False


@frappe.whitelist()
def render_docs_as_html(docs):
	# docs key value pair {doctype: docname}
	docs_html = "<div class='col-md-12 col-sm-12 text-muted'>"
	for doc in docs:
		docs_html += render_doc_as_html(doc['doctype'], doc['docname'])['html'] + '<br/>'
		return {'html': docs_html}


@frappe.whitelist()
def render_doc_as_html(doctype, docname, exclude_fields = []):
	"""
		Render document as HTML
	"""

	doc = frappe.get_doc(doctype, docname)
	meta = frappe.get_meta(doctype)
	doc_html = section_html = section_label = html = ""
	sec_on = has_data = False
	col_on = 0

	for df in meta.fields:
		# on section break append previous section and html to doc html
		if df.fieldtype == "Section Break":
			if has_data and col_on and sec_on:
				doc_html += section_html + html + "</div>"

			elif has_data and not col_on and sec_on:
				doc_html += """
					<br>
					<div class='row'>
						<div class='col-md-12 col-sm-12'>
							<b>{0}</b>
						</div>
					</div>
					<div class='row'>
						<div class='col-md-12 col-sm-12'>
							{1} {2}
						</div>
					</div>
				""".format(section_label, section_html, html)

			# close divs for columns
			while col_on:
				doc_html += "</div>"
				col_on -= 1

			sec_on = True
			has_data = False
			col_on = 0
			section_html = html = ""

			if df.label:
				section_label = df.label
			continue

		# on column break append html to section html or doc html
		if df.fieldtype == "Column Break":
			if sec_on and not col_on and has_data:
				section_html += """
					<br>
					<div class='row'>
						<div class='col-md-12 col-sm-12'>
							<b>{0}</b>
						</div>
					</div>
					<div class='row'>
						<div class='col-md-4 col-sm-4'>
							{1}
						</div>
				""".format(section_label, html)
			elif col_on == 1 and has_data:
				section_html += "<div class='col-md-4 col-sm-4'>" + html + "</div>"
			elif col_on > 1 and has_data:
				doc_html += "<div class='col-md-4 col-sm-4'>" + html + "</div>"
			else:
				doc_html += """
					<div class='row'>
						<div class='col-md-12 col-sm-12'>
							{0}
						</div>
					</div>
				""".format(html)

			html = ""
			col_on += 1

			if df.label:
				html += "<br>" + df.label
			continue

		# on table iterate through items and create table
		# based on the in_list_view property
		# append to section html or doc html
		if df.fieldtype == "Table":
			items = doc.get(df.fieldname)
			if not items:
				continue
			child_meta = frappe.get_meta(df.options)

			if not has_data:
				has_data = True
			table_head = table_row = ""
			create_head = True

			for item in items:
				table_row += "<tr>"
				for cdf in child_meta.fields:
					if cdf.in_list_view:
						if create_head:
							table_head += "<th class='text-muted'>" + cdf.label + "</th>"
						if item.get(cdf.fieldname):
							table_row += "<td>" + cstr(item.get(cdf.fieldname)) + "</td>"
						else:
							table_row += "<td></td>"

				create_head = False
				table_row += "</tr>"

			if sec_on:
				section_html += """
					<table class='table table-condensed bordered'>
						{0} {1}
					</table>
				""".format(table_head, table_row)
			else:
				html += """
					<table class='table table-condensed table-bordered'>
						{0} {1}
					</table>
				""".format(table_head, table_row)
			continue

		# on any other field type add label and value to html
		if not df.hidden and not df.print_hide and doc.get(df.fieldname) and df.fieldname not in exclude_fields:
			formatted_value = format_value(doc.get(df.fieldname), meta.get_field(df.fieldname), doc)
			html += "<br>{0} : {1}".format(df.label or df.fieldname, formatted_value)

			if not has_data : has_data = True

	if sec_on and col_on and has_data:
		doc_html += section_html + html + "</div></div>"
	elif sec_on and not col_on and has_data:
		doc_html += """
			<div class='col-md-12 col-sm-12'>
				<div class='col-md-12 col-sm-12'>
					{0} {1}
				</div>
			</div>
		""".format(section_html, html)

	return {"html": doc_html}


def update_address_links(address, method):
	'''
	Hook validate Address
	If Patient is linked in Address, also link the associated Customer
	'''
	if 'Healthcare' not in frappe.get_active_domains():
		return

	patient_links = list(filter(lambda link: link.get('link_doctype') == 'Patient', address.links))

	for link in patient_links:
		customer = frappe.db.get_value('Patient', link.get('link_name'), 'customer')
		if customer and not address.has_link('Customer', customer):
			address.append('links', dict(link_doctype = 'Customer', link_name = customer))


def update_patient_email_and_phone_numbers(contact, method):
	'''
	Hook validate Contact
	Update linked Patients' primary mobile and phone numbers
	'''
	if 'Healthcare' not in frappe.get_active_domains():
		return

	if contact.is_primary_contact and (contact.email_id or contact.mobile_no or contact.phone):
		patient_links = list(filter(lambda link: link.get('link_doctype') == 'Patient', contact.links))

		for link in patient_links:
			contact_details = frappe.db.get_value('Patient', link.get('link_name'), ['email', 'mobile', 'phone'], as_dict=1)
			if contact.email_id and contact.email_id != contact_details.get('email'):
				frappe.db.set_value('Patient', link.get('link_name'), 'email', contact.email_id)
			if contact.mobile_no and contact.mobile_no != contact_details.get('mobile'):
				frappe.db.set_value('Patient', link.get('link_name'), 'mobile', contact.mobile_no)
			if contact.phone and contact.phone != contact_details.get('phone'):
				frappe.db.set_value('Patient', link.get('link_name'), 'phone', contact.phone)
