<?php

namespace App\Services;

use App\Models\CompanyRequest;
use App\Models\Members\UserTenant;
use App\Models\Tenants\Tenant;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;

class CompanyService extends Service
{
    public function __construct(
        private readonly BarobillService $barobillService,
        private readonly TenantService $tenantService
    ) {}

    // =========================================================================
    // 사업자등록번호 검증
    // =========================================================================

    /**
     * 사업자등록번호 유효성 검사
     */
    public function checkBusinessNumber(string $businessNumber): array
    {
        // 바로빌 서비스를 통한 사업자등록번호 검증
        $result = $this->barobillService->checkBusinessNumber($businessNumber);

        // 이미 등록된 회사인지 확인
        $normalizedNumber = preg_replace('/[^0-9]/', '', $businessNumber);
        $existingTenant = Tenant::query()
            ->where('business_num', $normalizedNumber)
            ->orWhere('business_num', $this->formatBusinessNumber($normalizedNumber))
            ->first();

        if ($existingTenant) {
            $result['already_exists'] = true;
            $result['existing_company_name'] = $existingTenant->company_name;
        } else {
            $result['already_exists'] = false;
            $result['existing_company_name'] = null;
        }

        return $result;
    }

    /**
     * 사업자등록번호 포맷 (하이픈 추가)
     */
    private function formatBusinessNumber(string $number): string
    {
        $number = preg_replace('/[^0-9]/', '', $number);
        if (strlen($number) === 10) {
            return substr($number, 0, 3).'-'.substr($number, 3, 2).'-'.substr($number, 5, 5);
        }

        return $number;
    }

    // =========================================================================
    // 회사 추가 신청
    // =========================================================================

    /**
     * 회사 추가 신청 생성
     */
    public function createRequest(array $data): CompanyRequest
    {
        $userId = $this->apiUserId();
        $businessNumber = preg_replace('/[^0-9]/', '', $data['business_number']);

        // 중복 신청 확인 (대기중인 신청이 있는지)
        $existingRequest = CompanyRequest::query()
            ->where('user_id', $userId)
            ->where('business_number', $businessNumber)
            ->where('status', CompanyRequest::STATUS_PENDING)
            ->first();

        if ($existingRequest) {
            throw new BadRequestHttpException(__('error.company.request_already_exists'));
        }

        // 이미 등록된 회사인지 확인
        $existingTenant = Tenant::query()
            ->where('business_num', $businessNumber)
            ->orWhere('business_num', $this->formatBusinessNumber($businessNumber))
            ->first();

        if ($existingTenant) {
            // 이미 존재하는 회사에 합류 신청
            // 해당 회사의 관리자에게 알림을 보내거나 별도 처리 가능
            throw new BadRequestHttpException(__('error.company.already_registered'));
        }

        // 사업자등록번호 유효성 검사
        $validationResult = $this->barobillService->checkBusinessNumber($businessNumber);

        return CompanyRequest::create([
            'user_id' => $userId,
            'business_number' => $businessNumber,
            'company_name' => $data['company_name'],
            'ceo_name' => $data['ceo_name'] ?? $validationResult['ceo_name'] ?? null,
            'address' => $data['address'] ?? null,
            'phone' => $data['phone'] ?? null,
            'email' => $data['email'] ?? null,
            'message' => $data['message'] ?? null,
            'status' => CompanyRequest::STATUS_PENDING,
            'barobill_response' => $validationResult,
        ]);
    }

    /**
     * 회사 추가 신청 목록 (관리자용)
     */
    public function getRequests(array $params): LengthAwarePaginator
    {
        $query = CompanyRequest::query()
            ->with(['user:id,name,email', 'approver:id,name,email', 'createdTenant:id,company_name,code']);

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

        // 검색 (사업자번호, 회사명, 신청자명)
        if (! empty($params['search'])) {
            $search = $params['search'];
            $query->where(function ($q) use ($search) {
                $q->where('business_number', 'like', "%{$search}%")
                    ->orWhere('company_name', 'like', "%{$search}%")
                    ->orWhereHas('user', function ($uq) use ($search) {
                        $uq->where('name', 'like', "%{$search}%");
                    });
            });
        }

        // 날짜 범위 필터
        if (! empty($params['start_date'])) {
            $query->whereDate('created_at', '>=', $params['start_date']);
        }
        if (! empty($params['end_date'])) {
            $query->whereDate('created_at', '<=', $params['end_date']);
        }

        // 정렬
        $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 getRequest(int $id): CompanyRequest
    {
        return CompanyRequest::query()
            ->with(['user:id,name,email', 'approver:id,name,email', 'createdTenant:id,company_name,code'])
            ->findOrFail($id);
    }

    // =========================================================================
    // 신청 처리 (관리자)
    // =========================================================================

    /**
     * 회사 추가 신청 승인
     */
    public function approveRequest(int $id): CompanyRequest
    {
        $userId = $this->apiUserId();
        $request = CompanyRequest::findOrFail($id);

        if (! $request->is_pending) {
            throw new BadRequestHttpException(__('error.company.request_not_pending'));
        }

        return DB::transaction(function () use ($request, $userId) {
            // 테넌트 생성
            $tenantCode = $this->tenantService->generateTenantCode($request->company_name);
            $tenant = Tenant::create([
                'code' => $tenantCode,
                'company_name' => $request->company_name,
                'business_num' => $request->business_number,
                'ceo_name' => $request->ceo_name,
                'address' => $request->address,
                'phone' => $request->phone,
                'email' => $request->email,
            ]);

            // 신청자를 테넌트에 연결
            UserTenant::create([
                'user_id' => $request->user_id,
                'tenant_id' => $tenant->id,
                'is_active' => true,
                'is_default' => true,
                'joined_at' => now(),
            ]);

            // 신청 승인 처리
            $request->approve($userId, $tenant->id);

            return $request->fresh(['user', 'approver', 'createdTenant']);
        });
    }

    /**
     * 회사 추가 신청 반려
     */
    public function rejectRequest(int $id, ?string $reason = null): CompanyRequest
    {
        $userId = $this->apiUserId();
        $request = CompanyRequest::findOrFail($id);

        if (! $request->is_pending) {
            throw new BadRequestHttpException(__('error.company.request_not_pending'));
        }

        $request->reject($userId, $reason);

        return $request->fresh(['user', 'approver']);
    }

    // =========================================================================
    // 내 신청 목록 (사용자용)
    // =========================================================================

    /**
     * 내 회사 추가 신청 목록
     */
    public function getMyRequests(array $params): LengthAwarePaginator
    {
        $userId = $this->apiUserId();

        $query = CompanyRequest::query()
            ->where('user_id', $userId)
            ->with(['approver:id,name,email', 'createdTenant:id,company_name,code']);

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

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

        $perPage = $params['per_page'] ?? 20;

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