<?php

namespace App\Services;

use App\Models\Members\User;
use App\Models\Members\UserTenant;
use App\Models\Permissions\Role;
use App\Models\UserInvitation;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

class UserInvitationService extends Service
{
    /**
     * 초대 목록 조회
     */
    public function index(array $params): LengthAwarePaginator
    {
        $tenantId = $this->tenantId();

        $query = UserInvitation::query()
            ->where('tenant_id', $tenantId)
            ->with(['role:id,name', 'inviter:id,name']);

        // 상태 필터
        if (! empty($params['status'])) {
            $query->where('status', $params['status']);
        }

        // 이메일 검색
        if (! empty($params['search'])) {
            $search = $params['search'];
            $query->where(function ($q) use ($search) {
                $q->where('email', 'like', "%{$search}%");
            });
        }

        // 정렬
        $sortBy = $params['sort_by'] ?? 'created_at';
        $sortDir = $params['sort_dir'] ?? 'desc';
        $query->orderBy($sortBy, $sortDir);

        // 페이지네이션
        $perPage = $params['per_page'] ?? 20;

        return $query->paginate($perPage);
    }

    /**
     * 사용자 초대 발송
     */
    public function invite(array $data): UserInvitation
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        // role 문자열 → role_id 변환 (React 호환)
        if (! empty($data['role']) && empty($data['role_id'])) {
            $role = Role::where('name', $data['role'])
                ->where('tenant_id', $tenantId)
                ->first();
            $data['role_id'] = $role?->id;
        }

        return DB::transaction(function () use ($data, $tenantId, $userId) {
            $email = $data['email'];

            // 이미 테넌트에 가입된 사용자인지 확인
            $existingUser = User::where('email', $email)->first();
            if ($existingUser) {
                $existingMembership = UserTenant::where('tenant_id', $tenantId)
                    ->where('user_id', $existingUser->id)
                    ->whereNull('deleted_at')
                    ->exists();

                if ($existingMembership) {
                    throw new BadRequestHttpException(__('error.invitation.already_member'));
                }
            }

            // 이미 대기 중인 초대가 있는지 확인
            $pendingInvitation = UserInvitation::where('tenant_id', $tenantId)
                ->where('email', $email)
                ->pending()
                ->first();

            if ($pendingInvitation) {
                throw new BadRequestHttpException(__('error.invitation.already_pending'));
            }

            // 초대 생성
            $invitation = new UserInvitation;
            $invitation->tenant_id = $tenantId;
            $invitation->email = $email;
            $invitation->role_id = $data['role_id'] ?? null;
            $invitation->message = $data['message'] ?? null;
            $invitation->token = UserInvitation::generateToken();
            $invitation->status = UserInvitation::STATUS_PENDING;
            $invitation->invited_by = $userId;
            $invitation->expires_at = UserInvitation::calculateExpiresAt($data['expires_days'] ?? UserInvitation::DEFAULT_EXPIRES_DAYS);
            $invitation->save();

            // 초대 이메일 발송 (비동기 처리 권장)
            $this->sendInvitationEmail($invitation);

            return $invitation->load(['role:id,name', 'inviter:id,name']);
        });
    }

    /**
     * 초대 수락
     */
    public function accept(string $token, array $userData): User
    {
        return DB::transaction(function () use ($token, $userData) {
            // 토큰으로 초대 조회 (테넌트 스코프 제외)
            $invitation = UserInvitation::withoutGlobalScopes()
                ->where('token', $token)
                ->first();

            if (! $invitation) {
                throw new NotFoundHttpException(__('error.invitation.not_found'));
            }

            if (! $invitation->canAccept()) {
                if ($invitation->isExpired()) {
                    $invitation->markAsExpired();
                    throw new BadRequestHttpException(__('error.invitation.expired'));
                }
                throw new BadRequestHttpException(__('error.invitation.invalid_status'));
            }

            // 기존 사용자 확인 또는 신규 생성
            $user = User::where('email', $invitation->email)->first();

            if (! $user) {
                // 신규 사용자 생성
                $user = new User;
                $user->email = $invitation->email;
                $user->name = $userData['name'];
                $user->password = $userData['password'];
                $user->phone = $userData['phone'] ?? null;
                $user->save();
            }

            // 테넌트 멤버십 생성
            $userTenant = new UserTenant;
            $userTenant->user_id = $user->id;
            $userTenant->tenant_id = $invitation->tenant_id;
            $userTenant->is_active = true;
            $userTenant->is_default = ! $user->userTenants()->exists(); // 첫 테넌트면 기본으로
            $userTenant->joined_at = now();
            $userTenant->save();

            // 역할 부여 (있는 경우)
            if ($invitation->role_id) {
                $user->assignRole($invitation->role->name);
            }

            // 초대 수락 처리
            $invitation->markAsAccepted();

            return $user;
        });
    }

    /**
     * 초대 취소
     */
    public function cancel(int $id): bool
    {
        $tenantId = $this->tenantId();

        $invitation = UserInvitation::where('tenant_id', $tenantId)
            ->findOrFail($id);

        if (! $invitation->canCancel()) {
            throw new BadRequestHttpException(__('error.invitation.cannot_cancel'));
        }

        $invitation->markAsCancelled();

        return true;
    }

    /**
     * 초대 재발송
     */
    public function resend(int $id): UserInvitation
    {
        $tenantId = $this->tenantId();

        $invitation = UserInvitation::where('tenant_id', $tenantId)
            ->findOrFail($id);

        if ($invitation->status !== UserInvitation::STATUS_PENDING) {
            throw new BadRequestHttpException(__('error.invitation.cannot_resend'));
        }

        // 만료 기간 연장 및 토큰 재생성
        $invitation->token = UserInvitation::generateToken();
        $invitation->expires_at = UserInvitation::calculateExpiresAt();
        $invitation->save();

        // 이메일 재발송
        $this->sendInvitationEmail($invitation);

        return $invitation->load(['role:id,name', 'inviter:id,name']);
    }

    /**
     * 만료된 초대 일괄 처리 (스케줄러용)
     */
    public function expirePendingInvitations(): int
    {
        return UserInvitation::withoutGlobalScopes()
            ->expiredPending()
            ->update(['status' => UserInvitation::STATUS_EXPIRED]);
    }

    /**
     * 초대 이메일 발송
     */
    protected function sendInvitationEmail(UserInvitation $invitation): void
    {
        // TODO: 실제 메일 발송 로직 구현
        // Mail::to($invitation->email)->queue(new UserInvitationMail($invitation));

        // 현재는 로그로 대체
        \Log::info('User invitation email sent', [
            'email' => $invitation->email,
            'token' => $invitation->token,
            'tenant_id' => $invitation->tenant_id,
        ]);
    }
}
