# /opt/docker/dev/service_finder/backend/app/services/auth_service.py
import logging
import uuid
from datetime import datetime, timedelta, timezone
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, and_, update
from sqlalchemy.orm import joinedload
from fastapi.encoders import jsonable_encoder
from fastapi import HTTPException, status

from app.models.identity import User, Person, UserRole, VerificationToken, Wallet
from app.models import UserStats
from app.models.marketplace import Organization, OrganizationMember, OrgType, Branch
from app.schemas.auth import UserLiteRegister, UserKYCComplete
from app.core.security import get_password_hash, verify_password, generate_secure_slug
from app.services.email_manager import email_manager
from app.core.config import settings
from app.services.config_service import config
from app.services.geo_service import GeoService
from app.services.security_service import security_service
from app.services.gamification_service import GamificationService

logger = logging.getLogger(__name__)

class AuthService:
    @staticmethod
    async def register_lite(db: AsyncSession, user_in: UserLiteRegister):
        """ 1. FÁZIS: Lite regisztráció dinamikus korlátokkal és Sentinel naplózással. """
        try:
            # Paraméterek lekérése az admin felületről
            min_pass = await config.get_setting(db, "auth_min_password_length", default=8)
            default_role_name = await config.get_setting(db, "auth_default_role", default="user")
            reg_token_hours = await config.get_setting(db, "auth_registration_hours", region_code=user_in.region_code, default=48)
            
            if len(user_in.password) < int(min_pass):
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail=f"A jelszónak legalább {min_pass} karakter hosszúnak kell lennie."
                )

            # Check if email already exists
            existing_user = await db.execute(select(User).where(User.email == user_in.email))
            if existing_user.scalar_one_or_none():
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail="Ez az email cím már regisztrálva van."
                )

            new_person = Person(
                first_name=user_in.first_name,
                last_name=user_in.last_name,
                is_active=False,
                identity_docs={},  # EXPLICIT BEÁLLÍTÁS A DB HIBA ELKERÜLÉSÉRE
                ice_contact={},    # EXPLICIT BEÁLLÍTÁS A DB HIBA ELKERÜLÉSÉRE
                lifetime_xp=0,          # default -1, de explicit 0
                penalty_points=0,       # default -1, de explicit 0
                social_reputation=1.0,  # default 0.0, de explicit 1.0
                is_sales_agent=False,   # default True, de explicit False
                is_ghost=False,
                created_at=datetime.now(timezone.utc)
            )
            db.add(new_person)
            await db.flush()

            # Szerepkör dinamikus feloldása
            assigned_role = UserRole[default_role_name] if default_role_name in UserRole.__members__ else UserRole.user

            new_user = User(
                email=user_in.email,
                hashed_password=get_password_hash(user_in.password),
                person_id=new_person.id,
                role=assigned_role,
                is_active=False,
                is_deleted=False,
                region_code=user_in.region_code,
                preferred_language=user_in.lang,
                subscription_plan='FREE',
                # --- EXPLICIT DEFAULT ÉRTÉKEK A DB HIBA ELKERÜLÉSÉRE ---
                is_vip=True,  # Changed to True to force inclusion in INSERT
                preferred_currency="HUF",
                scope_level="individual",
                custom_permissions={},
                created_at=datetime.now(timezone.utc)
            )
            db.add(new_user)
            await db.flush()

            # Verifikációs token
            token_val = uuid.uuid4()
            db.add(VerificationToken(
                token=token_val,
                user_id=new_user.id,
                token_type="registration",
                expires_at=datetime.now(timezone.utc) + timedelta(hours=int(reg_token_hours))
            ))
            
            # Email küldés a beállított template alapján
            verification_link = f"{settings.FRONTEND_BASE_URL}/verify?token={token_val}"
            email_result = await email_manager.send_email(
                recipient=user_in.email,
                template_key="reg",
                variables={"first_name": user_in.first_name, "link": verification_link},
                lang=user_in.lang
            )
            # Check if email sending failed
            if email_result and email_result.get("status") == "error":
                raise HTTPException(
                    status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                    detail="Email delivery failed. Please contact support."
                )

            # Sentinel Audit Log
            await security_service.log_event(
                db, user_id=new_user.id, action="USER_REGISTER_LITE",
                severity="INFO", target_type="User", target_id=str(new_user.id),
                new_data={"email": user_in.email}
            )

            await db.commit()
            return new_user
        except Exception as e:
            await db.rollback()
            logger.error(f"Lite Reg Error: {e}")
            raise e

    @staticmethod
    async def complete_kyc(db: AsyncSession, user_id: int, kyc_in: UserKYCComplete):
        """ 2. FÁZIS: Teljes profil és Gamification inicializálás. """
        try:
            stmt = select(User).options(joinedload(User.person)).where(User.id == user_id)
            user = (await db.execute(stmt)).scalar_one_or_none()
            if not user: return None

            # Dinamikus beállítások (Soha ne legyen kódba vésve!)
            org_tpl = await config.get_setting(db, "org_naming_template", default="{last_name} Flotta")
            base_cur = await config.get_setting(db, "finance_default_currency", region_code=user.region_code, default="HUF")
            kyc_reward = await config.get_setting(db, "gamification_kyc_bonus", default=500)

            # Címkezelés (GeoService hívás)
            addr_id = await GeoService.get_or_create_full_address(
                db, zip_code=kyc_in.address_zip, city=kyc_in.address_city,
                street_name=kyc_in.address_street_name, street_type=kyc_in.address_street_type,
                house_number=kyc_in.address_house_number, parcel_id=kyc_in.address_hrsz
            )

            # Person adatok dúsítása
            p = user.person
            p.mothers_last_name = kyc_in.mothers_last_name
            p.mothers_first_name = kyc_in.mothers_first_name
            p.birth_place = kyc_in.birth_place
            p.birth_date = kyc_in.birth_date
            p.phone = kyc_in.phone_number
            p.address_id = addr_id
            p.identity_docs = jsonable_encoder(kyc_in.identity_docs)
            p.is_active = True

            # Dinamikus szervezet generálás
            org_full_name = org_tpl.format(last_name=p.last_name, first_name=p.first_name)
            new_org = Organization(
                full_name=org_full_name,
                name=f"{p.last_name} Széfe",
                folder_slug=generate_secure_slug(12),
                org_type=OrgType.individual,
                owner_id=user.id,
                is_active=True,
                status="verified",
                country_code=user.region_code,
                # --- EXPLICIT IDŐBÉLYEGEK A DB HIBA ELKERÜLÉSÉRE ---
                first_registered_at=datetime.now(timezone.utc),
                current_lifecycle_started_at=datetime.now(timezone.utc),
                created_at=datetime.now(timezone.utc),
                subscription_plan="FREE",
                base_asset_limit=1,
                purchased_extra_slots=0,
                notification_settings={},
                external_integration_config={},
                is_ownership_transferable=True
            )
            db.add(new_org)
            await db.flush()

            # Infrastruktúra elemek
            db.add(Branch(organization_id=new_org.id, address_id=addr_id, name="Home Base", is_main=True))
            db.add(OrganizationMember(organization_id=new_org.id, user_id=user.id, role="OWNER"))
            db.add(Wallet(user_id=user.id, currency=kyc_in.preferred_currency or base_cur))
            db.add(UserStats(user_id=user.id))

            user.is_active = True
            user.folder_slug = generate_secure_slug(12)
            # Set user's scope_id to the new personal organization ID
            user.scope_id = str(new_org.id)

            # Gamification XP jóváírás
            await GamificationService.award_points(db, user_id=user.id, amount=int(kyc_reward), reason="KYC_VERIFICATION")

            await db.commit()
            return user
        except Exception as e:
            await db.rollback()
            logger.error(f"KYC Error: {e}")
            raise e

    @staticmethod
    async def authenticate(db: AsyncSession, email: str, password: str):
        """ Felhasználó hitelesítése. """
        stmt = select(User).where(and_(User.email == email, User.is_deleted == False))
        res = await db.execute(stmt)
        user = res.scalar_one_or_none()
        if user and verify_password(password, user.hashed_password):
            return user
        return None

    @staticmethod
    async def verify_email(db: AsyncSession, token_str: str):
        """ Email megerősítés. """
        try:
            token_uuid = uuid.UUID(token_str)
            stmt = select(VerificationToken).where(and_(
                VerificationToken.token == token_uuid,
                VerificationToken.is_used == False,
                VerificationToken.expires_at > datetime.now(timezone.utc)
            ))
            token = (await db.execute(stmt)).scalar_one_or_none()
            if not token: return False
            
            token.is_used = True
            # Itt aktiválhatnánk a júzert, ha a Lite regnél még nem tennénk meg
            await db.commit()
            return True
        except: return False

    @staticmethod
    async def initiate_password_reset(db: AsyncSession, email: str):
        """ Elfelejtett jelszó folyamat indítása. """
        stmt = select(User).where(and_(User.email == email, User.is_deleted == False))
        user = (await db.execute(stmt)).scalar_one_or_none()
        
        if user:
            # Dinamikus lejárat az adminból
            reset_h = await config.get_setting(db, "auth_password_reset_hours", region_code=user.region_code, default=2)
            token_val = uuid.uuid4()
            db.add(VerificationToken(
                token=token_val, user_id=user.id, token_type="password_reset",
                expires_at=datetime.now(timezone.utc) + timedelta(hours=int(reset_h))
            ))
            
            link = f"{settings.FRONTEND_BASE_URL}/reset-password?token={token_val}"
            await email_manager.send_email(
                recipient=email, template_key="pwd_reset",
                variables={"link": link}, lang=user.preferred_language
            )
            await db.commit()
            return "success"
        return "not_found"

    @staticmethod
    async def reset_password(db: AsyncSession, email: str, token_str: str, new_password: str):
        """ Jelszó tényleges megváltoztatása token alapján. """
        try:
            token_uuid = uuid.UUID(token_str)
            stmt = select(VerificationToken).join(User).where(and_(
                User.email == email,
                VerificationToken.token == token_uuid,
                VerificationToken.token_type == "password_reset",
                VerificationToken.is_used == False,
                VerificationToken.expires_at > datetime.now(timezone.utc)
            ))
            token_rec = (await db.execute(stmt)).scalar_one_or_none()
            if not token_rec: return False
            
            user_stmt = select(User).where(User.id == token_rec.user_id)
            user = (await db.execute(user_stmt)).scalar_one()
            user.hashed_password = get_password_hash(new_password)
            token_rec.is_used = True
            
            await db.commit()
            return True
        except: return False

    @staticmethod
    async def soft_delete_user(db: AsyncSession, user_id: int, reason: str, actor_id: int):
        """ Felhasználó törlése (Soft-Delete) auditálással. """
        stmt = select(User).where(User.id == user_id)
        user = (await db.execute(stmt)).scalar_one_or_none()
        if not user or user.is_deleted: return False

        old_email = user.email
        user.email = f"deleted_{user.id}_{datetime.now().strftime('%Y%m%d')}_{old_email}"
        user.is_deleted = True
        user.is_active = False
        
        await security_service.log_event(
            db, user_id=actor_id, action="USER_SOFT_DELETE",
            severity="WARNING", target_type="User", target_id=str(user_id),
            new_data={"reason": reason}
        )
        await db.commit()
        return True