import asyncio

from sqlalchemy import select
from sqlalchemy.dialects.mysql import insert

from app.core.database import SessionLocal
from app.core.security import hash_password
from app.models import (
    Brand,
    Role,
    Permission,
    User,
    LoyaltyProgram,
    Tier,
    Reward,
)
from app.models.role import role_permissions


PERMS = [
    ("customers.view", "View customers"),
    ("customers.manage", "Manage customers"),
    ("transactions.manage", "Manage transactions"),
    ("rewards.view", "View rewards"),
    ("rewards.manage", "Manage rewards"),
    ("rewards.redeem", "Redeem rewards"),
    ("reports.view", "View reports"),
    ("settings.manage", "Manage settings"),
]


async def main():

    async with SessionLocal() as db:

        # -------------------------------------------------
        # 1. BRAND
        # -------------------------------------------------

        brand = await db.scalar(
            select(Brand).where(
                Brand.code == "CANTABIL-DEMO"
            )
        )

        if not brand:
            brand = Brand(
                name="Cantabil Demo",
                legal_name="Cantabil Demo Retail Pvt Ltd",
                code="CANTABIL-DEMO",
                industry="Retail",
            )

            db.add(brand)
            await db.flush()

        # -------------------------------------------------
        # 2. ROLE
        # -------------------------------------------------

        role = await db.scalar(
            select(Role).where(
                Role.brand_id == brand.id,
                Role.name == "Brand Admin",
            )
        )

        if not role:

            role = Role(
                brand_id=brand.id,
                name="Brand Admin",
            )

            db.add(role)
            await db.flush()

        # -------------------------------------------------
        # 3. PERMISSIONS
        # -------------------------------------------------

        for code, name in PERMS:

            permission = await db.scalar(
                select(Permission).where(
                    Permission.code == code
                )
            )

            if not permission:

                permission = Permission(
                    code=code,
                    name=name,
                )

                db.add(permission)
                await db.flush()

            # ---------------------------------------------
            # DIRECT INSERT INTO role_permissions
            # Avoid async lazy-loading
            # ---------------------------------------------

            existing = await db.execute(
                select(role_permissions).where(
                    role_permissions.c.role_id == role.id,
                    role_permissions.c.permission_id == permission.id,
                )
            )

            if existing.first() is None:

                await db.execute(
                    role_permissions.insert().values(
                        role_id=role.id,
                        permission_id=permission.id,
                    )
                )

        # -------------------------------------------------
        # 4. ADMIN USER
        # -------------------------------------------------

        user = await db.scalar(
            select(User).where(
                User.email == "admin@demo.local"
            )
        )

        if not user:

            user = User(
                brand_id=brand.id,
                role_id=role.id,
                name="Demo Admin",
                email="admin@demo.local",
                password_hash=hash_password(
                    "Admin@12345"
                ),
                status="active",
            )

            db.add(user)

        # -------------------------------------------------
        # 5. LOYALTY PROGRAM
        # -------------------------------------------------

        loyalty_program = await db.scalar(
            select(LoyaltyProgram).where(
                LoyaltyProgram.brand_id == brand.id
            )
        )

        if not loyalty_program:

            db.add(
                LoyaltyProgram(
                    brand_id=brand.id,
                    name="Demo Rewards",
                    points_per_100=10,
                )
            )

        # -------------------------------------------------
        # 6. TIERS
        # -------------------------------------------------

        tiers = [
            ("Silver", 0, 1),
            ("Gold", 500, 1.25),
            ("Platinum", 2000, 1.5),
        ]

        for name, min_points, multiplier in tiers:

            tier = await db.scalar(
                select(Tier).where(
                    Tier.brand_id == brand.id,
                    Tier.name == name,
                )
            )

            if not tier:

                db.add(
                    Tier(
                        brand_id=brand.id,
                        name=name,
                        min_points=min_points,
                        multiplier=multiplier,
                    )
                )

        # -------------------------------------------------
        # 7. REWARDS
        # -------------------------------------------------

        reward = await db.scalar(
            select(Reward).where(
                Reward.brand_id == brand.id
            )
        )

        if not reward:

            db.add_all(
                [
                    Reward(
                        brand_id=brand.id,
                        name="₹100 Voucher",
                        reward_type="voucher",
                        points_cost=1000,
                        stock=100,
                    ),
                    Reward(
                        brand_id=brand.id,
                        name="Gift Box",
                        reward_type="gift",
                        points_cost=2000,
                        stock=50,
                    ),
                ]
            )

        # -------------------------------------------------
        # COMMIT
        # -------------------------------------------------

        await db.commit()

    print("")
    print("======================================")
    print("       LOYALTY PLATFORM SEED")
    print("======================================")
    print("")
    print("Seed complete.")
    print("")
    print("Login:")
    print("Email    : admin@demo.local")
    print("Password : Admin@12345")
    print("")
    print("======================================")


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