<?php

namespace App\Services;

use App\Models\Commons\Menu;
use App\Models\Members\User;
use App\Models\Members\UserTenant;
use App\Models\Tenants\Department;
use App\Models\Tenants\Tenant;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;

class MemberService
{
    /**
     * 회원 조회(리스트)
     */
    public static function getMembers($request)
    {

        $pageNo = $request->page ?? 1;
        $pageSize = $request->size ?? 10;

        $query = User::whereHas('userTenants', function ($q) {
            $q->active();
        })->debug();
        $query = $query->paginate($pageSize, ['*'], 'page', $pageNo);

        return $query;

    }

    /**
     * 단일 회원 조회
     */
    public static function getMember(int $userNo)
    {
        $query = User::whereHas('userTenants', function ($q) {
            $q->active();
        })->where('id', $userNo);

        return $query->first();
    }

    /**
     * 내정보 확인
     */
    public static function getMyInfo()
    {
        $apiUser = app('api_user');
        $user = User::find($apiUser);
        $data['user'] = $user;

        $tenantId = app('tenant_id');
        if ($tenantId) {
            $tenant = Tenant::find($tenantId);
            $data['tenant'] = $tenant;
        }

        return $data;
    }

    /**
     * 내정보 수정
     */
    public static function getMyUpdate($request)
    {

        $apiUser = app('api_user');

        // 요청으로 받은 수정 데이터 유효성 검사
        $validatedData = $request->validate([
            'name' => 'sometimes|string|max:255',
            'phone' => 'sometimes|string|max:20',
            'email' => 'sometimes|email|max:100',
            'options' => 'nullable|json',
            'profile_photo_path' => 'nullable|string|max:255',
        ]);

        $user = User::find($apiUser);

        if (! $user) {
            return ['error' => 'User not found.', 'code' => 404];
        }

        // 사용자 정보 업데이트
        $user->update($validatedData);

        // 수정 성공 시 success 반환
        return 'success';
    }

    /**
     * 내 비밀번호 수정
     */
    public static function setMyPassword($request)
    {
        $apiUserId = app('api_user'); // 현재 로그인한 사용자 PK

        // 유효성 검사 (확인 비밀번호는 선택)
        $validated = $request->validate([
            'current_password' => 'required|string',
            'new_password' => 'required|string|min:8|max:64',
        ]);

        // 선택적으로 확인 비밀번호가 온 경우 체크
        if ($request->filled('new_password_confirmation') &&
            $request->input('new_password_confirmation') !== $validated['new_password']) {
            return ['error' => '비밀번호 확인이 일치하지 않습니다.', 'code' => 400];
        }

        // 유저 조회
        $user = User::find($apiUserId);
        if (! $user) {
            return ['error' => '유저를 찾을 수 없음', 'code' => 404];
        }

        // 현재 비밀번호 확인
        if (! Hash::check($validated['current_password'], $user->password)) {
            return ['error' => '현재 비밀번호가 일치하지 않습니다.', 'code' => 400];
        }

        // 기존 비밀번호와 동일한지 방지
        if (Hash::check($validated['new_password'], $user->password)) {
            return ['error' => '새 비밀번호가 기존 비밀번호와 동일합니다.', 'code' => 400];
        }

        // 비밀번호 변경 (guarded 우회: 직접 대입 + save)
        $user->password = Hash::make($validated['new_password']);
        $saved = $user->save();

        // (선택) 모든 기존 토큰 무효화하려면 아래 주석 해제
        // $user->tokens()->delete();

        return 'success';
    }

    /**
     * 나의 테넌트 목록
     */
    public static function getMyTenants()
    {

        $apiUser = app('api_user');
        $data = UserTenant::join('tenants', 'user_tenants.tenant_id', '=', 'tenants.id')
            ->where('user_tenants.user_id', $apiUser)
            ->get([
                'tenants.id',
                'tenants.company_name',
                'user_tenants.is_active',
                'user_tenants.is_default',
            ]);

        return $data;
    }

    /**
     * 나의 테넌트 전환
     */
    public static function switchMyTenant(int $tenantId)
    {

        $apiUser = app('api_user');

        // 1) 현재 유저의 기본 테넌트를 모두 해제
        UserTenant::withoutGlobalScopes()
            ->where('user_id', $apiUser)
            ->where('is_default', 1)
            ->update(['is_default' => 0]);

        // 2) 지정한 tenant_id를 기본 테넌트로 설정
        $updated = UserTenant::withoutGlobalScopes()
            ->where('user_id', $apiUser)
            ->where('tenant_id', $tenantId)
            ->update(['is_default' => 1]);

        if (! $updated) {
            return ['error' => '해당 테넌트를 찾을 수 없습니다.', 'code' => 404];
        }

        return 'success';
    }

    /**
     * 로그인 사용자 정보 조회 (테넌트 + 메뉴 권한 포함)
     */
    public static function getUserInfoForLogin(int $userId): array
    {
        // 1. 사용자 기본 정보 조회
        $user = User::find($userId);
        if (! $user) {
            throw new \Exception('사용자를 찾을 수 없습니다.');
        }

        // 기본 사용자 정보 (민감 정보 제외)
        $userInfo = [
            'id' => $user->id,
            'user_id' => $user->user_id,
            'name' => $user->name,
            'email' => $user->email,
            'phone' => $user->phone,
            'department' => null,
        ];

        // 2. 활성 테넌트 조회 (1순위: is_default=1, 2순위: is_active=1 첫 번째)
        $userTenants = UserTenant::with('tenant')
            ->where('user_id', $userId)
            ->where('is_active', 1)
            ->orderByDesc('is_default')
            ->orderBy('id')
            ->get();

        if ($userTenants->isEmpty()) {
            return [
                'user' => $userInfo,
                'tenant' => null,
                'menus' => [],
                'roles' => [],
            ];
        }

        $defaultUserTenant = $userTenants->first();
        $tenant = $defaultUserTenant->tenant;

        // 2-1. 소속 부서 조회 (tenant_user_profiles → departments)
        $profile = DB::table('tenant_user_profiles')
            ->where('user_id', $userId)
            ->where('tenant_id', $tenant->id)
            ->first();
        if ($profile && $profile->department_id) {
            $dept = DB::table('departments')->where('id', $profile->department_id)->first();
            if ($dept) {
                $userInfo['department'] = $dept->name;
            }
        }

        // 3. 테넌트 정보 구성
        $tenantInfo = [
            'id' => $tenant->id,
            'company_name' => $tenant->company_name,
            'business_num' => $tenant->business_num,
            'tenant_st_code' => $tenant->tenant_st_code,
            'other_tenants' => $userTenants->skip(1)->map(function ($ut) {
                return [
                    'tenant_id' => $ut->tenant_id,
                    'company_name' => $ut->tenant->company_name,
                    'business_num' => $ut->tenant->business_num,
                    'tenant_st_code' => $ut->tenant->tenant_st_code,
                ];
            })->values()->toArray(),
        ];

        // 4. 메뉴 권한 체크 (mng UserPermissionService와 동일한 로직)
        $now = now();

        // 4-1. 역할 권한 (user_roles 테이블)
        $rolePermissions = DB::table('user_roles')
            ->join('role_has_permissions', 'user_roles.role_id', '=', 'role_has_permissions.role_id')
            ->join('permissions', 'role_has_permissions.permission_id', '=', 'permissions.id')
            ->where('user_roles.user_id', $userId)
            ->where('user_roles.tenant_id', $tenant->id)
            ->whereNull('user_roles.deleted_at')
            ->where('permissions.name', 'like', 'menu:%.view')
            ->pluck('permissions.name')
            ->toArray();

        // 4-2. 부서 권한 (permission_overrides에서 Department 타입, effect=1)
        $deptPermissions = DB::table('department_user')
            ->join('permission_overrides', function ($join) use ($now) {
                $join->on('permission_overrides.model_id', '=', 'department_user.department_id')
                    ->where('permission_overrides.model_type', '=', Department::class)
                    ->whereNull('permission_overrides.deleted_at')
                    ->where('permission_overrides.effect', 1)
                    ->where(function ($q) use ($now) {
                        $q->whereNull('permission_overrides.effective_from')
                            ->orWhere('permission_overrides.effective_from', '<=', $now);
                    })
                    ->where(function ($q) use ($now) {
                        $q->whereNull('permission_overrides.effective_to')
                            ->orWhere('permission_overrides.effective_to', '>=', $now);
                    });
            })
            ->join('permissions', 'permissions.id', '=', 'permission_overrides.permission_id')
            ->whereNull('department_user.deleted_at')
            ->where('department_user.user_id', $userId)
            ->where('department_user.tenant_id', $tenant->id)
            ->where('permission_overrides.tenant_id', $tenant->id)
            ->where('permissions.name', 'like', 'menu:%.view')
            ->pluck('permissions.name')
            ->toArray();

        // 4-3. 개인 ALLOW 권한 (permission_overrides에서 User 타입, effect=1)
        // Note: mng는 App\Models\User를 사용하므로 하드코딩
        $personalAllows = DB::table('permission_overrides')
            ->join('permissions', 'permissions.id', '=', 'permission_overrides.permission_id')
            ->where('permission_overrides.model_type', 'App\\Models\\User')
            ->where('permission_overrides.model_id', $userId)
            ->where('permission_overrides.tenant_id', $tenant->id)
            ->where('permission_overrides.effect', 1)
            ->whereNull('permission_overrides.deleted_at')
            ->where(function ($q) use ($now) {
                $q->whereNull('permission_overrides.effective_from')
                    ->orWhere('permission_overrides.effective_from', '<=', $now);
            })
            ->where(function ($q) use ($now) {
                $q->whereNull('permission_overrides.effective_to')
                    ->orWhere('permission_overrides.effective_to', '>=', $now);
            })
            ->where('permissions.name', 'like', 'menu:%.view')
            ->pluck('permissions.name')
            ->toArray();

        // 4-4. 개인 DENY 권한 (permission_overrides에서 User 타입, effect=0)
        // Note: mng는 App\Models\User를 사용하므로 하드코딩
        $personalDenies = DB::table('permission_overrides')
            ->join('permissions', 'permissions.id', '=', 'permission_overrides.permission_id')
            ->where('permission_overrides.model_type', 'App\\Models\\User')
            ->where('permission_overrides.model_id', $userId)
            ->where('permission_overrides.tenant_id', $tenant->id)
            ->where('permission_overrides.effect', 0)
            ->whereNull('permission_overrides.deleted_at')
            ->where(function ($q) use ($now) {
                $q->whereNull('permission_overrides.effective_from')
                    ->orWhere('permission_overrides.effective_from', '<=', $now);
            })
            ->where(function ($q) use ($now) {
                $q->whereNull('permission_overrides.effective_to')
                    ->orWhere('permission_overrides.effective_to', '>=', $now);
            })
            ->where('permissions.name', 'like', 'menu:%.view')
            ->pluck('permissions.name')
            ->toArray();

        // 4-5. 최종 권한 계산: (역할 OR 부서 OR 개인ALLOW) - 개인DENY
        $allAllowed = array_unique(array_merge($rolePermissions, $deptPermissions, $personalAllows));
        $effectivePermissions = array_diff($allAllowed, $personalDenies);

        // 메뉴 ID 추출
        $allowedMenuIds = [];
        foreach ($effectivePermissions as $permName) {
            if (preg_match('/^menu:(\d+)\.view$/', $permName, $matches)) {
                $allowedMenuIds[] = (int) $matches[1];
            }
        }

        // 5. 메뉴 목록 조회 (권한 있는 메뉴만)
        $menus = [];
        if (! empty($allowedMenuIds)) {
            $menus = Menu::where('tenant_id', $tenant->id)
                ->where('is_active', 1)
                ->whereIn('id', $allowedMenuIds)
                ->orderBy('parent_id')
                ->orderBy('sort_order')
                ->get(['id', 'parent_id', 'name', 'url', 'icon', 'sort_order', 'is_external', 'external_url'])
                ->toArray();
        }

        // 6. 역할(Role) 정보 조회 (user_roles 테이블 사용 - mng와 동일)
        $roles = DB::table('user_roles')
            ->join('roles', 'user_roles.role_id', '=', 'roles.id')
            ->where('user_roles.user_id', $userId)
            ->where('user_roles.tenant_id', $tenant->id)
            ->whereNull('user_roles.deleted_at')
            ->select('roles.id', 'roles.name', 'roles.description')
            ->get()
            ->toArray();

        return [
            'user' => $userInfo,
            'tenant' => $tenantInfo,
            'menus' => $menus,
            'roles' => $roles,
        ];
    }
}
