import sys
import csv
from pathlib import Path

# Add parent directory to Python path so we can import helpers
parent_dir = Path(__file__).parent.parent
sys.path.insert(0, str(parent_dir))

from helpers.config import get_db_connection

CSV_PATH = parent_dir / "loaders" / "Contract_Update.csv"


def check_contract_number_format(cur):
    """Show sample contract numbers from DB to confirm expected format."""
    cur.execute("SELECT number FROM purchase_purchase ORDER BY id LIMIT 3")
    pur_samples = [r[0] for r in cur.fetchall()]
    cur.execute("SELECT number FROM sale_sale ORDER BY id LIMIT 3")
    sale_samples = [r[0] for r in cur.fetchall()]
    print(f"  Sample purchase numbers : {pur_samples}")
    print(f"  Sample sale numbers     : {sale_samples}")
    print()


def update_estimated_bl_dates(dry_run=False):
    conn = get_db_connection()
    cur = conn.cursor()

    print("=== Contract BL Date Update ===")
    print(f"CSV  : {CSV_PATH}")
    print(f"Mode : {'DRY RUN (no changes will be saved)' if dry_run else 'LIVE UPDATE'}\n")

    print("DB contract number format check:")
    check_contract_number_format(cur)

    # Read CSV
    rows = []
    with open(CSV_PATH, newline="", encoding="utf-8") as f:
        reader = csv.DictReader(f)
        for row in reader:
            contract_type = row["ContractType"].strip().upper()
            contract_number = row["ContractNumber"].strip()
            bl_date = row["EstimatedBlDate"].strip()
            if contract_type and contract_number and bl_date:
                rows.append((contract_type, contract_number, bl_date))

    print(f"Rows loaded from CSV: {len(rows)}\n")

    updated_count = 0
    skipped_count = 0
    not_found_count = 0

    for contract_type, contract_number, bl_date in rows:

        if contract_type == "P":
            # Resolve purchase_line IDs for this purchase number
            # Try both raw number (e.g. "2086") and P- prefix (e.g. "P-2086")
            cur.execute(
                """
                SELECT pl.id
                FROM purchase_line pl
                JOIN purchase_purchase pp ON pp.id = pl.purchase
                WHERE pp.number IN (%s, %s)
                  AND pl.type = 'line'
                ORDER BY pl.id
                """,
                (contract_number, f"P-{contract_number}"),
            )
            line_ids = [r[0] for r in cur.fetchall()]

            if not line_ids:
                print(f"  [NOT FOUND] Purchase {contract_number} — no matching purchase_line rows")
                not_found_count += 1
                continue

            # Update pricing_estimated rows linked to those lines with trigger = bldate
            cur.execute(
                """
                UPDATE pricing_estimated
                SET    estimated_date = %s,
                       write_date     = NOW(),
                       write_uid      = 1
                WHERE  line    = ANY(%s)
                  AND  trigger = 'bldate'
                RETURNING id, line, estimated_date
                """,
                (bl_date, line_ids),
            )
            updated_rows = cur.fetchall()

            if updated_rows:
                for pe_id, line_id, new_date in updated_rows:
                    print(
                        f"  [{'DRY' if dry_run else 'OK '}] Purchase {contract_number}"
                        f" | purchase_line={line_id} | pricing_estimated.id={pe_id}"
                        f" | estimated_date -> {new_date}"
                    )
                updated_count += len(updated_rows)
            else:
                print(
                    f"  [SKIP] Purchase {contract_number} — lines {line_ids} found"
                    f" but no pricing_estimated row with trigger='bldate'"
                )
                skipped_count += 1

        elif contract_type == "S":
            # Resolve sale_line IDs for this sale number
            # Try both raw number (e.g. "2086") and S- prefix (e.g. "S-2086")
            cur.execute(
                """
                SELECT sl.id
                FROM sale_line sl
                JOIN sale_sale ss ON ss.id = sl.sale
                WHERE ss.number IN (%s, %s)
                  AND sl.type = 'line'
                ORDER BY sl.id
                """,
                (contract_number, f"S-{contract_number}"),
            )
            line_ids = [r[0] for r in cur.fetchall()]

            if not line_ids:
                print(f"  [NOT FOUND] Sale {contract_number} — no matching sale_line rows")
                not_found_count += 1
                continue

            # Update pricing_estimated rows linked to those sale lines with trigger = bldate
            cur.execute(
                """
                UPDATE pricing_estimated
                SET    estimated_date = %s,
                       write_date     = NOW(),
                       write_uid      = 1
                WHERE  sale_line = ANY(%s)
                  AND  trigger   = 'bldate'
                RETURNING id, sale_line, estimated_date
                """,
                (bl_date, line_ids),
            )
            updated_rows = cur.fetchall()

            if updated_rows:
                for pe_id, sale_line_id, new_date in updated_rows:
                    print(
                        f"  [{'DRY' if dry_run else 'OK '}] Sale {contract_number}"
                        f" | sale_line={sale_line_id} | pricing_estimated.id={pe_id}"
                        f" | estimated_date -> {new_date}"
                    )
                updated_count += len(updated_rows)
            else:
                print(
                    f"  [SKIP] Sale {contract_number} — lines {line_ids} found"
                    f" but no pricing_estimated row with trigger='bldate'"
                )
                skipped_count += 1

        else:
            print(f"  [WARN] Unknown ContractType '{contract_type}' for contract {contract_number} — skipped")
            skipped_count += 1

    print("\n--- Summary ---")
    print(f"  Updated  : {updated_count} pricing_estimated rows")
    print(f"  Skipped  : {skipped_count} contracts (no bldate row in pricing_estimated)")
    print(f"  Not found: {not_found_count} contracts (contract number not in DB)")

    if dry_run:
        conn.rollback()
        print("\nDry run — all changes rolled back, nothing saved.")
    else:
        conn.commit()
        print("\nAll changes committed to database.")

    cur.close()
    conn.close()


if __name__ == "__main__":
    dry_run = "--dry-run" in sys.argv
    update_estimated_bl_dates(dry_run=dry_run)
