"""Dry Run orchestration for BestWeb provisioning: OLT + MikroTik."""
import asyncio
import json
from sqlalchemy import select
from app.core.database import AsyncSessionLocal
from app.models.models import Customer, OLTDevice, MikrotikDevice, DeviceCredential
from app.core.cdata_executor import CDataProvisionResult
from app.core.mikrotik import MockMikrotikAdapter
from app.core.customer_identity import decrypt_pppoe_password

async def dry_run_provisioning(customer_id: int):
    print(f"--- START DRY RUN FOR CUSTOMER ID: {customer_id} ---")
    async with AsyncSessionLocal() as db:
        # 1. Fetch Customer
        customer = (await db.execute(select(Customer).where(Customer.id == customer_id))).scalar_one_or_none()
        if not customer:
            print(f"Error: Customer {customer_id} not found.")
            return

        print(f"Target Customer: {customer.name} ({customer.customer_code})")
        print(f"Target OLT: {customer.olt_vendor} {customer.olt_model} (Port: {customer.olt_port}, ONU ID: {customer.onu_id}, SN: {customer.ont_sn})")
        print(f"Target MikroTik User: {customer.pppoe_username}")

        # 2. Check OLT Readiness (Dry Run logic)
        olt = (await db.execute(select(OLTDevice).where(OLTDevice.id == customer.olt_device_id))).scalar_one_or_none()
        if not olt:
            print("Error: OLT Device not linked to customer.")
            return

        cred_olt = (await db.execute(select(DeviceCredential).where(DeviceCredential.id == olt.credential_id))).scalar_one_or_none()
        if not cred_olt:
            print("Error: OLT Credential not found.")
            return
        
        print(f"\n[OLT DRY RUN] Command sequence for {olt.name}:")
        print(f"  > enable")
        print(f"  > config")
        print(f"  > interface gpon 0/0")
        print(f"  > ont add {customer.olt_port.split('/')[-1]} {customer.onu_id} sn-auth {customer.ont_sn}")
        print("  [SIMULATED SUCCESS]")

        # 3. Check MikroTik Readiness (Dry Run logic)
        mk = (await db.execute(select(MikrotikDevice).where(MikrotikDevice.id == customer.mikrotik_device_id))).scalar_one_or_none()
        if not mk:
            print("Error: MikroTik Device not linked to customer.")
            return
        
        mock_mk = MockMikrotikAdapter()
        pppoe_pass = decrypt_pppoe_password(customer.pppoe_password)
        
        print(f"\n[MIKROTIK DRY RUN] API call for {mk.name}:")
        print(f"  Action: upsert_pppoe_secret")
        print(f"  User: {customer.pppoe_username}")
        print(f"  Profile: {customer.service_profile or 'default'}")
        
        try:
            mock_mk.upsert_pppoe_secret(customer.pppoe_username, pppoe_pass, customer.service_profile)
            print("  [SIMULATED SUCCESS]")
        except Exception as e:
            print(f"  [SIMULATED FAILURE]: {e}")
            return

        # 4. Final Verdict
        print("\n--- DRY RUN RESULT: SUCCESS ---")
        print("Workflow is safe. No hardware was contacted.")
        print("Ready for LIVE provisioning.")

if __name__ == "__main__":
    from dotenv import load_dotenv
    load_dotenv()
    asyncio.run(dry_run_provisioning(29))
