<?php

namespace App\Services\Sales;

use App\Models\Department;
use App\Models\DepartmentUser;
use App\Models\Role;
use App\Models\Sales\SalesManagerDocument;
use App\Models\Sales\SalesPartner;
use App\Models\User;
use App\Models\UserRole;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class SalesManagerService
{
    /**
     * 영업파트너 역할 이름 목록
     */
    public const SALES_ROLES = ['sales', 'manager'];

    /**
     * 영업파트너 생성
     */
    public function createSalesPartner(array $data, array $documents = []): User
    {
        return DB::transaction(function () use ($data, $documents) {
            $tenantId = session('selected_tenant_id', 1);

            // 1. 사용자 생성
            $user = User::create([
                'user_id' => $data['user_id'] ?? null,
                'name' => $data['name'],
                'email' => $data['email'],
                'phone' => $data['phone'] ?? null,
                'password' => Hash::make($data['password']),
                'is_active' => false, // 승인 전까지 비활성
                'parent_id' => $data['parent_id'] ?? null, // 추천인(유치자)
                'approval_status' => 'pending', // 승인 대기 상태
                'must_change_password' => true,
            ]);

            // 2. 테넌트 연결
            $user->tenants()->attach($tenantId, [
                'is_active' => true,
                'is_default' => true,
                'joined_at' => now(),
            ]);

            // 3. 역할 할당
            if (! empty($data['role_ids'])) {
                $this->syncRoles($user, $tenantId, $data['role_ids']);
            }

            // 4. 영업팀 부서 자동 할당
            $this->assignSalesDepartment($user, $tenantId);

            // 4-1. 사업자 정보 저장 (선택)
            if (! empty($data['company_name']) || ! empty($data['biz_no']) || ! empty($data['address'])) {
                $partnerType = $data['partner_type'] ?? 'individual';
                $spData = [
                    'partner_code' => SalesPartner::generatePartnerCode(),
                    'partner_type' => $partnerType,
                    'status' => 'active',
                    'company_name' => $data['company_name'] ?? null,
                    'biz_no' => $data['biz_no'] ?? null,
                    'address' => $data['address'] ?? null,
                    'referrer_partner_id' => $data['referrer_partner_id'] ?? null,
                ];

                // 단체(corporate)이면 수당률 설정
                if ($partnerType === 'corporate') {
                    $spData['commission_rate'] = 30.00;
                    $spData['manager_commission_rate'] = 0;
                }

                SalesPartner::updateOrCreate(
                    ['user_id' => $user->id],
                    $spData
                );
            }

            // 5. 첨부 서류 저장
            if (! empty($documents)) {
                $this->uploadDocuments($user, $tenantId, $documents);
            }

            return $user;
        });
    }

    /**
     * 영업파트너 수정
     */
    public function updateSalesPartner(User $user, array $data, array $documents = []): User
    {
        return DB::transaction(function () use ($user, $data, $documents) {
            $tenantId = session('selected_tenant_id', 1);

            // 1. 기본 정보 업데이트 (parent_id는 변경 불가)
            $updateData = [
                'name' => $data['name'],
                'email' => $data['email'],
                'phone' => $data['phone'] ?? null,
            ];

            // 비밀번호 변경 시에만 업데이트
            if (! empty($data['password'])) {
                $updateData['password'] = Hash::make($data['password']);
            }

            $user->update($updateData);

            // 2. 역할 동기화
            if (isset($data['role_ids'])) {
                $this->syncRoles($user, $tenantId, $data['role_ids']);
            }

            // 2-1. 사업자 정보 업데이트
            $hasBizInfo = ! empty($data['company_name']) || ! empty($data['biz_no']) || ! empty($data['address']);
            $existingSp = SalesPartner::where('user_id', $user->id)->first();

            $hasPartnerType = ! empty($data['partner_type']);
            if ($hasBizInfo || $existingSp || $hasPartnerType) {
                $sp = $existingSp ?? new SalesPartner(['user_id' => $user->id]);
                if (! $sp->exists) {
                    $sp->partner_code = SalesPartner::generatePartnerCode();
                    $sp->partner_type = $data['partner_type'] ?? 'individual';
                    $sp->status = 'active';
                }
                // 승인 전에만 파트너 유형 변경 허용
                if ($hasPartnerType && $user->approval_status === 'pending') {
                    $newType = $data['partner_type'];
                    $sp->partner_type = $newType;
                    // 단체 → 수당률 설정, 개인 → 수당률 초기화
                    if ($newType === 'corporate') {
                        $sp->commission_rate = 30.00;
                        $sp->manager_commission_rate = 0;
                    } else {
                        $sp->commission_rate = $sp->getOriginal('commission_rate') ?? null;
                        $sp->manager_commission_rate = $sp->getOriginal('manager_commission_rate') ?? null;
                    }
                }
                $sp->company_name = $data['company_name'] ?? null;
                $sp->biz_no = $data['biz_no'] ?? null;
                $sp->address = $data['address'] ?? null;
                $sp->save();
            }

            // 3. 새 첨부 서류 저장
            if (! empty($documents)) {
                $this->uploadDocuments($user, $tenantId, $documents);
            }

            return $user->fresh();
        });
    }

    /**
     * 영업파트너 승인
     */
    public function approve(User $user, int $approverId): User
    {
        $user->update([
            'approval_status' => 'approved',
            'approved_by' => $approverId,
            'approved_at' => now(),
            'is_active' => true,
            'rejection_reason' => null,
        ]);

        return $user;
    }

    /**
     * 영업파트너 반려
     */
    public function reject(User $user, int $approverId, string $reason): User
    {
        $user->update([
            'approval_status' => 'rejected',
            'approved_by' => $approverId,
            'approved_at' => now(),
            'rejection_reason' => $reason,
            'is_active' => false,
        ]);

        return $user;
    }

    /**
     * 역할 위임
     *
     * @param  User  $fromUser  역할을 넘기는 파트너
     * @param  User  $toUser  역할을 받는 파트너
     * @param  string  $roleName  위임할 역할 (manager, recruiter 등)
     */
    public function delegateRole(User $fromUser, User $toUser, string $roleName): bool
    {
        $tenantId = session('selected_tenant_id', 1);

        return DB::transaction(function () use ($fromUser, $toUser, $roleName, $tenantId) {
            // 역할 조회
            $role = Role::where('tenant_id', $tenantId)
                ->where('name', $roleName)
                ->first();

            if (! $role) {
                throw new \InvalidArgumentException("역할을 찾을 수 없습니다: {$roleName}");
            }

            // fromUser가 해당 역할을 가지고 있는지 확인
            $hasRole = UserRole::where('user_id', $fromUser->id)
                ->where('tenant_id', $tenantId)
                ->where('role_id', $role->id)
                ->exists();

            if (! $hasRole) {
                throw new \InvalidArgumentException("{$fromUser->name}님이 {$roleName} 역할을 보유하고 있지 않습니다.");
            }

            // fromUser에서 역할 제거
            UserRole::where('user_id', $fromUser->id)
                ->where('tenant_id', $tenantId)
                ->where('role_id', $role->id)
                ->delete();

            // toUser에게 역할 추가 (이미 있으면 무시)
            UserRole::firstOrCreate([
                'user_id' => $toUser->id,
                'tenant_id' => $tenantId,
                'role_id' => $role->id,
            ], [
                'assigned_at' => now(),
            ]);

            return true;
        });
    }

    /**
     * 역할 부여
     */
    public function assignRole(User $user, string $roleName): bool
    {
        $tenantId = session('selected_tenant_id', 1);

        $role = Role::where('tenant_id', $tenantId)
            ->where('name', $roleName)
            ->first();

        if (! $role) {
            return false;
        }

        UserRole::firstOrCreate([
            'user_id' => $user->id,
            'tenant_id' => $tenantId,
            'role_id' => $role->id,
        ], [
            'assigned_at' => now(),
        ]);

        return true;
    }

    /**
     * 역할 제거
     */
    public function removeRole(User $user, string $roleName): bool
    {
        $tenantId = session('selected_tenant_id', 1);

        $role = Role::where('tenant_id', $tenantId)
            ->where('name', $roleName)
            ->first();

        if (! $role) {
            return false;
        }

        UserRole::where('user_id', $user->id)
            ->where('tenant_id', $tenantId)
            ->where('role_id', $role->id)
            ->delete();

        return true;
    }

    /**
     * 영업팀 부서 자동 할당
     */
    private function assignSalesDepartment(User $user, int $tenantId): void
    {
        // "영업팀" 부서를 찾거나 생성
        $salesDepartment = Department::firstOrCreate(
            [
                'tenant_id' => $tenantId,
                'name' => '영업팀',
            ],
            [
                'code' => 'SALES',
                'description' => '영업파트너 부서',
                'is_active' => true,
                'sort_order' => 100,
                'created_by' => auth()->id(),
            ]
        );

        // 사용자-부서 연결 (이미 있으면 무시)
        DepartmentUser::firstOrCreate(
            [
                'tenant_id' => $tenantId,
                'department_id' => $salesDepartment->id,
                'user_id' => $user->id,
            ],
            [
                'is_primary' => true,
                'joined_at' => now(),
                'created_by' => auth()->id(),
            ]
        );
    }

    /**
     * 역할 동기화
     */
    public function syncRoles(User $user, int $tenantId, array $roleIds): void
    {
        // 영업 관련 역할만 처리 (다른 역할은 유지)
        $salesRoleIds = Role::where('tenant_id', $tenantId)
            ->whereIn('name', self::SALES_ROLES)
            ->pluck('id')
            ->toArray();

        // 제거할 역할 soft delete (새 역할 목록에 없는 것들)
        $roleIdsToRemove = array_diff($salesRoleIds, $roleIds);
        if (! empty($roleIdsToRemove)) {
            UserRole::where('user_id', $user->id)
                ->where('tenant_id', $tenantId)
                ->whereIn('role_id', $roleIdsToRemove)
                ->delete();
        }

        // 새 역할 추가 (이미 있으면 복원, 없으면 생성)
        foreach ($roleIds as $roleId) {
            // soft delete된 레코드 포함하여 검색
            $existingRole = UserRole::withTrashed()
                ->where('user_id', $user->id)
                ->where('tenant_id', $tenantId)
                ->where('role_id', $roleId)
                ->first();

            if ($existingRole) {
                // 이미 존재하면 복원 (soft delete된 경우)
                if ($existingRole->trashed()) {
                    $existingRole->restore();
                }
            } else {
                // 새로 생성
                UserRole::create([
                    'user_id' => $user->id,
                    'tenant_id' => $tenantId,
                    'role_id' => $roleId,
                    'assigned_at' => now(),
                ]);
            }
        }
    }

    /**
     * 서류 업로드
     */
    public function uploadDocuments(User $user, int $tenantId, array $documents): array
    {
        $uploaded = [];

        foreach ($documents as $doc) {
            if (! isset($doc['file']) || ! $doc['file'] instanceof UploadedFile) {
                continue;
            }

            $file = $doc['file'];
            $documentType = $doc['document_type'] ?? 'other';
            $description = $doc['description'] ?? null;

            // 파일 저장
            $storedName = Str::uuid().'.'.$file->getClientOriginalExtension();
            $filePath = "sales-partners/{$user->id}/{$storedName}";

            Storage::disk('tenant')->put($filePath, file_get_contents($file));

            // DB 저장
            $document = SalesManagerDocument::create([
                'tenant_id' => $tenantId,
                'user_id' => $user->id,
                'file_path' => $filePath,
                'original_name' => $file->getClientOriginalName(),
                'stored_name' => $storedName,
                'mime_type' => $file->getMimeType(),
                'file_size' => $file->getSize(),
                'document_type' => $documentType,
                'description' => $description,
                'uploaded_by' => auth()->id(),
            ]);

            $uploaded[] = $document;
        }

        return $uploaded;
    }

    /**
     * 서류 삭제
     */
    public function deleteDocument(SalesManagerDocument $document): bool
    {
        // 물리 파일 삭제
        if ($document->existsInStorage()) {
            Storage::disk('tenant')->delete($document->file_path);
        }

        // DB 삭제
        $document->deleted_by = auth()->id();
        $document->save();

        return $document->delete();
    }

    /**
     * 영업파트너 목록 조회
     */
    public function getSalesPartners(array $filters = [])
    {
        $tenantId = session('selected_tenant_id', 1);

        // 영업 관련 역할을 가진 사용자 조회 (비활성 사용자도 포함 - 관리 목적)
        $query = User::query()
            ->whereHas('userRoles', function ($q) use ($tenantId) {
                $q->where('tenant_id', $tenantId)
                    ->whereHas('role', function ($rq) {
                        $rq->whereIn('name', self::SALES_ROLES);
                    });
            })
            ->with(['parent', 'userRoles.role', 'salesDocuments', 'salesPartner']);

        // 검색
        if (! empty($filters['search'])) {
            $search = $filters['search'];
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                    ->orWhere('user_id', 'like', "%{$search}%")
                    ->orWhere('email', 'like', "%{$search}%")
                    ->orWhere('phone', 'like', "%{$search}%");
            });
        }

        // 역할 필터
        if (! empty($filters['role'])) {
            $roleName = $filters['role'];
            $query->whereHas('userRoles', function ($q) use ($tenantId, $roleName) {
                $q->where('tenant_id', $tenantId)
                    ->whereHas('role', function ($rq) use ($roleName) {
                        $rq->where('name', $roleName);
                    });
            });
        }

        // 승인 상태 필터
        if (! empty($filters['approval_status'])) {
            $query->where('approval_status', $filters['approval_status']);
        }

        // 활성 상태 필터 (지정 시에만 적용)
        if (isset($filters['is_active'])) {
            $query->where('is_active', $filters['is_active']);
        }

        // 유치자(추천인) 필터 - 현재 로그인한 사용자가 유치한 파트너만
        if (! empty($filters['parent_id'])) {
            $query->where('parent_id', $filters['parent_id']);
        }

        return $query->orderBy('name');
    }

    /**
     * 추천인(유치자) 후보 목록
     * 승인된 모든 영업파트너가 추천인이 될 수 있음
     */
    public function getRecommenderCandidates(?int $excludeId = null)
    {
        $tenantId = session('selected_tenant_id', 1);

        $query = User::query()
            ->where('is_active', true)
            ->where('approval_status', 'approved')
            ->whereHas('userRoles', function ($q) use ($tenantId) {
                $q->where('tenant_id', $tenantId)
                    ->whereHas('role', function ($rq) {
                        $rq->whereIn('name', self::SALES_ROLES);
                    });
            });

        if ($excludeId) {
            $query->where('id', '!=', $excludeId);
        }

        return $query->orderBy('name')->get();
    }

    /**
     * 역할 위임 가능한 하위 파트너 목록
     */
    public function getDelegationCandidates(User $user)
    {
        return User::query()
            ->where('parent_id', $user->id)
            ->where('is_active', true)
            ->where('approval_status', 'approved')
            ->orderBy('name')
            ->get();
    }

    /**
     * 영업 역할 목록 조회
     */
    public function getSalesRoles()
    {
        $tenantId = session('selected_tenant_id', 1);

        return Role::where('tenant_id', $tenantId)
            ->whereIn('name', self::SALES_ROLES)
            ->get();
    }

    /**
     * 통계 조회
     */
    public function getStats(?int $parentId = null): array
    {
        $tenantId = session('selected_tenant_id', 1);

        $baseQuery = User::query()
            ->whereHas('userRoles', function ($q) use ($tenantId) {
                $q->where('tenant_id', $tenantId)
                    ->whereHas('role', function ($rq) {
                        $rq->whereIn('name', self::SALES_ROLES);
                    });
            });

        // 유치자 기준 필터
        if ($parentId) {
            $baseQuery->where('parent_id', $parentId);
        }

        return [
            'total' => (clone $baseQuery)->count(),
            'pending' => (clone $baseQuery)->where('approval_status', 'pending')->count(),
            'approved' => (clone $baseQuery)->where('approval_status', 'approved')->count(),
            'sales' => (clone $baseQuery)
                ->whereHas('userRoles.role', fn ($q) => $q->where('name', 'sales'))
                ->count(),
            'manager' => (clone $baseQuery)
                ->whereHas('userRoles.role', fn ($q) => $q->where('name', 'manager'))
                ->count(),
        ];
    }

    /**
     * 승인 대기 통계 조회 (본사 관리자용)
     */
    public function getApprovalStats(): array
    {
        $tenantId = session('selected_tenant_id', 1);

        $baseQuery = User::query()
            ->whereHas('userRoles', function ($q) use ($tenantId) {
                $q->where('tenant_id', $tenantId)
                    ->whereHas('role', function ($rq) {
                        $rq->whereIn('name', self::SALES_ROLES);
                    });
            });

        return [
            'pending' => (clone $baseQuery)->where('approval_status', 'pending')->count(),
            'approved_today' => (clone $baseQuery)
                ->where('approval_status', 'approved')
                ->whereDate('approved_at', today())
                ->count(),
            'rejected_today' => (clone $baseQuery)
                ->where('approval_status', 'rejected')
                ->whereDate('approved_at', today())
                ->count(),
        ];
    }

    /**
     * 파트너의 계층 레벨 계산
     */
    public function getPartnerLevel(User $user): int
    {
        $level = 1;
        $current = $user;

        while ($current->parent_id !== null) {
            $level++;
            $current = $current->parent;

            // 무한 루프 방지
            if ($level > 100) {
                break;
            }
        }

        return $level;
    }

    /**
     * 하위 파트너 전체 목록 (재귀)
     */
    public function getAllDescendants(User $user, int $maxDepth = 10): array
    {
        $descendants = [];
        $this->collectDescendants($user, $descendants, 1, $maxDepth);

        return $descendants;
    }

    private function collectDescendants(User $user, array &$descendants, int $currentDepth, int $maxDepth): void
    {
        if ($currentDepth > $maxDepth) {
            return;
        }

        $children = User::where('parent_id', $user->id)
            ->where('approval_status', 'approved')
            ->get();

        foreach ($children as $child) {
            $descendants[] = [
                'user' => $child,
                'level' => $currentDepth,
            ];
            $this->collectDescendants($child, $descendants, $currentDepth + 1, $maxDepth);
        }
    }
}
