"""Auth iş mantığı — kayıt, login, profil, şifre. Repository'ye delege eder."""

from fastapi import Depends

from app.auth.jwt import create_access_token
from app.models.tenant import Tenant
from app.repositories.tenant_repo import TenantRepository
from app.schemas.auth import (
    AuthResponse,
    ChangePasswordRequest,
    LoginRequest,
    RegisterRequest,
    TenantResponse,
    TokenResponse,
    UpdateProfileRequest,
)
from app.utils.exceptions import (
    ConflictError,
    UnauthorizedError,
    ValidationError,
)
from app.utils.security import (
    generate_api_key,
    generate_token,
    hash_password,
    verify_password,
)


class AuthService:
    def __init__(self, repo: TenantRepository = Depends()):
        self.repo = repo

    async def register(self, body: RegisterRequest) -> AuthResponse:
        if await self.repo.email_exists(body.email):
            raise ConflictError("Bu e-posta zaten kayıtlı.")

        tenant = await self.repo.create(
            name=body.name,
            email=body.email,
            password_hash=hash_password(body.password),
            api_key=generate_api_key(),
            webhook_secret=generate_token(24),
        )
        token = await self._issue_token(tenant)
        return AuthResponse(
            tenant=TenantResponse.model_validate(tenant), token=token
        )

    async def login(self, body: LoginRequest) -> AuthResponse:
        tenant = await self.repo.get_by_email(body.email)
        if not tenant or not verify_password(body.password, tenant.password_hash):
            raise UnauthorizedError("E-posta veya şifre hatalı.")
        if not tenant.is_active:
            raise UnauthorizedError("Hesabınız pasif durumda.")

        token = await self._issue_token(tenant)
        return AuthResponse(
            tenant=TenantResponse.model_validate(tenant), token=token
        )

    async def logout(self, jti: str) -> None:
        session = await self.repo.get_session_by_jti(jti)
        if session and session.revoked_at is None:
            await self.repo.revoke_session(session)

    async def refresh(self, tenant: Tenant, old_jti: str) -> TokenResponse:
        await self.logout(old_jti)
        return await self._issue_token(tenant)

    async def get_profile(self, tenant: Tenant) -> TenantResponse:
        return TenantResponse.model_validate(tenant)

    async def update_profile(
        self, tenant: Tenant, body: UpdateProfileRequest
    ) -> TenantResponse:
        updates = body.model_dump(exclude_none=True)
        if updates:
            tenant = await self.repo.update(tenant, **updates)
        return TenantResponse.model_validate(tenant)

    async def change_password(
        self, tenant: Tenant, body: ChangePasswordRequest
    ) -> None:
        if not verify_password(body.current_password, tenant.password_hash):
            raise ValidationError("Mevcut şifre hatalı.")
        await self.repo.update(
            tenant, password_hash=hash_password(body.new_password)
        )

    async def _issue_token(self, tenant: Tenant) -> TokenResponse:
        token, jti, expires_at = create_access_token(
            tenant.id, tenant.email, tenant.plan
        )
        await self.repo.create_session(
            tenant_id=tenant.id,
            jti=jti,
            expires_at=expires_at.replace(tzinfo=None),
        )
        return TokenResponse(access_token=token, expires_at=expires_at)
