import os
import pandas as pd
from docx import Document
from docx.shared import RGBColor
from docxcompose.composer import Composer
import streamlit as st
import tempfile


def get_cell_value(row, col_names):
    """
    Retrieve first non-empty, non-NaN value from a list of possible column names
    in a row. Returns 'NA' if no valid value found.
    col_names: list of column name strings to try in order.
    """
    for col_name in col_names:
        if col_name in row.index:
            val = row[col_name]
            if pd.notna(val):
                val_str = str(val).strip()
                if val_str != "":
                    return val_str
    return "NA"


def populate_docx_template(excel_file, template_files, temp_dir, selected_publishable_indices, selected_confidential_indices):
    """
    Generate one full Word document per selected Excel row from the template,
    filling all relevant cells in the table while preserving formatting.
    """
    df = pd.read_excel(excel_file)
    df.columns = df.columns.str.strip()

    generated_files = []

    # Create numbering maps separately
    publishable_numbers = {idx: num + 1 for num, idx in enumerate(selected_publishable_indices)}
    confidential_numbers = {idx: num + 1 for num, idx in enumerate(selected_confidential_indices)}

    # Combine selections keeping order: publishable first then confidential
    all_selected = selected_publishable_indices + selected_confidential_indices

    for idx, row_idx in enumerate(all_selected):
        row = df.iloc[row_idx]

        conf_status = str(row.get('Confidential / Publishable', '')).lower()
        is_confidential = (conf_status == 'yes' or 'confidential' in conf_status)

        # Numbering for current row
        if is_confidential:
            number = confidential_numbers.get(row_idx, 0)
        else:
            number = publishable_numbers.get(row_idx, 0)

        # Select template file
        template_key = 'confidential' if is_confidential else 'publishable'
        doc = Document(template_files[template_key])

        if not doc.tables:
            st.error("Template file appears to have no tables.")
            return []

        table = doc.tables[0]

        # Use helper to get cell values or 'NA' if missing/empty
        serial_number = get_cell_value(row, ['S No.'])
        client_name = get_cell_value(row, ['Client Name'])
        matter_overview = get_cell_value(row, ['Matter/Case Overview'])

        description = get_cell_value(row, ['Description  (in 500 words)', 'Description (in 500 words)', 'Description'])
        role_of_sa = get_cell_value(row, ['Role of S&A', 'Role of SA', 'Role'])
        significance = get_cell_value(row, ['The significance, impact and outcome of the case', 'Significance', 'Impact'])

        value = get_cell_value(row, ['Value'])
        cross_border = get_cell_value(row, ['Is this a cross-border matter? If yes, please indicate the jurisdictions involved.'])
        lead_partners = get_cell_value(row, ['Lead partners'])
        team_partners = get_cell_value(row, ['Team Members'])
        other_firms = get_cell_value(row, ['Other Firms/counsels Involved'])

        current_status = row.get('Current Status (ongoing / completed )')
        dates = str(current_status).strip() if pd.notna(current_status) and str(current_status).strip() != "" else "NA"

        try:
            # Fill client name cell (2,0)
            table.cell(2, 0).text = client_name
            if is_confidential:
                for paragraph in table.cell(2, 0).paragraphs:
                    for run in paragraph.runs:
                        run.font.color.rgb = RGBColor(255, 0, 0)

            # Matter overview cell (4,0)
            overview_cell = table.cell(4, 0)
            # Clear existing paragraphs
            overview_cell.text = ""

            # Overview header
            overview_header = overview_cell.add_paragraph()
            header_run = overview_header.add_run("Overview")
            header_run.bold = True
            if is_confidential:
                header_run.font.color.rgb = RGBColor(255, 0, 0)

            # Description paragraph
            desc_para = overview_cell.add_paragraph()
            desc_run = desc_para.add_run(description)
            if is_confidential:
                desc_run.font.color.rgb = RGBColor(255, 0, 0)

            # Role header
            role_header = overview_cell.add_paragraph()
            role_header.add_run("\n")  # linebreak
            role_run = role_header.add_run("Role of S&A")
            role_run.bold = True
            if is_confidential:
                role_run.font.color.rgb = RGBColor(255, 0, 0)

            # Role text
            role_para = overview_cell.add_paragraph()
            role_text_run = role_para.add_run(role_of_sa)
            if is_confidential:
                role_text_run.font.color.rgb = RGBColor(255, 0, 0)

            # Significance header
            sig_header = overview_cell.add_paragraph()
            sig_header.add_run("\n")
            sig_run = sig_header.add_run("Significance & Impact of the Matter")
            sig_run.bold = True
            if is_confidential:
                sig_run.font.color.rgb = RGBColor(255, 0, 0)

            # Significance text
            sig_para = overview_cell.add_paragraph()
            sig_text_run = sig_para.add_run(significance)
            if is_confidential:
                sig_text_run.font.color.rgb = RGBColor(255, 0, 0)

            # Remaining standard cells
            table.cell(5, 1).text = value
            table.cell(20, 1).text = other_firms
            table.cell(8, 1).text = cross_border
            table.cell(12, 0).text = lead_partners
            table.cell(12, 2).text = "S&A law offices"
            table.cell(16, 0).text = team_partners
            table.cell(16, 2).text = "S&A law offices"
            table.cell(22, 3).text = dates

            # Apply red font color if confidential to other cells
            if is_confidential:
                for cell_pos in [(5, 1), (8, 1), (12, 0), (12, 2), (16, 0), (16, 2), (20, 1), (22, 3)]:
                    cell = table.cell(cell_pos[0], cell_pos[1])
                    for paragraph in cell.paragraphs:
                        for run in paragraph.runs:
                            run.font.color.rgb = RGBColor(255, 0, 0)

        except IndexError:
            st.error("Template table structure mismatch. Please check your template cell indices.")
            return []
        except Exception as e:
            st.error(f"Error processing document: {str(e)}")
            return []

        # Clean filename (replace spaces)
        safe_client_name = "".join(c for c in client_name if c.isalnum() or c in (" ", "_")).rstrip()
        safe_client_name = safe_client_name.replace(" ", "_") or "client"

        prefix = "CONF" if is_confidential else "PUB"
        outpath = os.path.join(temp_dir, f"{idx:03d}_{prefix}_{safe_client_name}.docx")
        doc.save(outpath)
        generated_files.append(outpath)

    return generated_files


def combine_documents_with_watermark(file_paths, output_file):
    """
    Combine multiple .docx files preserving full formatting like tables, headers, footers, watermarks.
    """
    if not file_paths:
        return None

    combined_doc = Document(file_paths[0])
    composer = Composer(combined_doc)


    for fp in file_paths[1:]:
        doc = Document(fp)
        composer.append(doc)

    composer.save(output_file)
    return output_file


def app():
    st.title("Legal 500 Document Generator")

    # Hardcoded template paths (change these to your actual template locations)
    publishable_template_path = r"C:\Users\Administrator\Desktop\Legal 500.doc"
    confidential_template_path = r"C:\Users\Administrator\Desktop\Legal 500..doc"

    # Upload Excel file with data
    excel_file = st.file_uploader("Upload Excel file with data", type=["xlsx", "xls"])

    if excel_file is not None:
        df = pd.read_excel(excel_file)
        df.columns = df.columns.str.strip()

        st.subheader("Select Records to Include")

        tab1, tab2 = st.tabs(["Publishable", "Confidential"])
        selected_publishable_indices = []
        selected_confidential_indices = []

        with tab1:
            st.write("Select publishable records (marked as 'No' or 'Publishable'):")
            publishable_rows = []
            for i, row in df.iterrows():
                pval = str(row.get('Confidential / Publishable', '')).lower()
                if pd.notna(pval) and (pval == 'no' or 'publishable' in pval):
                    publishable_rows.append(i)

            for i in publishable_rows:
                row = df.iloc[i]
                serial_number = get_cell_value(row, ['S No.'])
                client_name = get_cell_value(row, ['Client Name'])
                value = get_cell_value(row, ['Value'])

                label = f"{serial_number} - {client_name} - ({value})"
                if st.checkbox(label, key=f"pub_{i}"):
                    if i not in selected_publishable_indices:
                        selected_publishable_indices.append(i)

        with tab2:
            st.write("Select confidential records (marked as 'Yes', 'Confidential', or 'Maintain Confidentiality'):")
            confidential_rows = []
            for i, row in df.iterrows():
                pval = str(row.get('Confidential / Publishable', '')).lower()
                if pd.notna(pval) and ('yes' == pval or 'confidential' in pval or 'maintain confidentiality' in pval):
                    confidential_rows.append(i)

            for i in confidential_rows:
                row = df.iloc[i]
                serial_number = get_cell_value(row, ['S No.'])
                client_name = get_cell_value(row, ['Client Name'])
                value = get_cell_value(row, ['Value'])

                label = f"{serial_number} - {client_name} - ({value})"
                if st.checkbox(label, key=f"conf_{i}"):
                    if i not in selected_confidential_indices:
                        selected_confidential_indices.append(i)

        if st.button("Generate Documents"):
            if selected_publishable_indices or selected_confidential_indices:
                with tempfile.TemporaryDirectory() as temp_dir:
                    # Validate templates exist
                    if not os.path.exists(publishable_template_path):
                        st.error(f"Publishable template file not found: {publishable_template_path}")
                        return

                    if not os.path.exists(confidential_template_path):
                        st.error(f"Confidential template file not found: {confidential_template_path}")
                        return

                    template_files = {
                        'publishable': publishable_template_path,
                        'confidential': confidential_template_path
                    }

                    progress_bar = st.progress(0)
                    status = st.empty()

                    status.text("Populating templates per selected record...")

                    with st.spinner("Processing..."):
                        generated_files = populate_docx_template(
                            excel_file,
                            template_files,
                            temp_dir,
                            selected_publishable_indices,
                            selected_confidential_indices
                        )

                    progress_bar.progress(50)

                    if not generated_files:
                        st.error("No documents generated. Check template and data.")
                        return

                    status.text("Combining generated documents (preserving watermark and formatting)...")
                    combined_path = os.path.join(temp_dir, "Legal_500_Combined.docx")
                    combine_documents_with_watermark(generated_files, combined_path)
                    progress_bar.progress(100)

                    if os.path.exists(combined_path):
                        status.text("Documents generated successfully!")
                        with open(combined_path, "rb") as f:
                            st.download_button(
                                label="Download Combined Document",
                                data=f,
                                file_name="Legal_500_Combined.docx",
                                mime="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                            )
                    else:
                        st.error("Failed to generate combined document.")
            else:
                st.warning("Select at least one record to generate documents.")


if __name__ == "__main__":
    app()  i want to run this separtely without the main file ....also in combined doc before bpth publishble nd confidential a want to attach a doc whose path i will replace in the code ...but combine such that the format of doc doesnot chngs also like cuurent code it must include watermarks in footer too