import asyncio
from datetime import datetime
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession
from app.database import Base
from app.models.lender import Lender, Product
from app.models.configuration import (
    InterestConfiguration, AllocationConfiguration, CollectionConfiguration,
    NpaConfiguration, ForeclosureConfiguration, ChargeMaster, ChargeConfiguration,
    WaiveOffConfiguration, RpsConfiguration
)

async def bootstrap():
    print("==================================================")
    print("BOOTSTRAPING DEVELOPMENT SQLITE DATABASE (lms.db)")
    print("==================================================")

    # 1. Setup local sqlite database
    engine = create_async_engine("sqlite+aiosqlite:///lms.db", echo=False)
    async_session = async_sessionmaker(engine, expire_on_commit=False, class_=AsyncSession)

    async with engine.begin() as conn:
        # Create all tables dynamically
        await conn.run_sync(Base.metadata.drop_all)
        await conn.run_sync(Base.metadata.create_all)
        print("[DB] Local SQLite tables created successfully in lms.db.")

    async with async_session() as db:
        # 2. Seed Lender (Tenant) & Product
        lender = Lender(name="Credit Fair India", code="CF_INDIA")
        db.add(lender)
        await db.flush()
        
        product = Product(lender_id=lender.id, name="Solar Installation Retail Loan", code="SOLAR_T1")
        db.add(product)
        await db.flush()
        
        # Add another product for diversity
        product2 = Product(lender_id=lender.id, name="Electric Vehicle Two-Wheeler Loan", code="EV_BIKE_T2")
        db.add(product2)
        await db.flush()
        
        print(f"[Seed] Created Lender: {lender.name} ({lender.code})")
        print(f"[Seed] Created Product 1: {product.name}")
        print(f"[Seed] Created Product 2: {product2.name}")

        # 3. Create Configurations for Product 1 (Solar Installment)
        interest_config = InterestConfiguration(
            product_id=product.id,
            calculation_basis="ACTUAL_365",
            emi_type="REDUCING",
            repayment_frequency="MONTHLY",
            grace_period_days=3,
            version=1,
            effective_from=datetime.utcnow(),
            is_active=True
        )
        db.add(interest_config)

        allocation_config = AllocationConfiguration(
            product_id=product.id,
            sequence_type="REGULAR_EMI",
            priority_sequence=["interest", "principal", "charges"],
            version=1,
            effective_from=datetime.utcnow(),
            is_active=True
        )
        db.add(allocation_config)

        collection_config = CollectionConfiguration(
            product_id=product.id,
            allocation_strategy="OLDEST_DUE_FIRST",
            advance_collection_strategy="INTEREST_BENEFIT",
            excess_refund_required=True,
            version=1,
            effective_from=datetime.utcnow(),
            is_active=True
        )
        db.add(collection_config)
        
        npa_config = NpaConfiguration(
            product_id=product.id,
            dpd_threshold=90,
            bucket_classification_rules={"0-30": "Standard", "31-60": "SMA-1", "61-90": "SMA-2", "90+": "NPA"},
            version=1,
            effective_from=datetime.utcnow(),
            is_active=True
        )
        db.add(npa_config)
        
        foreclosure_config = ForeclosureConfiguration(
            product_id=product.id,
            charge_type="PERCENTAGE",
            charge_value=2.00,
            lock_in_period_months=3,
            rebate_percentage=50.00,
            version=1,
            effective_from=datetime.utcnow(),
            is_active=True
        )
        db.add(foreclosure_config)

        charge_master = ChargeMaster(code="LATE_PENALTY", name="Late Payment Penalty", description="Fee applied on overdue principal installments")
        db.add(charge_master)
        await db.flush()

        charge_config = ChargeConfiguration(
            product_id=product.id,
            charge_master_id=charge_master.id,
            charge_type="PERCENTAGE",
            value=2.00,
            is_taxable=True,
            tax_percentage=18.00,
            version=1,
            effective_from=datetime.utcnow(),
            is_active=True
        )
        db.add(charge_config)

        # 4. Create Configurations for Product 2 (EV Bike - flat interest & principal-first sequence)
        interest_config2 = InterestConfiguration(
            product_id=product2.id,
            calculation_basis="ACTUAL_360",
            emi_type="FLAT",
            repayment_frequency="MONTHLY",
            grace_period_days=0,
            version=1,
            effective_from=datetime.utcnow(),
            is_active=True
        )
        db.add(interest_config2)

        allocation_config2 = AllocationConfiguration(
            product_id=product2.id,
            sequence_type="REGULAR_EMI",
            priority_sequence=["principal", "interest", "charges"],
            version=1,
            effective_from=datetime.utcnow(),
            is_active=True
        )
        db.add(allocation_config2)

        collection_config2 = CollectionConfiguration(
            product_id=product2.id,
            allocation_strategy="OLDEST_DUE_FIRST",
            advance_collection_strategy="NO_INTEREST_BENEFIT",
            excess_refund_required=False,
            version=1,
            effective_from=datetime.utcnow(),
            is_active=True
        )
        db.add(collection_config2)
        
        npa_config2 = NpaConfiguration(
            product_id=product2.id,
            dpd_threshold=90,
            bucket_classification_rules={"0-30": "Standard", "31-90": "SMA", "90+": "NPA"},
            version=1,
            effective_from=datetime.utcnow(),
            is_active=True
        )
        db.add(npa_config2)
        
        foreclosure_config2 = ForeclosureConfiguration(
            product_id=product2.id,
            charge_type="FIXED",
            charge_value=1500.00,
            lock_in_period_months=0,
            rebate_percentage=0.00,
            version=1,
            effective_from=datetime.utcnow(),
            is_active=True
        )
        db.add(foreclosure_config2)

        charge_config2 = ChargeConfiguration(
            product_id=product2.id,
            charge_master_id=charge_master.id,
            charge_type="FIXED",
            value=250.00,
            is_taxable=True,
            tax_percentage=18.00,
            version=1,
            effective_from=datetime.utcnow(),
            is_active=True
        )
        db.add(charge_config2)

        # 5. Waive-Off Configurations
        # Product 1 (Solar): Both BOUNCE and PENAL are waiveable; BOUNCE is waived first
        waive_off_config1 = WaiveOffConfiguration(
            product_id=product.id,
            waiveable_charge_categories=["BOUNCE", "PENAL"],
            version=1,
            effective_from=datetime.utcnow(),
            is_active=True
        )
        db.add(waive_off_config1)

        # Product 2 (EV Bike): Only BOUNCE is waiveable
        waive_off_config2 = WaiveOffConfiguration(
            product_id=product2.id,
            waiveable_charge_categories=["BOUNCE"],
            version=1,
            effective_from=datetime.utcnow(),
            is_active=True
        )
        db.add(waive_off_config2)

        # 6. RPS Configurations
        # Product 1 (Solar): Three split options — full POS, 80/20, 70/30.
        # Hurdle Rate is only set on the 80/20 co-lending split.
        rps_config1 = RpsConfiguration(
            product_id=product.id,
            allowed_splits=[
                {"parts": [{"pct": 100, "party": "primary_lender"}]},
                {"parts": [{"pct": 80, "party": "primary_lender", "hurdle_rate": 10.5}, {"pct": 20, "party": "co-lender"}]},
                {"parts": [{"pct": 70, "party": "primary_lender"}, {"pct": 30, "party": "co-lender"}]},
            ],
            version=1,
            effective_from=datetime.utcnow(),
            is_active=True
        )
        db.add(rps_config1)

        # Product 2 (EV Bike): Two split options — full POS and 60/40.
        # Hurdle Rate is only set on the 60/40 co-lending split.
        rps_config2 = RpsConfiguration(
            product_id=product2.id,
            allowed_splits=[
                {"parts": [{"pct": 100, "party": "primary_lender"}]},
                {"parts": [{"pct": 60, "party": "primary_lender", "hurdle_rate": 9.5}, {"pct": 40, "party": "co-lender"}]},
            ],
            version=1,
            effective_from=datetime.utcnow(),
            is_active=True
        )
        db.add(rps_config2)
        
        await db.commit()
        print("[Seed] Seeding completed.")
        
    print("==================================================")
    print("DATABASE INITIALIZED & PRE-SEEDED SUCCESSFULLY!")
    print("==================================================")

if __name__ == "__main__":
    asyncio.run(bootstrap())
