"""
Link Prescriptions to Diagnoses Script
Links existing prescriptions to diagnoses by matching medication pharmClass
to diagnosis ICD codes using body-region heuristics.

REVERSIBLE: To undo, run:
    db.prescriptions.updateMany({}, {$unset: {diagnosisId: ""}})
"""

import sys
import os

sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))

from bson import ObjectId
from pymongo import MongoClient
from dotenv import load_dotenv

load_dotenv(os.path.join(os.path.dirname(__file__), '..', '.env'))

MONGODB_URI = os.getenv('MONGODB_URI')
MONGODB_DB_NAME = os.getenv('MONGODB_DB_NAME', 'hipograf')

# Map medication pharmClass → likely ICD code prefixes
PHARMCLASS_ICD_MAP = {
    'Retinoid': ['L70', 'L24'],
    'Nonsteroidal Anti-inflammatory Drug': ['M54', 'M00-M99'],
    'Corticosteroid': ['L24', 'J45', 'L70'],
    'Proton Pump Inhibitor': ['K20-K31'],
    'HMG-CoA Reductase Inhibitor': ['E11', 'I10'],
    'Angiotensin Converting Enzyme Inhibitor': ['I10'],
    'Angiotensin 2 Receptor Blocker': ['I10'],
    'beta-Adrenergic Blocker': ['I10'],
    'Dihydropyridine Calcium Channel Blocker': ['I10'],
    'Sulfonylurea': ['E11'],
    'Insulin Analog': ['E11'],
    'beta-Adrenergic Agonist': ['J45'],
    'Anti-epileptic Agent': ['G43', 'G40'],
    'Benzodiazepine': ['G43', 'F41'],
    'Azole Antifungal': ['L24', 'L70'],
    'Muscle Relaxant': ['M54'],
}


def main():
    print("=" * 60)
    print("Link Prescriptions to Diagnoses")
    print("=" * 60)

    client = MongoClient(MONGODB_URI)
    db = client[MONGODB_DB_NAME]

    prescriptions = list(db.prescriptions.find({}))
    diagnoses = list(db.diagnoses.find({}))

    print(f"\nFound {len(prescriptions)} prescriptions and {len(diagnoses)} diagnoses.")

    if not prescriptions or not diagnoses:
        print("Nothing to link.")
        return

    # Build diagnosis lookup by patient and ICD code
    diag_by_patient = {}
    for d in diagnoses:
        pid = str(d['patientId'])
        if pid not in diag_by_patient:
            diag_by_patient[pid] = []
        diag_by_patient[pid].append(d)

    linked = 0
    for pres in prescriptions:
        patient_id = str(pres['patientId'])
        patient_diagnoses = diag_by_patient.get(patient_id, [])

        if not patient_diagnoses:
            continue

        # Get medication info
        med_id = pres.get('medicationId')
        med = None
        if med_id:
            med = db.medications.find_one({'_id': ObjectId(str(med_id))})

        if not med:
            continue

        pharm_class = med.get('pharmClass', '')
        med_name = med.get('genericName', '')

        # Try to match via pharmClass → ICD mapping
        best_diagnosis = None
        icd_prefixes = PHARMCLASS_ICD_MAP.get(pharm_class, [])

        for diag in patient_diagnoses:
            diag_code = diag.get('icdCode', '')
            diag_base = diag_code.split('.')[0]

            for prefix in icd_prefixes:
                if '-' in prefix:
                    # Range like M00-M99
                    start, end = prefix.split('-')
                    if start <= diag_base <= end:
                        best_diagnosis = diag
                        break
                elif diag_code.startswith(prefix) or diag_base == prefix:
                    best_diagnosis = diag
                    break

            if best_diagnosis:
                break

        # If no match by pharmClass, try matching by body region
        if not best_diagnosis and med:
            # Look up disease for each diagnosis and compare body regions
            med_indications = (med.get('indications', '') or '').lower()
            for diag in patient_diagnoses:
                diag_notes = (diag.get('notes', '') or '').lower()
                diag_code = diag.get('icdCode', '')

                # Check if medication indications mention the diagnosis
                if diag_code.lower() in med_indications:
                    best_diagnosis = diag
                    break

        if best_diagnosis:
            db.prescriptions.update_one(
                {'_id': pres['_id']},
                {'$set': {'diagnosisId': best_diagnosis['_id']}}
            )
            linked += 1
            print(f"  Linked: {med_name} → {best_diagnosis.get('icdCode', '?')} ({best_diagnosis.get('notes', '')[:50]})")
        else:
            print(f"  No match: {med_name} ({pharm_class})")

    print(f"\n{'=' * 60}")
    print(f"Linked {linked}/{len(prescriptions)} prescriptions to diagnoses.")
    print(f"\nTo undo: db.prescriptions.updateMany({{}}, {{$unset: {{diagnosisId: ''}}}})")

    client.close()


if __name__ == '__main__':
    main()
