from selenium import webdriver
from selenium.common import TimeoutException
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait, Select
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager
import re
import time
import os
import base64
import tempfile
from datetime import datetime


class AutomationMassHealthPreAuth:
    def __init__(self, data):
        self.headless = False
        self.driver = None
        self.extracted_data = {}

        print(f"DEBUG: Received data = {data}")
        self.upload_files = []
        if isinstance(data, dict):
            self.upload_files = (data.get("pdfs", []) or []) + (data.get("images", []) or [])
        self.data = data.get("data") if isinstance(data, dict) else None
        if not self.data and isinstance(data, dict) and isinstance(data.get("claim"), dict):
            claim = data.get("claim")
            first_line = None
            if isinstance(claim.get("serviceLines"), list) and len(claim.get("serviceLines")) > 0:
                first_line = claim.get("serviceLines")[0] if isinstance(claim.get("serviceLines")[0], dict) else None

            patient_name = (claim.get("patientName") or "").strip()
            first_name = ""
            last_name = ""
            if patient_name:
                parts = patient_name.split()
                first_name = parts[0] if len(parts) > 0 else ""
                last_name = " ".join(parts[1:]) if len(parts) > 1 else ""

            self.data = {
                "massdhpUsername": claim.get("massdhpUsername", ""),
                "massdhpPassword": claim.get("massdhpPassword", ""),
                "memberId": claim.get("memberId", ""),
                "dateOfBirth": claim.get("dateOfBirth", ""),
                "submissionDate": claim.get("serviceDate", ""),
                "firstName": claim.get("firstName", "") or first_name,
                "lastName": claim.get("lastName", "") or last_name,
                "procedureCode": (first_line or {}).get("procedureCode", "") if first_line else "",
                "toothNumber": (first_line or {}).get("toothNumber", "") if first_line else "",
                "toothSurface": (first_line or {}).get("toothSurface", "") if first_line else "",
            }

        if not self.data:
            self.data = {}

        print(f"DEBUG: Extracted data = {self.data}")

        # Extract service lines data for multiple rows
        self.serviceLines = []
        if isinstance(data, dict) and isinstance(data.get("claim"), dict):
            claim = data.get("claim")
            service_lines = claim.get("serviceLines", [])
            if isinstance(service_lines, list) and len(service_lines) > 0:
                self.serviceLines = service_lines

        print(f"DEBUG: Found {len(self.serviceLines)} service lines")
        for i, line in enumerate(self.serviceLines):
            print(f"DEBUG: Service line {i+1}: {line}")

        # Flatten values for convenience
        self.massdhp_username = self.data.get("massdhpUsername", "")
        self.massdhp_password = self.data.get("massdhpPassword", "")
        self.dateOfBirth = self.data.get("dateOfBirth", "")
        self.originalDateOfBirth = self.data.get("dateOfBirth", "")
        self.memberId = self.data.get("memberId", "")
        self.submissionDate = self.data.get("submissionDate", "")
        self.firstName = self.data.get("firstName", "")
        self.lastName = self.data.get("lastName", "")
        self.procedureCode = self.data.get("procedureCode", "")
        self.toothNumber = self.data.get("toothNumber", "")
        self.toothSurface = self.data.get("toothSurface", "")

        print(f"DEBUG: submissionDate = '{self.submissionDate}'")
        print(f"DEBUG: firstName = '{self.firstName}', lastName = '{self.lastName}'")
        print(f"DEBUG: procedureCode = '{self.procedureCode}'")

        # Extract rendering provider info from npiProvider field
        self.rendering_provider_name = ""
        self.rendering_provider_npi = ""
        if isinstance(data, dict) and isinstance(data.get("claim"), dict):
            npi_provider = data["claim"].get("npiProvider") or {}
            self.rendering_provider_name = (npi_provider.get("providerName") or "").strip()
            self.rendering_provider_npi = (npi_provider.get("npiNumber") or "").strip()

        print(f"DEBUG: rendering_provider_name = '{self.rendering_provider_name}'")
        print(f"DEBUG: rendering_provider_npi = '{self.rendering_provider_npi}'")

        # Convert dateOfBirth to MMDDYYYY format
        if self.dateOfBirth:
            dob_raw = str(self.dateOfBirth).strip()
            if "T" in dob_raw:
                dob_raw = dob_raw.split("T")[0]

            parsed = None
            for fmt in ("%Y-%m-%d", "%m-%d-%Y", "%m/%d/%Y"):
                try:
                    parsed = datetime.strptime(dob_raw, fmt)
                    break
                except Exception:
                    continue

            if parsed:
                self.dateOfBirth = parsed.strftime("%m%d%Y")

        self.download_dir = os.path.abspath("downloads")
        os.makedirs(self.download_dir, exist_ok=True)

    def config_driver(self):
        options = webdriver.ChromeOptions()
        if self.headless:
            options.add_argument("--headless")

        options.add_argument("--enable-print-browser")

        prefs = {
            "download.default_directory": self.download_dir,
            "plugins.always_open_pdf_externally": False,
            "download.prompt_for_download": False,
            "download.directory_upgrade": True,
        }
        options.add_experimental_option("prefs", prefs)

        s = Service(ChromeDriverManager().install())
        driver = webdriver.Chrome(service=s, options=options)
        self.driver = driver

    def login(self):
        wait = WebDriverWait(self.driver, 30)

        try:
            signin_button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a.btn.btn-block.btn-primary[href='https://connectsso.masshealth-dental.org/mhprovider/index.html']")))
            signin_button.click()
            time.sleep(2)

            email_field = wait.until(EC.presence_of_element_located((By.ID, "User")))
            email_field.clear()
            email_field.send_keys(self.massdhp_username)

            password_field = wait.until(EC.presence_of_element_located((By.ID, "Password")))
            password_field.clear()
            password_field.send_keys(self.massdhp_password)

            login_button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input[type='submit'][name='submit'][value='Login']")))
            login_button.click()

            return "Success"
        except Exception as e:
            print(f"Error while logging in: {e}")
            return "ERROR:LOGIN FAILED"

    def navigate_to_submit_claims(self):
        wait = WebDriverWait(self.driver, 30)

        try:
            claims_dropdown = wait.until(
                EC.presence_of_element_located(
                    (By.XPATH, "//strong[contains(@class,'navtitle') and contains(text(),'Claims/Prior Authorizations')]")
                )
            )
            self.driver.execute_script("arguments[0].scrollIntoView(true);", claims_dropdown)
            self.driver.execute_script("arguments[0].click();", claims_dropdown)
            time.sleep(1)

            submit_claims_link = wait.until(
                EC.presence_of_element_located(
                    (By.XPATH, "//a[contains(@class,'navitem subnav') and contains(text(),'Submit Claims & Prior Authorizations')]")
                )
            )
            time.sleep(1)
            self.driver.execute_script("arguments[0].scrollIntoView(true);", submit_claims_link)
            self.driver.execute_script("arguments[0].click();", submit_claims_link)
            time.sleep(1)

            return "Success"
        except Exception as e:
            print(f"Error navigating to Submit Claims: {e}")
            return "ERROR:NAVIGATION_FAILED"

    def select_dental_prior_authorization(self):
        """Select 'Dental Prior Authorization' (2nd option) from the submission type dropdown."""
        wait = WebDriverWait(self.driver, 30)

        try:
            submission_dropdown = wait.until(
                EC.presence_of_element_located(
                    (By.XPATH, "//select[contains(@ng-model,'vm.newClaim.type')]")
                )
            )
            time.sleep(1)

            select = Select(submission_dropdown)

            # Try by visible text first (most reliable)
            target_texts = [
                "Dental Prior Authorization",
                "Dental Pre-Authorization",
                "Prior Authorization",
                "Pre-Authorization",
            ]
            for text in target_texts:
                try:
                    select.select_by_visible_text(text)
                    print(f"DEBUG: Selected preauth option by text: '{text}'")
                    time.sleep(1)
                    return "Success"
                except Exception:
                    continue

            # Fallback: select by index (2nd option = index 1, skipping the placeholder at index 0)
            options = select.options
            print(f"DEBUG: Available options: {[o.text for o in options]}")
            non_empty = [o for o in options if o.get_attribute("value") and o.get_attribute("value") not in ("", "string:")]
            if len(non_empty) >= 2:
                non_empty[1].click()
                print(f"DEBUG: Selected 2nd non-empty option: '{non_empty[1].text}'")
                time.sleep(1)
                return "Success"

            raise Exception("Could not find preauthorization option in dropdown")
        except Exception as e:
            print(f"Error selecting Dental Prior Authorization: {e}")
            return "ERROR:SELECTION FAILED"

    def fill_date_of_service(self):
        wait = WebDriverWait(self.driver, 30)

        try:
            raw_date = self.submissionDate if self.submissionDate else datetime.now().strftime("%Y-%m-%d")
            try:
                formatted_date = datetime.strptime(raw_date.strip(), "%Y-%m-%d").strftime("%m/%d/%Y")
            except ValueError:
                formatted_date = raw_date
            print(f"DEBUG: Using service date = '{formatted_date}'")

            date_input = wait.until(
                EC.visibility_of_element_located(
                    (By.XPATH, "//input[@name='dateOfService' and @ng-model='date' and @placeholder='mm/dd/yyyy']")
                )
            )
            time.sleep(1)

            self.driver.execute_script(f"arguments[0].value = '{formatted_date}'; arguments[0].dispatchEvent(new Event('input', {{ bubbles: true }})); arguments[0].dispatchEvent(new Event('change', {{ bubbles: true }}));", date_input)
            time.sleep(1)
            date_input.send_keys(Keys.TAB)
            time.sleep(1)

            return "Success"
        except Exception as e:
            print(f"Error filling Date of Service: {e}")
            return "ERROR:DATE_FILL_FAILED"

    def fill_member_eligibility(self):
        wait = WebDriverWait(self.driver, 30)

        try:
            print(f"DEBUG: Filling member eligibility with DOB: '{self.originalDateOfBirth}'")

            formatted_dob = ""
            if self.originalDateOfBirth:
                try:
                    dob_raw = str(self.originalDateOfBirth).strip()
                    if "T" in dob_raw:
                        dob_raw = dob_raw.split("T")[0]

                    date_obj = None
                    for fmt in ("%Y-%m-%d", "%m-%d-%Y", "%m/%d/%Y"):
                        try:
                            date_obj = datetime.strptime(dob_raw, fmt)
                            break
                        except Exception:
                            continue

                    if date_obj:
                        formatted_dob = date_obj.strftime("%m/%d/%Y")
                    print(f"DEBUG: Formatted DOB = '{formatted_dob}'")
                except Exception as e:
                    print(f"DEBUG: DOB parsing error: {e}")
                    formatted_dob = ""

            dob_input = wait.until(
                EC.visibility_of_element_located(
                    (By.XPATH, "//input[@name='dateInput' and @placeholder='mm/dd/yyyy' and @ng-model='date']")
                )
            )
            time.sleep(1)
            self.driver.execute_script(f"arguments[0].value = '{formatted_dob}'; arguments[0].dispatchEvent(new Event('input', {{ bubbles: true }})); arguments[0].dispatchEvent(new Event('change', {{ bubbles: true }}));", dob_input)
            time.sleep(1)
            dob_input.send_keys(Keys.TAB)
            time.sleep(1)

            if self.memberId:
                print(f"DEBUG: Filling member ID: '{self.memberId}'")
                member_input = wait.until(
                    EC.visibility_of_element_located(
                        (By.XPATH, "//input[@placeholder='Member Number' and @ng-model='vm.number']")
                    )
                )
                time.sleep(1)
                member_input.click()
                time.sleep(1)
                member_input.clear()
                time.sleep(1)
                member_input.send_keys(self.memberId)
                time.sleep(1)
                member_input.send_keys(Keys.TAB)
                time.sleep(1)

            print("DEBUG: Clicking SEARCH button")
            search_button = wait.until(
                EC.element_to_be_clickable(
                    (By.XPATH, "//button[@ng-click='vm.searchPrep()' and contains(text(),'SEARCH')]")
                )
            )
            search_button.click()
            time.sleep(2)

            return "Success"
        except Exception as e:
            print(f"Error filling Member Eligibility: {e}")
            return "ERROR:MEMBER_ELIGIBILITY_FAILED"

    def select_place_of_service_office(self):
        wait = WebDriverWait(self.driver, 30)

        try:
            pos_dropdown = wait.until(
                EC.presence_of_element_located(
                    (By.XPATH, "//select[contains(@ng-model,'vm.newClaim.placeOfTreatmentCode')]")
                )
            )
            time.sleep(1)

            select = Select(pos_dropdown)
            select.select_by_visible_text("Office")
            time.sleep(2)

            return "Success"
        except Exception as e:
            print(f"Error selecting Office place of service: {e}")
            return "ERROR:SELECTION FAILED"

    def select_office_summit_framingham(self):
        wait = WebDriverWait(self.driver, 30)

        try:
            office_dropdown = wait.until(
                EC.visibility_of_element_located(
                    (By.XPATH, "//select[@id='selectOffice']")
                )
            )
            time.sleep(1)

            select = Select(office_dropdown)
            options = select.options
            for opt in options:
                if opt.get_attribute("value") not in (None, "", "string:") and opt.text.strip():
                    select.select_by_index(options.index(opt))
                    print(f"DEBUG: Selected office option: '{opt.text.strip()}'")
                    break
            time.sleep(2)

            return "Success"
        except Exception as e:
            print(f"Error selecting service office: {e}")
            return "ERROR:SELECTION FAILED"

    def select_dentist(self):
        wait = WebDriverWait(self.driver, 30)

        provider_name = self.rendering_provider_name or "Mary Scannell"
        provider_npi = self.rendering_provider_npi or ""

        parts = provider_name.strip().split()
        if len(parts) >= 2:
            last_name = parts[-1]
            first_names = " ".join(parts[:-1])
            search_keyword = last_name
            display_name = f"{last_name}, {first_names} - {provider_npi}"
        else:
            search_keyword = provider_name
            display_name = f"{provider_name} - {provider_npi}"

        print(f"DEBUG: Searching dentist: keyword='{search_keyword}', expected='{display_name}'")

        try:
            dentist_input = wait.until(
                EC.visibility_of_element_located(
                    (By.XPATH, "//input[@id='inputProvider' and @placeholder='Enter a dentist']")
                )
            )
            time.sleep(1)

            dentist_input.clear()
            dentist_input.send_keys(search_keyword)
            time.sleep(3)

            option_xpath = f"//a[@ng-bind-html and contains(., '{display_name}')]"

            try:
                option = wait.until(EC.element_to_be_clickable((By.XPATH, option_xpath)))
                print("DEBUG: Found dentist option, clicking...")
                self.driver.execute_script("arguments[0].scrollIntoView(true);", option)
                time.sleep(1)
                option.click()
                time.sleep(2)
                return "Success"
            except Exception:
                fallback_selectors = [
                    f"//ul[contains(@class,'dropdown-menu')]//a[contains(., '{display_name}')]",
                    f"//ul[contains(@class,'dropdown-menu')]//li[contains(., '{display_name}')]",
                ]
                for selector in fallback_selectors:
                    try:
                        option = wait.until(EC.element_to_be_clickable((By.XPATH, selector)))
                        self.driver.execute_script("arguments[0].scrollIntoView(true);", option)
                        time.sleep(1)
                        option.click()
                        time.sleep(2)
                        return "Success"
                    except Exception:
                        continue

                print("DEBUG: Using Arrow Down + Enter fallback")
                dentist_input.send_keys(Keys.ARROW_DOWN)
                time.sleep(1)
                dentist_input.send_keys(Keys.ENTER)
                time.sleep(2)
                return "Success"

        except Exception as e:
            print(f"Error selecting dentist {display_name}: {e}")
            return "ERROR:SELECTION_FAILED"

    def click_plus_button(self):
        wait = WebDriverWait(self.driver, 30)

        try:
            print("DEBUG: Clicking plus button to add new service line")
            time.sleep(3)

            plus_button = None

            try:
                all_plus_buttons = self.driver.find_elements(By.XPATH, "//button[contains(text(), '+')]")
                for btn in all_plus_buttons:
                    ng_click = btn.get_attribute("ng-click")
                    if ng_click and "serviceLineAdd" in ng_click:
                        plus_button = btn
                        break
            except Exception as e:
                print(f"DEBUG: Error searching for + buttons: {e}")

            if not plus_button:
                selectors = [
                    "//button[@ng-click='vm.serviceLineAdd()' and contains(@class,'btn') and text()='+']",
                    "//button[contains(@class,'btn') and @ng-click='vm.serviceLineAdd()']",
                    "//button[text()='+']",
                ]
                for selector in selectors:
                    try:
                        plus_button = wait.until(EC.element_to_be_clickable((By.XPATH, selector)))
                        break
                    except Exception:
                        continue

            if not plus_button:
                plus_button = self.driver.execute_script("""
                    var buttons = document.getElementsByTagName('button');
                    for (var i = 0; i < buttons.length; i++) {
                        if (buttons[i].textContent.trim() === '+' &&
                            buttons[i].getAttribute('ng-click') &&
                            buttons[i].getAttribute('ng-click').includes('serviceLineAdd')) {
                            return buttons[i];
                        }
                    }
                    return null;
                """)
                if not plus_button:
                    raise Exception("Could not find plus button with any method")

            time.sleep(1)
            self.driver.execute_script("arguments[0].scrollIntoView(true);", plus_button)
            time.sleep(1)

            try:
                plus_button.click()
            except Exception:
                try:
                    self.driver.execute_script("arguments[0].click();", plus_button)
                except Exception:
                    from selenium.webdriver.common.action_chains import ActionChains
                    ActionChains(self.driver).move_to_element(plus_button).click().perform()

            time.sleep(2)
            print("DEBUG: Successfully clicked plus button")
            return "Success"
        except Exception as e:
            print(f"Error clicking plus button: {e}")
            return "ERROR:PLUS_BUTTON_FAILED"

    def fill_service_line(self, row_number=1, procedure_code="", tooth_number="", tooth_surface="", billed_amount=""):
        wait = WebDriverWait(self.driver, 30)

        try:
            print(f"DEBUG: Filling service line {row_number} - Procedure: {procedure_code}, Tooth: {tooth_number}, Surface: {tooth_surface}, Amount: {billed_amount}")

            if procedure_code:
                procedure_inputs = wait.until(
                    EC.presence_of_all_elements_located(
                        (By.XPATH, "//input[@ng-model='serviceLine.procedure' and @placeholder='Code']")
                    )
                )
                if len(procedure_inputs) < row_number:
                    raise Exception(f"Only {len(procedure_inputs)} procedure inputs found, need row {row_number}")

                procedure_input = procedure_inputs[row_number - 1]
                time.sleep(1)
                procedure_input.clear()
                procedure_input.send_keys(procedure_code)
                time.sleep(3)

                try:
                    dropdown = wait.until(
                        EC.visibility_of_element_located(
                            (By.XPATH, "//ul[contains(@class,'dropdown-menu') and not(contains(@class,'ng-hide'))]")
                        )
                    )
                    first_option = dropdown.find_element(By.XPATH, ".//li")
                    if first_option:
                        first_option.click()
                        time.sleep(2)
                except Exception:
                    procedure_input.send_keys(Keys.TAB)
                    time.sleep(1)

            if tooth_number:
                tooth_inputs = wait.until(
                    EC.presence_of_all_elements_located(
                        (By.XPATH, "//input[@ng-model='serviceLine.toothCode' and @placeholder='Tooth']")
                    )
                )
                if len(tooth_inputs) < row_number:
                    raise Exception(f"Only {len(tooth_inputs)} tooth inputs found, need row {row_number}")
                tooth_input = tooth_inputs[row_number - 1]
                time.sleep(1)
                tooth_input.clear()
                tooth_input.send_keys(tooth_number.upper())
                time.sleep(2)
                tooth_input.send_keys(Keys.TAB)
                time.sleep(1)

            if tooth_surface:
                surface_inputs = wait.until(
                    EC.presence_of_all_elements_located(
                        (By.XPATH, "//input[@ng-model='serviceLine.surface' and @placeholder='Surface']")
                    )
                )
                if len(surface_inputs) < row_number:
                    raise Exception(f"Only {len(surface_inputs)} surface inputs found, need row {row_number}")
                surface_input = surface_inputs[row_number - 1]
                time.sleep(1)
                surface_input.clear()
                surface_input.send_keys(tooth_surface.upper())
                time.sleep(2)
                surface_input.send_keys(Keys.TAB)
                time.sleep(1)

            if billed_amount:
                billed_amount_inputs = wait.until(
                    EC.presence_of_all_elements_located(
                        (By.XPATH, "//input[@ng-model='serviceLine.billedAmount' and @placeholder='00.00' and @type='number']")
                    )
                )
                if len(billed_amount_inputs) < row_number:
                    raise Exception(f"Only {len(billed_amount_inputs)} billed amount inputs found, need row {row_number}")
                billed_amount_input = billed_amount_inputs[row_number - 1]
                time.sleep(1)
                billed_amount_input.clear()
                billed_amount_input.send_keys(billed_amount)
                time.sleep(2)
                self.driver.execute_script("arguments[0].dispatchEvent(new Event('input', { bubbles: true })); arguments[0].dispatchEvent(new Event('change', { bubbles: true }));", billed_amount_input)
                time.sleep(1)
                billed_amount_input.send_keys(Keys.TAB)
                time.sleep(2)

            print(f"DEBUG: Service line {row_number} filled successfully")
            return "Success"
        except Exception as e:
            print(f"Error filling service line {row_number}: {e}")
            return "ERROR:SERVICE_LINE_FILL_FAILED"

    def add_file_attachment(self):
        wait = WebDriverWait(self.driver, 30)

        try:
            print("DEBUG: Adding file attachment")
            if not self.upload_files:
                print("DEBUG: No uploaded files available for attachment")
                return "ERROR:NO_FILES"

            with tempfile.TemporaryDirectory() as tmp_dir:
                for file_obj in self.upload_files:
                    if not isinstance(file_obj, dict):
                        continue

                    base64_data = file_obj.get("bufferBase64", "")
                    file_name = file_obj.get("originalname", "file.pdf")
                    if not base64_data:
                        continue

                    safe_file_name = os.path.basename(file_name)
                    if not any(safe_file_name.lower().endswith(ext) for ext in [".pdf", ".jpg", ".jpeg", ".png", ".webp"]):
                        safe_file_name += ".bin"

                    tmp_path = os.path.join(tmp_dir, safe_file_name)
                    with open(tmp_path, "wb") as f:
                        f.write(base64.b64decode(base64_data))

                    print(f"DEBUG: Uploading file: {tmp_path}")

                    injection_result = self.driver.execute_script("""
                        try {
                            var fileInput = document.getElementById('fileAttachment');
                            if (!fileInput) return 'FILE_INPUT_NOT_FOUND';
                            var scope = angular.element(fileInput).scope();
                            if (!scope || !scope.vm) return 'SCOPE_NOT_FOUND';
                            var fileAttachment = {
                                name: arguments[0],
                                type: scope.vm.fileType || 'RR',
                                data: arguments[1],
                                updatedDate: new Date()
                            };
                            if (!scope.vm.displayedArray) {
                                scope.vm.displayedArray = [];
                            }
                            scope.vm.displayedArray.push(fileAttachment);
                            scope.$apply();
                            return 'FILE_INJECTED:' + scope.vm.displayedArray.length;
                        } catch (err) {
                            return 'ERROR:' + err.message;
                        }
                    """, safe_file_name, base64_data)
                    print(f"DEBUG: Injection result = {injection_result}")

                    if not injection_result.startswith('FILE_INJECTED'):
                        print(f"DEBUG: Injection failed: {injection_result}")
                        return "ERROR:UPLOAD_FAILED"

                    wait.until(
                        EC.presence_of_element_located(
                            (By.XPATH, "//table[contains(@class, 'table-striped') and @ng-if='vm.displayedArray && vm.displayedArray.length']//tbody/tr")
                        )
                    )
                    time.sleep(1)

            return "Success"
        except Exception as e:
            print(f"Error adding file attachment: {e}")
            return "ERROR:UPLOAD_FAILED"

    def select_radiology_reports(self):
        wait = WebDriverWait(self.driver, 30)

        try:
            doc_type_dropdown = wait.until(
                EC.presence_of_element_located(
                    (By.XPATH, "//select[@ng-model='vm.fileType' and @ng-options=\"item.value as item.name for item in vm.documentTypes\"]")
                )
            )
            time.sleep(1)

            select = Select(doc_type_dropdown)
            select.select_by_visible_text("Radiology Reports")
            self.driver.execute_script(
                "arguments[0].dispatchEvent(new Event('input', { bubbles: true }));"
                "arguments[0].dispatchEvent(new Event('change', { bubbles: true }));",
                doc_type_dropdown
            )
            wait.until(lambda d: (doc_type_dropdown.get_attribute("value") or "").strip() != "")
            time.sleep(2)

            return "Success"
        except Exception as e:
            print(f"Error selecting Radiology Reports: {e}")
            return "ERROR:RADIOLOGY_REPORTS_FAILED"

    def click_submit_button(self):
        wait = WebDriverWait(self.driver, 30)

        try:
            print("DEBUG: Clicking SUBMIT button")

            submit_button = wait.until(
                EC.element_to_be_clickable(
                    (By.XPATH, "//button[@ng-click=\"vm.submitForm('File Custom Pop Up Error')\" and contains(., 'SUBMIT')]")
                )
            )

            if submit_button.get_attribute("disabled"):
                print("DEBUG: SUBMIT button is disabled")
                return "ERROR:SUBMIT_BUTTON_DISABLED"

            submit_button.click()
            print("DEBUG: SUBMIT button clicked successfully")
            time.sleep(6)
            print(f"DEBUG: Current URL after submit = {self.driver.current_url}")

            return "Success"
        except Exception as e:
            print(f"Error clicking SUBMIT button: {e}")
            return "ERROR:SUBMIT_FAILED"

    def extract_preauth_number(self):
        """Extract preauthorization number from MassHealth confirmation page."""
        wait = WebDriverWait(self.driver, 30)

        try:
            print("DEBUG: Extracting preauth number from confirmation page")
            wait.until(lambda d: d.execute_script("return document.readyState") == "complete")
            time.sleep(2)

            page_text = self.driver.find_element(By.TAG_NAME, "body").text
            print(f"DEBUG: Page text snippet: {page_text[:500]}")

            selectors = [
                "//*[contains(text(), 'assigned the number')]",
                "//p[contains(text(), 'assigned the number')]",
                "//div[contains(text(), 'assigned the number')]",
                "//span[contains(text(), 'assigned the number')]",
                "//h1[contains(text(), 'Submission Success')]/following-sibling::*",
            ]

            for selector in selectors:
                try:
                    elements = self.driver.find_elements(By.XPATH, selector)
                    for element in elements:
                        text = element.text.strip()
                        match = re.search(r'(\d{15})', text)
                        if match:
                            preauth_number = match.group(1)
                            print(f"DEBUG: Found 15-digit preauth number: {preauth_number}")
                            return preauth_number
                        match = re.search(r'(\d{9,14})', text)
                        if match:
                            preauth_number = match.group(1)
                            print(f"DEBUG: Found preauth number (9-14 digits): {preauth_number}")
                            return preauth_number
                except Exception as e:
                    print(f"DEBUG: Selector {selector} failed: {e}")
                    continue

            preauth_number = self.driver.execute_script(r"""
                var allElements = document.querySelectorAll('body, p, div, span, td, label, h1, h2, h3');
                for (var i = 0; i < allElements.length; i++) {
                    var text = allElements[i].textContent || '';
                    var match15 = text.match(/(\d{15})/);
                    if (match15) return match15[1];
                    var match9to14 = text.match(/(\d{9,14})/);
                    if (match9to14) return match9to14[1];
                }
                return null;
            """)

            if preauth_number:
                print(f"DEBUG: Found preauth number via JavaScript: {preauth_number}")
                return preauth_number

            print("DEBUG: Could not extract preauth number from page")
            return None

        except Exception as e:
            print(f"Error extracting preauth number: {e}")
            return None

    def save_confirmation_pdf(self):
        wait = WebDriverWait(self.driver, 30)

        wait.until(lambda d: d.execute_script("return document.readyState") == "complete")
        wait.until(EC.presence_of_element_located((By.TAG_NAME, "body")))
        time.sleep(2)

        print(f"DEBUG: Capturing confirmation from: {self.driver.current_url}")

        preauth_number = self.extract_preauth_number()

        safe_member = "".join(c for c in str(self.memberId) if c.isalnum() or c in "-_.")
        timestamp = time.strftime("%Y%m%d_%H%M%S")
        safe_preauth = ("_" + "".join(c for c in str(preauth_number) if c.isalnum() or c in "-_.")[:20]) if preauth_number else ""

        try:
            pdf_filename = f"preauth_confirmation_{safe_member}{safe_preauth}_{timestamp}.pdf"
            pdf_data = self.driver.execute_cdp_cmd("Page.printToPDF", {
                "printBackground": True,
                "paperWidth": 8.5,
                "paperHeight": 11,
                "marginTop": 0.4,
                "marginBottom": 0.4,
                "marginLeft": 0.4,
                "marginRight": 0.4,
            })
            pdf_bytes = base64.b64decode(pdf_data["data"])
            pdf_path = os.path.join(self.download_dir, pdf_filename)
            with open(pdf_path, "wb") as f:
                f.write(pdf_bytes)
            print(f"DEBUG: PDF saved at: {pdf_path}")
            return {
                "status": "success",
                "pdf_path": pdf_path,
                "file_type": "pdf",
                "preAuthNumber": preauth_number,
                "message": "PreAuth confirmation PDF captured successfully",
            }
        except Exception as e:
            print(f"PDF capture failed, falling back to screenshot: {e}")

        try:
            screenshot_filename = f"preauth_confirmation_{safe_member}{safe_preauth}_{timestamp}.png"
            screenshot_path = os.path.join(self.download_dir, screenshot_filename)
            total_height = self.driver.execute_script("return document.body.scrollHeight")
            self.driver.set_window_size(1280, max(total_height, 800))
            time.sleep(1)
            self.driver.save_screenshot(screenshot_path)
            print(f"DEBUG: Screenshot saved at: {screenshot_path}")
            return {
                "status": "success",
                "pdf_path": screenshot_path,
                "file_type": "screenshot",
                "preAuthNumber": preauth_number,
                "message": "Full-page screenshot captured (PDF failed)",
            }
        except Exception as ss_error:
            return {
                "status": "error",
                "message": f"PDF + Screenshot failed: {ss_error}",
            }

    def main_workflow(self, url):
        try:
            self.config_driver()
            self.driver.get(url)
            time.sleep(2)

            login_result = self.login()
            if login_result != "Success":
                return {"status": "error", "message": login_result}

            nav_result = self.navigate_to_submit_claims()
            if nav_result != "Success":
                return {"status": "error", "message": nav_result}

            # Select "Dental Prior Authorization" (2nd option) instead of "Dental Claim"
            select_result = self.select_dental_prior_authorization()
            if select_result != "Success":
                return {"status": "error", "message": select_result}

            # No Date of Service field on prior authorization form — skip it

            pos_result = self.select_place_of_service_office()
            if pos_result != "Success":
                return {"status": "error", "message": pos_result}

            office_result = self.select_office_summit_framingham()
            if office_result != "Success":
                return {"status": "error", "message": office_result}

            dentist_result = self.select_dentist()
            if dentist_result != "Success":
                return {"status": "error", "message": dentist_result}

            eligibility_result = self.fill_member_eligibility()
            if eligibility_result != "Success":
                return {"status": "error", "message": eligibility_result}

            # Fill service lines
            if not self.serviceLines:
                print("DEBUG: No service lines found, using fallback values")
                service_result = self.fill_service_line(
                    row_number=1,
                    procedure_code=self.procedureCode,
                    tooth_number=self.toothNumber,
                    tooth_surface=self.toothSurface,
                )
                if service_result != "Success":
                    return {"status": "error", "message": service_result}
            else:
                for i, service_line in enumerate(self.serviceLines):
                    row_num = i + 1
                    print(f"DEBUG: Processing service line {row_num} of {len(self.serviceLines)}")

                    if i > 0:
                        plus_result = self.click_plus_button()
                        if plus_result != "Success":
                            return {"status": "error", "message": plus_result}

                    service_result = self.fill_service_line(
                        row_number=row_num,
                        procedure_code=service_line.get("procedureCode", ""),
                        tooth_number=service_line.get("toothNumber", ""),
                        tooth_surface=service_line.get("toothSurface", ""),
                        billed_amount=service_line.get("totalBilled", ""),
                    )
                    if service_result != "Success":
                        return {"status": "error", "message": f"Service line {row_num} failed: {service_result}"}

            radiology_result = self.select_radiology_reports()
            if radiology_result != "Success":
                return {"status": "error", "message": radiology_result}

            if self.upload_files:
                file_result = self.add_file_attachment()
                if file_result != "Success":
                    return {"status": "error", "message": file_result}
            else:
                print("DEBUG: No files to attach, skipping attachment step")

            submit_result = self.click_submit_button()
            if submit_result != "Success":
                return {"status": "error", "message": submit_result}

            pdf_result = self.save_confirmation_pdf()
            if pdf_result.get("status") == "error":
                return {"status": "error", "message": pdf_result.get("message")}

            time.sleep(3)

            return {
                "status": "success",
                "message": "PreAuth automation completed successfully.",
                "pdf_path": pdf_result.get("pdf_path"),
                "file_type": pdf_result.get("file_type"),
                "preAuthNumber": pdf_result.get("preAuthNumber"),
            }
        except Exception as e:
            print(f"PreAuth automation error: {e}")
            return {"status": "error", "message": str(e)}
        finally:
            if self.driver:
                self.driver.quit()
