"""
main_orchestrator.py

MASTER ORCHESTRATOR
===================

Pipeline:

PDF
 ↓
DL Pipeline
 ↓
Confidence Score
 ↓
if score < threshold:
    DLM Engine
 ↓
Merge Results
 ↓
Final Output

This file should remain CLEAN.
All heavy logic stays inside:
- dl_pipeline.py
- extract_land.py
"""

import json
import time
from pathlib import Path

# ==============================
# IMPORT DL PIPELINE
# ==============================

from dl_pipeline import (
    extract_land_record_dl,
    merge_results,
)

# ==============================
# IMPORT DLM ENGINE
# ==============================

from extract_land import (
    extract_land_record as extract_land_record_dlm
)

# ==============================
# CONFIG
# ==============================

DL_THRESHOLD = 70

ENABLE_DLM_FALLBACK = True

ENABLE_LOGS = True

# ==============================
# LOGGER
# ==============================

def log(msg):

    if ENABLE_LOGS:
        print(msg)

# ==============================
# FIELD VALIDATION
# ==============================

def validate_result(result):

    issues = []

    # Required headers
    required_headers = [
        "jl_no",
        "daag_no",
        "mouza",
    ]

    for field in required_headers:

        if not result.get(field):
            issues.append(f"missing_{field}")

    # Entries
    entries = result.get("khatian_entries", [])

    if len(entries) == 0:
        issues.append("no_entries")

    # Validate entries
    for idx, e in enumerate(entries):

        if not e.get("khatian_no"):
            issues.append(f"entry_{idx}_missing_khatian")

        if not e.get("owner_name"):
            issues.append(f"entry_{idx}_missing_owner")

    return issues

# ==============================
# METADATA GENERATOR
# ==============================

def build_metadata(
    pdf_path,
    dl_score,
    pipeline_used,
    issues,
    processing_time
):

    return {
        "source_file": Path(pdf_path).name,
        "pipeline_used": pipeline_used,
        "dl_confidence": dl_score,
        "issues": issues,
        "processing_time_seconds": round(processing_time, 2),
    }

# ==============================
# MAIN ORCHESTRATOR
# ==============================

def process_land_record(pdf_path):

    start_time = time.time()

    log("\n==============================")
    log("STARTING LAND RECORD PIPELINE")
    log("==============================")

    # ==============================
    # STEP 1 — RUN DL PIPELINE
    # ==============================

    log("\n[1] Running DL pipeline...")

    dl_result = extract_land_record_dl(pdf_path)

    dl_score = dl_result.get("dl_confidence", 0)

    log(f"DL Confidence Score: {dl_score}")

    # ==============================
    # STEP 2 — VALIDATE DL OUTPUT
    # ==============================

    issues = validate_result(dl_result)

    if issues:
        log(f"Validation Issues: {issues}")

    # ==============================
    # STEP 3 — HIGH CONFIDENCE
    # ==============================

    if dl_score >= DL_THRESHOLD:

        log("\nDL result accepted.")

        pipeline_used = "DL_ONLY"

        total_time = time.time() - start_time

        metadata = build_metadata(
            pdf_path=pdf_path,
            dl_score=dl_score,
            pipeline_used=pipeline_used,
            issues=issues,
            processing_time=total_time
        )

        final_result = {
            **dl_result,
            "metadata": metadata
        }

        return final_result

    # ==============================
    # STEP 4 — FALLBACK TO DLM
    # ==============================

    if ENABLE_DLM_FALLBACK:

        log("\nDL confidence LOW.")
        log("Running DLM fallback engine...")

        dlm_result = extract_land_record_dlm(pdf_path)

        # ==============================
        # STEP 5 — MERGE RESULTS
        # ==============================

        log("\nMerging DL + DLM results...")

        merged_result = merge_results(
            dl_result,
            dlm_result
        )

        pipeline_used = "DL_PLUS_DLM"

        total_time = time.time() - start_time

        metadata = build_metadata(
            pdf_path=pdf_path,
            dl_score=dl_score,
            pipeline_used=pipeline_used,
            issues=issues,
            processing_time=total_time
        )

        merged_result["metadata"] = metadata

        log("\nPipeline completed successfully.")

        return merged_result

    # ==============================
    # STEP 6 — DL ONLY (NO FALLBACK)
    # ==============================

    log("\nDLM fallback disabled.")

    pipeline_used = "DL_ONLY_LOW_CONFIDENCE"

    total_time = time.time() - start_time

    metadata = build_metadata(
        pdf_path=pdf_path,
        dl_score=dl_score,
        pipeline_used=pipeline_used,
        issues=issues,
        processing_time=total_time
    )

    dl_result["metadata"] = metadata

    return dl_result

# ==============================
# BATCH PROCESSING
# ==============================

def process_multiple_pdfs(pdf_files):

    results = []

    total = len(pdf_files)

    log(f"\nProcessing {total} PDFs...\n")

    for idx, pdf_path in enumerate(pdf_files, start=1):

        log(f"\n===================================")
        log(f"FILE {idx}/{total}")
        log(f"{pdf_path}")
        log("===================================")

        try:

            result = process_land_record(pdf_path)

            results.append({
                "file": pdf_path,
                "success": True,
                "result": result
            })

        except Exception as e:

            results.append({
                "file": pdf_path,
                "success": False,
                "error": str(e)
            })

            log(f"ERROR: {str(e)}")

    return results

# ==============================
# SAVE JSON
# ==============================

def save_result_json(result, output_path):

    with open(output_path, "w", encoding="utf-8") as f:

        json.dump(
            result,
            f,
            ensure_ascii=False,
            indent=2
        )

    log(f"\nSaved JSON: {output_path}")

# ==============================
# CLI
# ==============================

if __name__ == "__main__":

    import sys
    import glob

    if len(sys.argv) < 2:

        print("\nUsage:")
        print("python main_orchestrator.py file.pdf")
        print("python main_orchestrator.py *.pdf")

        exit()

    targets = sys.argv[1:]

    pdf_files = []

    # Expand wildcard patterns
    for t in targets:

        expanded = glob.glob(t)

        if expanded:
            pdf_files.extend(expanded)
        else:
            pdf_files.append(t)

    # Remove duplicates
    pdf_files = list(set(pdf_files))

    # ==============================
    # SINGLE FILE
    # ==============================

    if len(pdf_files) == 1:

        pdf_path = pdf_files[0]

        result = process_land_record(pdf_path)

        print("\n==============================")
        print("FINAL RESULT")
        print("==============================\n")

        print(
            json.dumps(
                result,
                ensure_ascii=False,
                indent=2
            )
        )

        # Auto-save
        output_json = (
            Path(pdf_path).stem
            + "_result.json"
        )

        save_result_json(
            result,
            output_json
        )

    # ==============================
    # MULTIPLE FILES
    # ==============================

    else:

        results = process_multiple_pdfs(pdf_files)

        print("\n==============================")
        print("BATCH PROCESSING COMPLETE")
        print("==============================\n")

        print(
            json.dumps(
                results,
                ensure_ascii=False,
                indent=2
            )
        )

        save_result_json(
            results,
            "batch_results.json"
        )