import os
import sys
from datetime import datetime, timedelta
from decimal import Decimal

BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
if BASE_DIR not in sys.path:
    sys.path.insert(0, BASE_DIR)

from app import create_app
from app.extensions import db
from app.models import (
    Activity,
    ActivityImage,
    ActivityType,
    CauseCategory,
    City,
    DonationCause,
    DonationCauseImage,
    DonationSuggestedAmount,
    Employee,
    HeartRule,
    Partner,
    Permission,
    Role,
    SystemSetting,
    User,
)

app = create_app()

PERMISSIONS = [
    "portal.access",
    "activities.view",
    "activities.register",
    "activities.create",
    "activities.edit",
    "activities.approve",
    "activities.publish",
    "attendance.view",
    "attendance.manage",
    "donations.view",
    "donations.create",
    "donations.reconcile",
    "impact.view",
    "impact.manage",
    "employees.view",
    "manager.approvals.view",
    "manager.approvals.manage",
    "admin.dashboard.view",
    "reports.view",
    "reports.export",
]

EMPLOYEE_PERMISSIONS = [
    "portal.access",
    "activities.view",
    "activities.register",
    "donations.view",
    "donations.create",
    "impact.view",
]

MANAGER_PERMISSIONS = EMPLOYEE_PERMISSIONS + [
    "manager.approvals.view",
    "manager.approvals.manage",
]

ROLES = {
    "EMPLOYEE": EMPLOYEE_PERMISSIONS,
    "MANAGER": MANAGER_PERMISSIONS,
    "PIRAMAL_ADMIN": PERMISSIONS,
    "INDIAISUS_ADMIN": PERMISSIONS,
    "OPERATIONS": [
        "portal.access",
        "activities.view",
        "activities.create",
        "activities.edit",
        "attendance.view",
        "attendance.manage",
        "impact.view",
    ],
    "FINANCE": [
        "portal.access",
        "donations.view",
        "donations.reconcile",
        "reports.view",
        "reports.export",
    ],
    "SUPER_ADMIN": PERMISSIONS,
}

CAUSES = [
    ("EDUCATION", "Education"),
    ("HEALTHCARE", "Healthcare"),
    ("LIVELIHOOD", "Livelihood"),
    ("WOMEN", "Women Empowerment"),
    ("CHILD", "Child Welfare"),
    ("ENVIRONMENT", "Environment"),
]

ACTIVITY_TYPES = [
    ("FIELD", "Field Volunteering"),
    ("SKILL", "Skill-based Volunteering"),
    ("VIRTUAL", "Virtual Volunteering"),
]

DEMO_USERS = {
    "admin": {
        "email": "admin@sevasetu.local",
        "employee_code": "PSS-ADMIN-001",
        "full_name": "Seva Setu Admin",
        "roles": ["SUPER_ADMIN", "EMPLOYEE"],
    },
    "manager": {
        "email": "manager@sevasetu.local",
        "employee_code": "PSS-MGR-001",
        "full_name": "Demo Manager",
        "roles": ["MANAGER", "EMPLOYEE"],
    },
    "employee": {
        "email": "employee@sevasetu.local",
        "employee_code": "PSS-EMP-001",
        "full_name": "Demo Employee",
        "roles": ["EMPLOYEE"],
    },
}


def get_or_create_demo_user(details, city, role_map):
    user = User.query.filter_by(official_email=details["email"]).first()
    if not user:
        user = User(official_email=details["email"], is_active=True)
        db.session.add(user)
        db.session.flush()
    else:
        user.is_active = True

    user.roles = [role_map[code] for code in details["roles"]]

    employee = Employee.query.filter_by(user_id=user.id).first()
    if not employee:
        employee = Employee(
            user_id=user.id,
            employee_code=details["employee_code"],
            full_name=details["full_name"],
            official_email=details["email"],
            city_id=city.id,
            eligible_for_portal=True,
            first_login_completed=True,
            is_active=True,
        )
        db.session.add(employee)
    else:
        employee.employee_code = details["employee_code"]
        employee.full_name = details["full_name"]
        employee.official_email = details["email"]
        employee.city_id = city.id
        employee.eligible_for_portal = True
        employee.first_login_completed = True
        employee.is_active = True

    db.session.flush()
    return user, employee


def seed_demo_content(admin_user, mumbai):
    """Create editable demo content for Seva Bhaav and Seva Daan. Safe to run repeatedly."""
    categories = {c.code: c for c in CauseCategory.query.all()}
    activity_types = {a.code: a for a in ActivityType.query.all()}

    partner = Partner.query.filter_by(name="India Is Us Demo Partner").first()
    if not partner:
        partner = Partner(
            name="India Is Us Demo Partner",
            partner_type="NGO",
            contact_name="Demo Programme Team",
            contact_email="partner@sevasetu.local",
            website="https://www.indiaisus.com/",
            is_active=True,
        )
        db.session.add(partner)
        db.session.flush()

    now = datetime.now()
    activity_seed = [
        {
            "activity_code": "SB-DEMO-001",
            "title": "Mumbai Beach Cleanup Drive",
            "cause": "ENVIRONMENT",
            "type": "FIELD",
            "days": 14,
            "start_hour": 7,
            "duration": 3,
            "capacity": 40,
            "working": False,
            "approval": False,
            "meeting": "Juhu Beach, Mumbai",
            "impact": "Join fellow volunteers to help restore a cleaner coastline for the community.",
            "description": "A hands-on community cleanup focused on removing litter, segregating collected waste and building awareness around responsible disposal.",
            "do": "Participate in the cleanup, segregate collected waste and support the on-ground awareness activity.",
            "carry": "Comfortable shoes, cap and a reusable water bottle. Cleanup material will be provided.",
            "eligibility": "Open to eligible employees. Participants should be comfortable with light outdoor physical activity.",
            "safety": "Wear closed footwear, use the provided gloves and follow the volunteer coordinator's safety briefing.",
        },
        {
            "activity_code": "SB-DEMO-002",
            "title": "Career Mentoring for Young Learners",
            "cause": "EDUCATION",
            "type": "SKILL",
            "days": 21,
            "start_hour": 14,
            "duration": 2,
            "capacity": 25,
            "working": True,
            "approval": True,
            "meeting": "Piramal Mumbai Office / Partner Learning Centre",
            "impact": "Share practical career guidance and workplace perspectives with young learners preparing for their next step.",
            "description": "A structured mentoring session where employee volunteers interact with young learners on career awareness, workplace readiness and confidence building.",
            "do": "Facilitate small-group conversations, answer career questions and guide learners through simple workplace-readiness exercises.",
            "carry": "Laptop optional. Session guide and facilitation material will be shared in advance.",
            "eligibility": "Open to employees willing to mentor and communicate with young adults. No prior teaching experience required.",
            "safety": "Follow partner safeguarding guidelines and keep all interactions within the scheduled group format.",
        },
        {
            "activity_code": "SB-DEMO-003",
            "title": "Digital Skills Volunteering Session",
            "cause": "LIVELIHOOD",
            "type": "VIRTUAL",
            "days": 28,
            "start_hour": 16,
            "duration": 2,
            "capacity": 50,
            "working": True,
            "approval": True,
            "meeting": "Online - joining details shared after confirmation",
            "impact": "Help participants build confidence with essential digital tools used in education and employment.",
            "description": "A virtual skill-based volunteering session covering practical digital basics such as email, documents, online safety and job-search tools.",
            "do": "Demonstrate digital tools, support guided exercises and answer participant questions during the session.",
            "carry": "Laptop, stable internet connection and headset recommended.",
            "eligibility": "Employees comfortable using common productivity and communication tools.",
            "safety": "Use only approved meeting links and do not exchange personal contact details with participants.",
        },
    ]

    for item in activity_seed:
        activity = Activity.query.filter_by(activity_code=item["activity_code"]).first()
        if activity:
            continue
        start = (now + timedelta(days=item["days"])).replace(hour=item["start_hour"], minute=0, second=0, microsecond=0)
        end = start + timedelta(hours=item["duration"])
        db.session.add(Activity(
            activity_code=item["activity_code"],
            title=item["title"],
            short_impact_statement=item["impact"],
            description=item["description"],
            what_you_will_do=item["do"],
            what_to_carry=item["carry"],
            eligibility_requirements=item["eligibility"],
            safety_instructions=item["safety"],
            cause_category_id=categories[item["cause"]].id,
            activity_type_id=activity_types[item["type"]].id,
            partner_id=partner.id,
            city_id=mumbai.id,
            meeting_point=item["meeting"],
            start_datetime=start,
            end_datetime=end,
            registration_open_at=now - timedelta(days=1),
            registration_close_at=start - timedelta(days=2),
            capacity=item["capacity"],
            manager_approval_required=item["approval"],
            working_hours_activity=item["working"],
            cancellation_cutoff_hours=24,
            status="PUBLISHED",
            published_at=now,
            created_by_id=admin_user.id,
            approved_by_id=admin_user.id,
        ))

    cause_seed = [
        {
            "code": "SD-DEMO-001", "name": "Support a Child's Learning Journey", "category": "EDUCATION",
            "problem": "Children from underserved communities can face gaps in access to learning material and structured academic support.",
            "enables": "Contributions support learning resources, mentoring and programme delivery for participating children.",
            "target": Decimal("500000.00"),
            "amounts": [(Decimal("500.00"), "Supports learning material for a participating learner."), (Decimal("1000.00"), "Contributes towards structured learning support."), (Decimal("2500.00"), "Helps strengthen a learner's programme support package.")],
        },
        {
            "code": "SD-DEMO-002", "name": "Community Health & Wellness Support", "category": "HEALTHCARE",
            "problem": "Vulnerable communities may have limited access to preventive health awareness and basic wellness support.",
            "enables": "Contributions help programme partners conduct community health awareness and wellness initiatives.",
            "target": Decimal("750000.00"),
            "amounts": [(Decimal("750.00"), "Contributes to community health awareness material."), (Decimal("1500.00"), "Supports programme delivery for a community wellness initiative."), (Decimal("3000.00"), "Helps extend preventive-health outreach to more participants.")],
        },
        {
            "code": "SD-DEMO-003", "name": "Women Livelihood & Skills Initiative", "category": "WOMEN",
            "problem": "Women seeking economic independence can benefit from market-relevant skills, mentoring and livelihood enablement.",
            "enables": "Contributions support skills training, mentoring and livelihood-readiness interventions delivered through programme partners.",
            "target": Decimal("1000000.00"),
            "amounts": [(Decimal("1000.00"), "Contributes to training resources for a participant."), (Decimal("2500.00"), "Supports skills and livelihood-readiness sessions."), (Decimal("5000.00"), "Helps expand structured training and mentoring support.")],
        },
    ]

    for item in cause_seed:
        cause = DonationCause.query.filter_by(cause_code=item["code"]).first()
        if cause:
            continue
        cause = DonationCause(
            cause_code=item["code"],
            name=item["name"],
            cause_category_id=categories[item["category"]].id,
            partner_id=partner.id,
            problem_statement=item["problem"],
            contribution_enables=item["enables"],
            fundraising_target=item["target"],
            start_date=now.date(),
            end_date=(now + timedelta(days=180)).date(),
            status="PUBLISHED",
            created_by_id=admin_user.id,
        )
        db.session.add(cause)
        db.session.flush()
        for sort_order, (amount, impact_text) in enumerate(item["amounts"], start=1):
            db.session.add(DonationSuggestedAmount(
                donation_cause_id=cause.id, amount=amount, impact_text=impact_text, sort_order=sort_order
            ))
    # Ensure each seeded activity has a professional local illustration. This also
    # updates older databases where the demo records already existed before images were added.
    activity_images = {
        "SB-DEMO-001": ("/static/images/seeds/beach-cleanup.svg", "Volunteers taking part in a beach cleanup"),
        "SB-DEMO-002": ("/static/images/seeds/career-mentoring.svg", "Career mentoring session with young learners"),
        "SB-DEMO-003": ("/static/images/seeds/digital-skills.svg", "Digital skills volunteering session"),
    }
    for code, (path, alt_text) in activity_images.items():
        activity = Activity.query.filter_by(activity_code=code).first()
        if activity and not ActivityImage.query.filter_by(activity_id=activity.id, file_path=path).first():
            db.session.add(ActivityImage(
                activity_id=activity.id, file_path=path, alt_text=alt_text, sort_order=0, is_primary=True
            ))

    # Ensure the seeded Seva Daan causes also have local illustrations.
    cause_images = {
        "SD-DEMO-001": ("/static/images/seeds/child-learning.svg", "Learning support for children"),
        "SD-DEMO-002": ("/static/images/seeds/community-health.svg", "Community health and wellness support"),
        "SD-DEMO-003": ("/static/images/seeds/women-livelihood.svg", "Women livelihood and skills initiative"),
    }
    for code, (path, alt_text) in cause_images.items():
        cause = DonationCause.query.filter_by(cause_code=code).first()
        if cause and not DonationCauseImage.query.filter_by(donation_cause_id=cause.id, file_path=path).first():
            db.session.add(DonationCauseImage(
                donation_cause_id=cause.id, file_path=path, alt_text=alt_text, sort_order=0
            ))


with app.app_context():
    # Permissions
    for code in PERMISSIONS:
        permission = Permission.query.filter_by(code=code).first()
        if not permission:
            db.session.add(Permission(code=code, name=code.replace(".", " ").title()))
    db.session.flush()

    all_permissions = {p.code: p for p in Permission.query.all()}

    # Roles and role-permission mapping
    for code, permission_codes in ROLES.items():
        role = Role.query.filter_by(code=code).first()
        if not role:
            role = Role(code=code, name=code.replace("_", " ").title())
            db.session.add(role)
            db.session.flush()
        role.permissions = [all_permissions[p] for p in permission_codes]

    # Launch cities
    for code, name, eligible in [("MUM", "Mumbai", True), ("PUN", "Pune", True)]:
        if not City.query.filter_by(code=code).first():
            db.session.add(City(code=code, name=name, state_name="Maharashtra", launch_eligible=eligible))
    db.session.flush()

    # Masters
    for code, name in CAUSES:
        if not CauseCategory.query.filter_by(code=code).first():
            db.session.add(CauseCategory(code=code, name=name))

    for code, name in ACTIVITY_TYPES:
        if not ActivityType.query.filter_by(code=code).first():
            db.session.add(ActivityType(code=code, name=name))

    # Hearts rules
    if not HeartRule.query.filter_by(code="VOLUNTEER_HOUR").first():
        db.session.add(HeartRule(code="VOLUNTEER_HOUR", action_type="VOLUNTEER_HOUR", calculation_type="PER_UNIT", hearts=10))
    if not HeartRule.query.filter_by(code="ACTIVITY_COMPLETE").first():
        db.session.add(HeartRule(code="ACTIVITY_COMPLETE", action_type="ACTIVITY_COMPLETE", calculation_type="FIXED", hearts=20))

    defaults = {
        "reserve_capacity_during_approval": "false",
        "manager_nudge_cooling_hours": "24",
        "default_cancellation_cutoff_hours": "24",
    }
    for key, value in defaults.items():
        if not SystemSetting.query.filter_by(key=key).first():
            db.session.add(SystemSetting(key=key, value=value))

    db.session.flush()

    # Development personas. No password or SSO subject is required; auth/dev-login handles local bypass.
    role_map = {role.code: role for role in Role.query.all()}
    mumbai = City.query.filter_by(code="MUM").first()

    _, admin_employee = get_or_create_demo_user(DEMO_USERS["admin"], mumbai, role_map)
    _, manager_employee = get_or_create_demo_user(DEMO_USERS["manager"], mumbai, role_map)
    _, employee_employee = get_or_create_demo_user(DEMO_USERS["employee"], mumbai, role_map)

    # Employee reports to the seeded manager; admin has no reporting dependency.
    employee_employee.manager_id = manager_employee.id

    # Seed three published Seva Bhaav activities and three published Seva Daan causes.
    seed_demo_content(User.query.filter_by(official_email=DEMO_USERS["admin"]["email"]).first(), mumbai)

    db.session.commit()

    print("Seed completed.")
    print("Development accounts:")
    print("  Admin:    admin@sevasetu.local")
    print("  Manager:  manager@sevasetu.local")
    print("  Employee: employee@sevasetu.local")
    print("Use /auth/login while DEV_LOGIN_ENABLED=true. No password is required in development mode.")
    print("Demo content: 3 published Seva Bhaav activities + 3 published Seva Daan causes.")
