import io
import re
import base64
from PIL import Image
import fitz  # PyMuPDF

def extract_text_from_pdf(pdf_path):
    text = ""
    with fitz.open(pdf_path) as pdf:
        for page in pdf:
            text += page.get_text()
    return text

def extract_addresses(text):
    sections = re.split(r"Present Address|Permanent Address", text)
    
    if len(sections) < 3:
        return None, None

    present_address_raw = sections[1].strip()
    permanent_address_raw = sections[2].strip()

    def parse_components(raw):
        lines = raw.split("\n")
        components = {
            "division": lines[lines.index("Division") + 1] if "Division" in lines else "",
            "district": lines[lines.index("District") + 1] if "District" in lines else "",
            "rmo": lines[lines.index("RMO") + 1] if "RMO" in lines else "",
            "upazila": lines[lines.index("Upozila") + 1] if "Upozila" in lines else "",
            "union": lines[lines.index("Union/Ward") + 1] if "Union/Ward" in lines else "",
            "mouza": lines[lines.index("Mouza/Moholla") + 1] if "Mouza/Moholla" in lines else "",
            "village": lines[lines.index("Village/Road") + 1] if "Village/Road" in lines else "",
            "home": lines[lines.index("Post Office") - 1] if "Post Office" in lines else "",
            "post_office": lines[lines.index("Post Office") + 1] if "Post Office" in lines else "",
            "postal_code": lines[lines.index("Postal Code") + 1] if "Postal Code" in lines else "",
            "region": lines[lines.index("Region") + 1] if "Region" in lines else ""
        }
        
        if "Village/Road" in lines:
            village_index = lines.index("Village/Road") + 1
            if village_index + 1 < len(lines) and lines[village_index] == "Additional":
                components["village"] = lines[village_index + 2]
                if "Home" in lines[village_index + 4] and "Additional" not in lines[village_index + 4]:
                    components["village"] += f" {lines[village_index + 3]}"


        return components

    present_components = parse_components(present_address_raw)
    permanent_components = parse_components(permanent_address_raw)

    present_address = (
        f"বাসা/হোল্ডিং: {present_components['home']}, "
        f"গ্রাম/রাস্তা: {present_components['village']}, "
        f"ডাকঘর: {present_components['post_office']} - {present_components['postal_code']}, "
        f"{present_components['upazila']}, "
        f"{present_components['district']}"
    )

    permanent_address = (
        f"বাসা/হোল্ডিং: {permanent_components['home']}, "
        f"গ্রাম/রাস্তা: {permanent_components['village']}, "
        f"ডাকঘর: {permanent_components['post_office']} - {permanent_components['postal_code']}, "
        f"{permanent_components['upazila']}, "
        f"{permanent_components['district']}"
    )
    
    return present_address, permanent_address

def extract_images_from_pdf(pdf_path):
    photo = None
    sign = None
    image_count = 0

    with fitz.open(pdf_path) as pdf:
        for page_num in range(len(pdf)):
            for img_index, img in enumerate(pdf.get_page_images(page_num)):
                if image_count >= 2:
                    break

                xref = img[0]
                base_image = pdf.extract_image(xref)
                image_bytes = base_image["image"]

                try:
                    if 'smask' in base_image:
                        smask_xref = base_image['smask']
                        smask_image = pdf.extract_image(smask_xref)
                        smask_bytes = smask_image['image']

                        smask_image_obj = Image.open(io.BytesIO(smask_bytes))
                        smask_image_obj = smask_image_obj.convert("L")

                        with Image.open(io.BytesIO(image_bytes)) as image:
                            image = image.convert("RGBA")
                            image.putalpha(smask_image_obj)
                            buffer = io.BytesIO()
                            image.save(buffer, format="PNG")
                            encoded_image = base64.b64encode(buffer.getvalue()).decode()
                    else:
                        with Image.open(io.BytesIO(image_bytes)) as image:
                            image = image.convert("RGB")
                            buffer = io.BytesIO()
                            image.save(buffer, format="PNG")
                            encoded_image = base64.b64encode(buffer.getvalue()).decode()

                    if image_count == 0:
                        photo = f"data:image/png;base64,{encoded_image}"
                    elif image_count == 1:
                        sign = f"data:image/png;base64,{encoded_image}"

                    image_count += 1
                except Exception as e:
                    if str(e) == "bad xref":
                        image = Image.open(io.BytesIO(image_bytes))
                        buffer = io.BytesIO()
                        image.save(buffer, format="PNG")
                        encoded_image = base64.b64encode(buffer.getvalue()).decode()
                        
                        if image_count == 0:
                            photo = f"data:image/png;base64,{encoded_image}"
                        elif image_count == 1:
                            sign = f"data:image/png;base64,{encoded_image}"

                        image_count += 1
                    else:
                        print(e)

            if image_count >= 2:
                break

    return photo, sign


def extract_key_value_pairs(text):
    patterns = {
        "nid_number": r"National ID\n(.+?)\n",
        "pin": r"Pin\n(.+?)\n",
        "name_bn": r"Name\(Bangla\)\n(.+?)\n",
        "name_en": r"Name\(English\)\n(.+?)\n",
        "date_of_birth": r"Date of Birth\n(.+?)\n",
        "date_of_place": r"Birth Place\n(.+?)\n",
        "father_name": r"Father Name\n(.+?)\n",
        "mother_name": r"Mother Name\n(.+?)\n",
        "blood_group": r"Blood Group\n(.+?)\n(?:TIN|$)",
    }

    extracted_data = {}
    for key, pattern in patterns.items():
        match = re.search(pattern, text)
        extracted_data[key] = match.group(1).strip() if match else ""
    return extracted_data

def process_pdf(pdf_path):
    extracted_text = extract_text_from_pdf(pdf_path)

    photo, sign = extract_images_from_pdf(pdf_path)

    extracted_data = extract_key_value_pairs(extracted_text)
    present_address, permanent_address = extract_addresses(extracted_text)

    extracted_data["present_address"] = present_address
    extracted_data["permanent_address"] = permanent_address
    extracted_data["photo"] = photo
    extracted_data["sign"] = sign

    return extracted_data
