
import requests
import os
import logging
import json
from enum import Enum
# import certifi  - This didn't work, bamberg seems to be using a homemade SSL cert
# The verify attribute is set to False, as this API only works on the hospitals network
# Keeping it here in case of need, use with `verify=certifi.where()`

from median.constant import MEDIANWEB_POSTE, CONFIG_WEB_CLE
from median.views import RawConfig


class EncounterStatus(Enum):
    finished = "finished"
    in_progess = "in-progress"


class MedicationStatus(Enum):
    active = "active"
    # inactive = "?"


class BambergDataFetcher:
    """ DATA FETCHER : BAMBERG FUNCTIONS - TO BE USED ONLY WITH THE DATA FETCHER ! """
    def __init__(self, import_id: int, location_code: str):
        self.import_id = import_id
        self.logger = logging.getLogger("median.datafetcher.bamberg")
        self.location_code = location_code

    def process_import(self):
        # Call the data fetching functions for Bamberg

        try:
            self.logger.info("Fetching data from URL 1 - Encounters")
            encounters, patient_info = self.get_data_1()

            self.logger.info("Fetching data from URL 2 - Medications")
            for encounter in encounters:
                encounter_id = encounter["id"]
                self.get_data_2(encounter_id, patient_info)

            self.logger.info("Bamberg data import completed successfully")
            return True
        except Exception as e:
            self.logger.error(f"Bamberg data import failed: {e}")
            return False

    def get_data_1(self):
        url_1 = RawConfig(MEDIANWEB_POSTE, CONFIG_WEB_CLE).read(param="k_web_data_fetch_url_1")
        if not url_1:
            self.logger.error("Missing configuration for k_web_data_fetch_url_1")
            raise ValueError("Configuration for URL 1 is missing")
        try:
            if url_1.value.startswith(("http://", "https://")):
                # Fetch from URL with parameters (code location, count, offset)
                # GET https://v1bs0047.kliniken.ssb.local/fhir/Encounter?_count=10&_offset=0
                # &location=<wardName>&class=IMP&status=in-progress
                params = {
                    "location": self.location_code,
                    "_count": 100,
                    "_offset": 1100,
                    "class": "IMP",
                    "status": "in-progress",
                }
                response = requests.get(url_1.value, params=params, verify=False)
                response.raise_for_status()
                data = response.json()
                return self._extract_from_encounters_json(data)
            else:
                # Testing mode: read from local JSON file
                if not os.path.isfile(url_1.value):
                    raise ValueError(f"File not found: {url_1.value}")
                with open(url_1.value, "r", encoding="utf-8") as f:
                    data = json.load(f)
                    return self._extract_from_encounters_json(data)
            # Process or store the fetched data as needed
            self.logger.info(f"Successfully fetched data from URL 1: {len(data)} items")
        except (requests.RequestException, ValueError, json.JSONDecodeError) as e:
            self.logger.error(f"Failed to fetch data from URL 1: {e}")
            raise

    def get_data_2(self, encounter_id, patient_info):
        # Nothing happens here yet, maybe "medication request"
        url_2 = RawConfig(MEDIANWEB_POSTE, CONFIG_WEB_CLE).read(param="k_web_data_fetch_url_2")
        if not url_2:
            self.logger.error("Missing configuration for k_web_data_fetch_url_2")
            raise ValueError("Configuration for URL 1 is missing")
        try:
            if url_2.value.startswith(("http://", "https://")):
                # Fetch from URL with parameters (encounter, profile))
                # https://v1bs0047.kliniken.ssb.local/fhir/MedicationRequest
                # encounter=4420701
                # _profile=https://gematik.de/fhir/isik/StructureDefinition/ISiKMedikationsVerordnung
                url_with_params = (
                    f"{url_2.value}?encounter={encounter_id}"
                    "&_profile=https://gematik.de/fhir/isik/StructureDefinition/ISiKMedikationsVerordnung"
                )
                response = requests.get(url_with_params, verify=False)
                response.raise_for_status()
                data = response.json()

                # Extract patient_info and add to medication data
                data["patient"] = {
                    "last_name": patient_info["last_name"],
                    "first_name": patient_info["first_name"],
                    "departement": patient_info["location"][0],
                    "location": patient_info["location"][1],
                    "room": patient_info["location"][2],
                    "bed": patient_info["location"][3],
                }

                return self._extract_from_medications_json(data, encounter_id)
            else:
                # Testing mode: read from local JSON file
                if not os.path.isfile(url_2.value):
                    raise ValueError(f"File not found: {url_2.value}")
                with open(url_2.value, "r", encoding="utf-8") as f:
                    data = json.load(f)

                    # Extract patient_info and add to medication data
                    data["patient"] = {
                        "last_name": patient_info["last_name"],
                        "first_name": patient_info["first_name"],
                        "departement": patient_info["location"][0],
                        "location": patient_info["location"][1],
                        "room": patient_info["location"][2],
                        "bed": patient_info["location"][3],
                    }

                    return self._extract_from_medications_json(data, encounter_id)
            # Process or store the fetched data as needed
            self.logger.info(f"Successfully fetched data from URL 1: {len(data)} items")
        except (requests.RequestException, ValueError, json.JSONDecodeError) as e:
            self.logger.error(f"Failed to fetch data from URL 1: {e}")
            raise

        return

    def _extract_from_encounters_json(self, data):
        try:
            entries = data["entry"]

            self.logger.info(f"Found {len(entries)} encounters")

            # Keep only the active encounters
            active_entries = []
            for entry in entries:
                entry_data = entry["resource"]
                if entry_data["status"] == EncounterStatus.in_progess.value:
                    active_entries.append(entry_data)

            # Remove the original data for memory
            data.clear()
            entries.clear()

            successfull_entries = []

            for a_entry in active_entries:
                try:
                    stay_id = a_entry["id"]
                    patient_data = a_entry["subject"]
                    ipp = patient_data["id"]

                    # Get the patient location data
                    patient_info = {}
                    last_name, first_name = [part.strip() for part in patient_data["display"].split(",")]
                    patient_info["last_name"] = last_name
                    patient_info["first_name"] = first_name

                    for location_base in a_entry["location"]:
                        location_detail = location_base["location"]
                        data_identifier = location_detail["identifier"]

                        if data_identifier.get("system"):
                            patient_info["location"] = data_identifier.get("value", "").split("/")

                    # Make an enounter file
                    upload_config = RawConfig(MEDIANWEB_POSTE, CONFIG_WEB_CLE).read(param="k_web_data_fetch_upload_1")
                    if not upload_config:
                        self.logger.error("Missing configuration for k_web_data_fetch_upload_1")
                        raise ValueError("Configuration for upload path is missing")
                    else:
                        try:
                            # Create a file
                            upload_folder_path = upload_config.value
                            filename = f"encounters_{ipp}_{stay_id}_{self.import_id}.json"
                            encounter_folder = os.path.join(upload_folder_path, "encounter")
                            os.makedirs(encounter_folder, exist_ok=True)
                            filepath = os.path.join(encounter_folder, filename)
                            with open(filepath, "w", encoding="utf-8") as f:
                                json.dump(a_entry, f, ensure_ascii=False, indent=4)
                            successfull_entries.append(a_entry)
                        except PermissionError as pe:
                            self.logger.error(f"Permission error writing file {filename}: {pe}")
                            continue
                        except IOError as ioe:
                            self.logger.error(f"I/O error writing file {filename}: {ioe}")
                            continue
                        except Exception as e:
                            self.logger.error(f"Unexpected error writing file {filename}: {e}")
                            continue

                except Exception as e:
                    self.logger.error(f"Error processing entry {a_entry.get('id', 'unknown')}: {e}")
                    continue

            return successfull_entries, patient_info

        except Exception as e:
            self.logger.error(f"Error processing encounters JSON data: {e}")
            raise e

    def _extract_from_medications_json(self, data, encounter_id):
        try:
            # Make an enounter file
            upload_config = RawConfig(MEDIANWEB_POSTE, CONFIG_WEB_CLE).read(param="k_web_data_fetch_upload_1")
            if not upload_config:
                self.logger.error("Missing configuration for k_web_data_fetch_upload_1")
                raise ValueError("Configuration for upload path is missing")
            else:
                try:
                    # Here is the right place pour remove attributes we don't want in the json
                    # example with the attribute "category" :
                    # if "category" in a_entry:
                    #     del a_entry["category"]

                    # Create a file
                    upload_folder_path = upload_config.value
                    filename = f"medication_{encounter_id}_{self.import_id}.json"

                    encounter_folder = os.path.join(upload_folder_path, "medication")
                    os.makedirs(encounter_folder, exist_ok=True)
                    filepath = os.path.join(encounter_folder, filename)

                    with open(filepath, "w", encoding="utf-8") as f:
                        json.dump(data, f, ensure_ascii=False, indent=4)
                except PermissionError as pe:
                    self.logger.error(f"Permission error writing file {filename}: {pe}")
                    raise pe
                except IOError as ioe:
                    self.logger.error(f"I/O error writing file {filename}: {ioe}")
                    raise ioe
                except Exception as e:
                    self.logger.error(f"Unexpected error writing file {filename}: {e}")
                    raise e

                except Exception as e:
                    self.logger.error(f"Error processing entry {data.get('id', 'unknown')}: {e}")
                    raise e

            return True

        except Exception as e:
            self.logger.error(f"Error processing encounters JSON data: {e}")
            return False
