from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from .models import LogEncounter, AnomaliLog
from faskes.models import InformasiDasarFaskes
import json
import requests
from django.http import JsonResponse, StreamingHttpResponse
import asyncio
from asgiref.sync import sync_to_async

from django.template.loader import render_to_string
from .utils import post_encounter, progress_encounter
from datetime import datetime, timedelta
from django.utils import timezone
from dateutil.relativedelta import relativedelta
from bpjs.bpjs import Vclaim
from django.db.models import Count, OuterRef, Subquery, F
from otentifikasi.models import Biodata, MenuItem
from pemeriksaan.models import Pendaftaran, BiodataSatusehat, InputIcd10
import time 
from django.db import transaction
import uuid
from satusehat.objects.encounter import objBodyPost, objIcd10Rank1, objIcd10Rank2, objIcd10Primer, objIcd10Sekunder

# Create your views here.

faskes_info = InformasiDasarFaskes.objects.last()
api_url = faskes_info.auth_url
base_url = faskes_info.base_url
consent_url = faskes_info.consent_url
client_id = faskes_info.client_id
client_secret = faskes_info.secret_key
organization_id = faskes_info.organization_id
location_id = '94cfb6eb-d4b0-43b1-9a82-7ff096efb7bd' #ALABINA
  
def post_patient(request):
    token = faskes_info.auth_token
    start_date = "2023-12-15T07:25:00+07:00"
    ruangan = "Ruangan 1A"
    poli_nama = "Poliklinik Gigi"
    patient_ss_id = "PS001458"
    patient_display = "Asri Susanti"
    doctor_ss_id = "N10000001"
    doctor_display = "Drg. Nina Marlina"
    encounter_temp = post_encounter(start_date, ruangan, poli_nama, patient_ss_id, patient_display, doctor_ss_id, doctor_display)
    # Convert the payload to JSON
    json_temp = {
    "class": {
        "code": "AMB",
        "display": "ambulatory",
        "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode"
    },
    "diagnosis": [
        {
            "condition": {
                "display": "Necrosis of pulp",
                "reference": "Condition/4e3c23bb-10de-4abc-8a90-839ae468aeaa"
            },
            "rank": 1,
            "use": {
                "coding": [
                    {
                        "code": "DD",
                        "display": "Discharge diagnosis",
                        "system": "http://terminology.hl7.org/CodeSystem/diagnosis-role"
                    }
                ]
            }
        }
    ],
    "id": "d648ff8c-c36d-4f11-87bb-66d159eb285c",
    "identifier": [
        {
            "system": "http://sys-ids.kemkes.go.id/encounter/17ae0692-f882-4d42-8ee5-68970c639a1b",
            "value": "PS001458"
        }
    ],
    "location": [
        {
            "location": {
                "display": "Ruang 1A, Poliklinik Rawat Jalan",
                "reference": "Location/ef011065-38c9-46f8-9c35-d1fe68966a3e"
            }
        }
    ],
    "meta": {
        "lastUpdated": "2024-01-03T06:18:04.369973+00:00",
        "versionId": "MTcwNDI2MjY4NDM2OTk3MzAwMA"
    },
    "participant": [
        {
            "individual": {
                "display": "Drg. Nina Marlina",
                "reference": "Practitioner/N10000001"
            },
            "type": [
                {
                    "coding": [
                        {
                            "code": "ATND",
                            "display": "attender",
                            "system": "http://terminology.hl7.org/CodeSystem/v3-ParticipationType"
                        }
                    ]
                }
            ]
        }
    ],
    "period": {
        "end": "2024-01-03T09:00:00+07:00",
        "start": "2024-01-03T07:25:00+07:00"
    },
    "resourceType": "Encounter",
    "serviceProvider": {
        "reference": "Organization/17ae0692-f882-4d42-8ee5-68970c639a1b"
    },
    "status": "finished",
    "statusHistory": [
        {
            "period": {
                "end": "2024-01-03T08:00:00+07:00",
                "start": "2024-01-03T07:25:00+07:00"
            },
            "status": "arrived"
        },
        {
            "period": {
                "end": "2024-01-03T09:00:00+07:00",
                "start": "2024-01-03T08:00:00+07:00"
            },
            "status": "in-progress"
        },
        {
            "period": {
                "end": "2024-01-03T09:00:00+07:00",
                "start": "2024-01-03T09:00:00+07:00"
            },
            "status": "finished"
        }
    ],
    "subject": {
        "display": "Asri Susanti",
        "reference": "Patient/100000030009"
    }
}
    payload_json = json.dumps(json_temp)

    # Headers with Bearer token and content type
    headers = {
        'Authorization': f'Bearer {token}',
        'Content-Type': 'application/json',
    }

    # Make the POST request
    # response = requests.post(base_url, data=payload_json, headers=headers)

    # Check the response
    # if response.status_code == 200 or response.status_code == 201:
    start_date_str = datetime.strptime(start_date, "%Y-%m-%dT%H:%M:%S%z")
    conv_date = start_date_str - relativedelta(hours=7)
    log_encounter_create = LogEncounter(
        type="Encounter - POST",
        patient_id=patient_ss_id,
        patient_name=patient_display,
        practitioner=doctor_display,
        status="arrived",
        start_date=conv_date,
        json=payload_json
        # Add other fields as needed
    )
    log_encounter_create.save()
    #     print('Request successful')
    #     print(response.json())
    #     return JsonResponse(response.json(), safe=False, status=200)
    # else:
    #     print(f'Request failed with status code: {response.status_code}')
    #     print(response.text)
    #     return JsonResponse(response.json(), safe=False, status=response.status_code)

def call_patient(request):
    token = faskes_info.auth_token
    start_date = "2023-12-15T07:25:00+07:00"
    ruangan = "Ruangan 1A"
    poli_nama = "Poliklinik Gigi"
    patient_ss_id = "PS000002"
    patient_display = "Muhammad Rizki Fadillah"
    doctor_ss_id = "N10000001"
    doctor_display = "Drg. Nina Marlina"
    encounter_temp = progress_encounter(start_date, ruangan, poli_nama, patient_ss_id, patient_display, doctor_ss_id, doctor_display)
    # Convert the payload to JSON
    payload_json = json.dumps(encounter_temp)

    # Headers with Bearer token and content type
    headers = {
        'Authorization': f'Bearer {token}',
        'Content-Type': 'application/json',
    }

    # Make the PUT request
    # response = requests.post(base_url, data=payload_json, headers=headers)

    # Check the response
    # if response.status_code == 200 or response.status_code == 201:
    start_date_str = datetime.strptime(start_date, "%Y-%m-%dT%H:%M:%S%z")
    conv_date = start_date_str - relativedelta(hours=7)
    log_encounter_create = LogEncounter(
        type="Encounter - POST",
        patient_id=patient_ss_id,
        patient_name=patient_display,
        practitioner=doctor_display,
        status="arrived",
        start_date=conv_date,
        json=payload_json
        # Add other fields as needed
    )
    log_encounter_create.save()
    #     print('Request successful')
    #     print(response.json())
    #     return JsonResponse(response.json(), safe=False, status=200)
    # else:
    #     print(f'Request failed with status code: {response.status_code}')
    #     print(response.text)
    #     return JsonResponse(response.json(), safe=False, status=response.status_code)

@login_required
def records(request):
    # get_pendaftaran = BiodataSatusehat.objects.all()
    # for item in get_pendaftaran:
    #     Biodata.objects.filter(user_ptr_id=item.patient_id).update(satusehat_id=item.satusehat_id, satusehat_name=item.satusehat_name)
    if request.GET.get('filter') == 'duplicate_nik':
        nik_list = []
        anomalilist = AnomaliLog.objects.values('nomor_induk_kependudukan').annotate(
            count=Count('nomor_induk_kependudukan'),
        ).filter(count__gt=1).annotate(
            distinct_no_rm=Count('nomor_rekam_medis', distinct=True),
        ).filter(distinct_no_rm__gt=1)
        is_duplicate = 'duplicate_nik'
        anomali_total = 0
    else:
        anomali_total = 0
        # anomalilist = AnomaliLog.objects.exclude(nama_dokter='RUNA').filter(satusehat_name__isnull=False)
        anomalilist = AnomaliLog.objects.filter(satusehat_name__isnull=False)
        for item in anomalilist:
            if InputIcd10.objects.filter(pendaftaran_id=item.id).exists():
                item.is_diagnosa = 1
            else:
                anomali_total += 1
                item.is_diagnosa = 0
        is_duplicate = ''

    terkirim = Pendaftaran.objects.filter(satusehat_status=1).count()
    pending = Pendaftaran.objects.filter(satusehat_status=0).count()
    user_groups = request.user.groups.all()
    menu_items = MenuItem.objects.filter(auth_menu_access__group__in=user_groups).order_by('order').distinct()
    context = {
        'terkirim': terkirim,
        'pending': pending,
        'anomali': anomali_total,
        'anomalilist': anomalilist,
        'is_duplicate': is_duplicate,
        'menu_items': menu_items,
    }
    return render(request, 'satusehat/record.html', context)

def checklist_record(request):
    patients_status = []

    return render(request, 'satusehat/popup.html', {'patients_status': patients_status})

@sync_to_async
def sync_get_access_token(payload):
    try:
        response = requests.post(api_url + "/accesstoken?grant_type=client_credentials", data=payload, headers={'Content-Type': 'application/x-www-form-urlencoded'})
        response.raise_for_status()
        json_response = response.json()
        with transaction.atomic():
            faskes_info.auth_token = json_response.get('access_token')
            faskes_info.save()
        return True
    except requests.exceptions.RequestException as err:
        json_data = json.dumps({str(err)})
        return False

@sync_to_async
def sync_send_encounter(payload_json, headers, id):
    try:
        response = requests.post(base_url, data=payload_json, headers=headers)
        response.raise_for_status()  # Raises an HTTPError for bad responses (4xx or 5xx)
        # Check the response
        if response.status_code == 200 or response.status_code == 201:
            json_data = json.dumps(response.json())
            Pendaftaran.objects.filter(id=id).update(satusehat_status=1, ss_response=json_data)
            return True
            # break
        else:
            json_data = json.dumps(response.json())
            return False
    except requests.exceptions.RequestException as err:
        json_data = json.dumps({str(err)})
        print(json_data)

async def send_encounter(payload_json, headers, item_id):
    return await sync_send_encounter(payload_json, headers, item_id)

async def get_access_token(request):
    payload = {
        'client_id': client_id,
        'client_secret': client_secret,
    }
    return await sync_get_access_token(payload)

async def generate_events(request):
    patients = [
        {'name': 'Pasien 1', 'dokter': 'Dr. Safira', 'status': 'success...✔', 'status_color': 'green'},
        {'name': 'Pasien 2', 'dokter': 'Dr. Safira', 'status': 'failed...✘', 'status_color': 'red'},
        {'name': 'Pasien 3', 'dokter': 'Dr. Safira', 'status': 'success...✔', 'status_color': 'green'},
        # Add more patients if needed
    ]

    yield f"<div><i>Generating authorization token...</i></div>"
    access = await get_access_token(request)
    if access:
        yield f"<div><i>Token successfully generated...</i></div>"
        get_pendaftaran =  await sync_to_async(list)(Pendaftaran.objects.exclude(pasien__satusehat_id__isnull=True).filter(pasien__nomor_induk_kependudukan__isnull=False, satusehat_status__isnull=True, dokter_id=41432)[:1000])
        for item in get_pendaftaran:
            exists = await sync_to_async(InputIcd10.objects.filter(pendaftaran_id=item.id).exists)()
            if exists:
                diagnosa = await sync_to_async(list)(InputIcd10.objects.filter(pendaftaran_id=item.id)[:2])
                uuid1 = uuid.uuid4()
                uuid_icd10_primer = uuid.uuid4()
                uuid_icd10_sekunder = uuid.uuid4()
                tanggal_masuk = item.waktu_masuk.strftime("%d %B %Y")    
                created_at = item.created_at.strftime("%Y-%m-%dT%H:%M:%S+00:00")
                waktu_masuk = item.waktu_masuk.strftime("%Y-%m-%dT%H:%M:%S+00:00")
                waktu_keluar = item.waktu_keluar.strftime("%Y-%m-%dT%H:%M:%S+00:00")

                body_post = await objBodyPost(uuid1, item, location_id, organization_id, created_at, waktu_masuk, waktu_keluar)

                if len(diagnosa) >= 2:
                    icd10rank1 = await objIcd10Rank1(uuid_icd10_primer, diagnosa)
                    icd10rank2 = await objIcd10Rank2(uuid_icd10_sekunder, diagnosa)
                    icd101 = await objIcd10Primer(uuid1, item, uuid_icd10_primer, diagnosa, tanggal_masuk)
                    icd102 = await objIcd10Sekunder(uuid1, item, uuid_icd10_sekunder, diagnosa, tanggal_masuk)

                    body_post['entry'][0]['resource'].setdefault("diagnosis", []).append(icd10rank1)
                    body_post.setdefault("entry", []).append(icd101)
                    body_post['entry'][0]['resource'].setdefault("diagnosis", []).append(icd10rank2)
                    body_post.setdefault("entry", []).append(icd102)

                else:
                    icd10rank1 = await objIcd10Rank1(uuid_icd10_primer, diagnosa)
                    icd101 = await objIcd10Primer(uuid1, item, uuid_icd10_primer, diagnosa, tanggal_masuk)

                    body_post['entry'][0]['resource'].setdefault("diagnosis", []).append(icd10rank1)
                    body_post.setdefault("entry", []).append(icd101)

                payload_json = json.dumps(body_post)
                auth = faskes_info.auth_token
                headers = {
                    'Authorization': f'Bearer {auth}',
                    'Content-Type': 'application/json',
                }
                # send = send_encounter(payload_json, headers, item.id)
                send = True
                if send:
                    patient_item_html = await sync_to_async(render_to_string)('satusehat/_item_patient.html', {'patient': {'name': item.pasien.satusehat_name, 'dokter': item.dokter.first_name, 'status': 'success...✔', 'status_color': 'green'}})
                    yield patient_item_html
                else:
                    patient_item_html = await sync_to_async(render_to_string)('satusehat/_item_patient.html', {'patient': {'name': 'Anjay', 'dokter': 'Aneh', 'status': 'failed...✘', 'status_color': 'green'}})
                    yield patient_item_html
                print(payload_json)
                break

async def checklist_stream(request):
    return StreamingHttpResponse(generate_events(request))

@login_required
def history_detail(request):
    if request.POST.get('id'):
        id = request.POST.get('id')
    else:
        id = 1
    # Create a subquery to get the latest Pendaftaran record for each unique nomor_rekam_medis
    subquery = Pendaftaran.objects.filter(
        pasien__nomor_induk_kependudukan=id
    ).order_by('-created_at').values('id')

    # Use the subquery to filter the main queryset
    history = Pendaftaran.objects.filter(
        id__in=Subquery(subquery)
    ).values()

    # Annotate the related data
    history = history.annotate(
        nomor_rekam_medis=F('pasien__nomor_rekam_medis'),
        alamat=F('pasien__alamat'),
        nama_pasien=F('pasien__first_name'),
        nama_dokter=F('dokter__first_name'),
        polinama=F('dokter__poli__nama'),
        biaya=F('pembayaran__total_pembayaran')
    )

    return JsonResponse(list(history), safe=False)

def change_rm(request):
    try:
        firstrm = request.POST.get('firstrm')
        secondrm = request.POST.get('secondrm')
        get_biodata = Biodata.objects.get(nomor_rekam_medis=secondrm)
        Pendaftaran.objects.filter(pasien__nomor_rekam_medis=firstrm).update(pasien_id=get_biodata.user_ptr_id)
        return JsonResponse({'code':200,'msg':'Berhasil'}, safe=False)
    except:
        return JsonResponse({'code':400,'msg':'Gagal'}, safe=False)

def checkNikByBpjs(request):
    current_date = timezone.now()
    formatted_date = current_date.strftime('%Y-%m-%d')
    data = request.POST
    route = 'Peserta/{0}/{1}/tglSEP/{2}'.format(data.get('noka_bpjs'), data.get('nomor'), formatted_date)
    try:
        req = Vclaim(route=route)
        req.get()
        if req.data:
            data = req.data
            obj = {
                'nokartu' : data['peserta']['noKartu'],
                'nik' : data['peserta']['nik'],
                'nama' : data['peserta']['nama'],
                'pisa' : data['peserta']['pisa'],
                'sex' : data['peserta']['sex'],
                'noMR' : data['peserta']['mr']['noMR'],
                'noTelepon' : data['peserta']['mr']['noTelepon'],
                'tglLahir' : data['peserta']['tglLahir'],
                'tglCetakKartu' : data['peserta']['tglCetakKartu'],
                'tglTAT' : data['peserta']['tglTAT'],
                'tglTMT' : data['peserta']['tglTMT'],
                'kodeStatusPeserta' : data['peserta']['statusPeserta']['kode'],
                'keteranganStatusPeserta' : data['peserta']['statusPeserta']['keterangan'],
                'kdProvider' : data['peserta']['provUmum']['kdProvider'],
                'nmProvider' : data['peserta']['provUmum']['nmProvider'],
                'kodeJenisPeserta' : data['peserta']['jenisPeserta']['kode'],
                'keteranganJenisPeserta' : data['peserta']['jenisPeserta']['keterangan'],
                'kodeHakKelas' : data['peserta']['hakKelas']['kode'],
                'keteranganHakKelas' : data['peserta']['hakKelas']['keterangan'],
                'umurSekarang' : data['peserta']['umur']['umurSekarang'],
                'umurSaatPelayanan' : data['peserta']['umur']['umurSaatPelayanan'],
                'dinsos' : data['peserta']['informasi']['dinsos'],
                'prolanisPRB' : data['peserta']['informasi']['prolanisPRB'],
                'noSKTM' : data['peserta']['informasi']['noSKTM'],
                'eSEP' : data['peserta']['informasi']['eSEP'],
                'noAsuransi' : data['peserta']['cob']['noAsuransi'],
                'nmAsuransi' : data['peserta']['cob']['nmAsuransi'],
                'tglTMT_COB' : data['peserta']['cob']['tglTMT'],
                'tglTAT_COB' : data['peserta']['cob']['tglTAT']
            }
            return JsonResponse(obj, safe=False)
        else:
            return JsonResponse('Gagal', safe=False)
    except requests.Timeout:
        print("Request timed out")
    except requests.TooManyRedirects:
        print("Too many redirects")
    except requests.RequestException as e:
        print("Request exception:", e) 

            
@login_required
def get_records(request):
    now = timezone.now()
    records = LogEncounter.objects.filter(created_at__gte=now - timezone.timedelta(days=1)).values()
    return JsonResponse(list(records), safe=False, status=200)