<?php

namespace App\Services\Sales;

use App\Models\Sales\TenantProspect;
use App\Models\Tenants\Tenant;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class TenantProspectService
{
    /**
     * 명함 등록 (영업권 확보)
     */
    public function register(array $data, ?UploadedFile $businessCard = null, ?string $businessCardBase64 = null): TenantProspect
    {
        return DB::transaction(function () use ($data, $businessCard, $businessCardBase64) {
            $now = now();
            $expiresAt = $now->copy()->addMonths(TenantProspect::VALIDITY_MONTHS);
            $cooldownEndsAt = $expiresAt->copy()->addMonths(TenantProspect::COOLDOWN_MONTHS);

            // 명함 이미지 저장 (파일 업로드 또는 Base64)
            $businessCardPath = null;
            if ($businessCard) {
                $businessCardPath = $this->uploadBusinessCard($businessCard, $data['registered_by']);
            } elseif ($businessCardBase64) {
                $businessCardPath = $this->saveBase64Image($businessCardBase64, $data['registered_by']);
            }

            return TenantProspect::create([
                'business_number' => $data['business_number'],
                'company_name' => $data['company_name'],
                'ceo_name' => $data['ceo_name'] ?? null,
                'contact_phone' => $data['contact_phone'] ?? null,
                'contact_email' => $data['contact_email'] ?? null,
                'address' => $data['address'] ?? null,
                'registered_by' => $data['registered_by'],
                'business_card_path' => $businessCardPath,
                'status' => TenantProspect::STATUS_ACTIVE,
                'registered_at' => $now,
                'expires_at' => $expiresAt,
                'cooldown_ends_at' => $cooldownEndsAt,
                'memo' => $data['memo'] ?? null,
            ]);
        });
    }

    /**
     * 영업권 정보 수정
     */
    public function update(
        TenantProspect $prospect,
        array $data,
        ?UploadedFile $businessCard = null,
        ?UploadedFile $idCard = null,
        ?UploadedFile $bankbook = null
    ): TenantProspect {
        return DB::transaction(function () use ($prospect, $data, $businessCard, $idCard, $bankbook) {
            $updateData = [
                'company_name' => $data['company_name'],
                'ceo_name' => $data['ceo_name'] ?? null,
                'contact_phone' => $data['contact_phone'] ?? null,
                'contact_email' => $data['contact_email'] ?? null,
                'address' => $data['address'] ?? null,
                'memo' => $data['memo'] ?? null,
            ];

            // 명함 이미지 교체
            if ($businessCard) {
                if ($prospect->business_card_path) {
                    Storage::disk('tenant')->delete($prospect->business_card_path);
                }
                $updateData['business_card_path'] = $this->uploadAttachment($businessCard, $prospect->registered_by);
            }

            // 신분증 이미지 교체
            if ($idCard) {
                if ($prospect->id_card_path) {
                    Storage::disk('tenant')->delete($prospect->id_card_path);
                }
                $updateData['id_card_path'] = $this->uploadAttachment($idCard, $prospect->registered_by);
            }

            // 통장사본 이미지 교체
            if ($bankbook) {
                if ($prospect->bankbook_path) {
                    Storage::disk('tenant')->delete($prospect->bankbook_path);
                }
                $updateData['bankbook_path'] = $this->uploadAttachment($bankbook, $prospect->registered_by);
            }

            $prospect->update($updateData);

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

    /**
     * 테넌트로 전환
     */
    public function convertToTenant(TenantProspect $prospect, int $convertedBy): Tenant
    {
        return DB::transaction(function () use ($prospect, $convertedBy) {
            // 고유 테넌트 코드 생성 (T + 타임스탬프 + 랜덤)
            $tenantCode = 'T'.now()->format('ymd').strtoupper(substr(uniqid(), -4));

            // 테넌트 생성
            $tenant = Tenant::create([
                'company_name' => $prospect->company_name,
                'code' => $tenantCode,
                'business_num' => $prospect->business_number,
                'ceo_name' => $prospect->ceo_name,
                'phone' => $prospect->contact_phone,
                'email' => $prospect->contact_email,
                'address' => $prospect->address,
                'tenant_st_code' => 'trial',
                'tenant_type' => 'STD',  // STD = Standard (일반 고객)
            ]);

            // 전환한 사용자를 테넌트에 연결 (user_tenants)
            $tenant->users()->attach($convertedBy, [
                'is_active' => true,
                'is_default' => false,
                'joined_at' => now(),
            ]);

            // 영업권 상태 업데이트
            $prospect->update([
                'status' => TenantProspect::STATUS_CONVERTED,
                'tenant_id' => $tenant->id,
                'converted_at' => now(),
                'converted_by' => $convertedBy,
            ]);

            return $tenant;
        });
    }

    /**
     * 영업권 만료 처리 (배치용)
     */
    public function expireOldProspects(): int
    {
        return TenantProspect::where('status', TenantProspect::STATUS_ACTIVE)
            ->where('expires_at', '<=', now())
            ->update(['status' => TenantProspect::STATUS_EXPIRED]);
    }

    /**
     * 사업자번호로 등록 가능 여부 확인
     */
    public function canRegister(string $businessNumber, ?int $excludeId = null): array
    {
        $query = TenantProspect::where('business_number', $businessNumber);

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

        // 이미 전환된 경우
        $converted = (clone $query)->where('status', TenantProspect::STATUS_CONVERTED)->first();
        if ($converted) {
            return [
                'can_register' => false,
                'reason' => '이미 테넌트로 전환된 회사입니다.',
                'prospect' => $converted,
            ];
        }

        // 유효한 영업권이 있는 경우
        $active = (clone $query)->active()->first();
        if ($active) {
            return [
                'can_register' => false,
                'reason' => "이미 {$active->registeredBy->name}님이 영업권을 보유 중입니다. (만료: {$active->expires_at->format('Y-m-d')})",
                'prospect' => $active,
            ];
        }

        // 재등록 대기 중인 경우
        $inCooldown = (clone $query)
            ->where('status', TenantProspect::STATUS_EXPIRED)
            ->where('cooldown_ends_at', '>', now())
            ->first();

        if ($inCooldown) {
            return [
                'can_register' => false,
                'reason' => "재등록 대기 기간 중입니다. (등록 가능: {$inCooldown->cooldown_ends_at->format('Y-m-d')})",
                'prospect' => $inCooldown,
            ];
        }

        return [
            'can_register' => true,
            'reason' => null,
            'prospect' => null,
        ];
    }

    /**
     * 목록 조회
     */
    public function getProspects(array $filters = [])
    {
        $query = TenantProspect::with(['registeredBy', 'tenant']);

        // 검색
        if (! empty($filters['search'])) {
            $search = $filters['search'];
            $query->where(function ($q) use ($search) {
                $q->where('company_name', 'like', "%{$search}%")
                    ->orWhere('business_number', 'like', "%{$search}%")
                    ->orWhere('ceo_name', 'like', "%{$search}%")
                    ->orWhere('contact_phone', 'like', "%{$search}%");
            });
        }

        // 상태 필터
        if (! empty($filters['status'])) {
            if ($filters['status'] === 'active') {
                $query->active();
            } elseif ($filters['status'] === 'expired') {
                $query->where('status', TenantProspect::STATUS_EXPIRED);
            } elseif ($filters['status'] === 'converted') {
                $query->converted();
            }
        }

        // 특정 영업파트너
        if (! empty($filters['registered_by'])) {
            $query->byPartner($filters['registered_by']);
        }

        return $query->orderBy('created_at', 'desc');
    }

    /**
     * 통계 조회
     */
    public function getStats(?int $partnerId = null): array
    {
        $baseQuery = TenantProspect::query();

        if ($partnerId) {
            $baseQuery->byPartner($partnerId);
        }

        return [
            'total' => (clone $baseQuery)->count(),
            'active' => (clone $baseQuery)->active()->count(),
            'expired' => (clone $baseQuery)->where('status', TenantProspect::STATUS_EXPIRED)->count(),
            'converted' => (clone $baseQuery)->converted()->count(),
        ];
    }

    /**
     * 첨부파일 업로드 (명함, 신분증, 통장사본 등)
     */
    private function uploadAttachment(UploadedFile $file, int $userId): string
    {
        $storedName = Str::uuid().'.'.$file->getClientOriginalExtension();
        $filePath = "prospects/{$userId}/{$storedName}";

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

        return $filePath;
    }

    /**
     * 명함 이미지 업로드 (register에서 사용)
     */
    private function uploadBusinessCard(UploadedFile $file, int $userId): string
    {
        return $this->uploadAttachment($file, $userId);
    }

    /**
     * Base64 이미지 저장
     */
    private function saveBase64Image(string $base64Data, int $userId): ?string
    {
        // data:image/jpeg;base64,... 형식에서 데이터 추출
        if (preg_match('/^data:image\/(\w+);base64,/', $base64Data, $matches)) {
            $extension = $matches[1];
            $base64Data = preg_replace('/^data:image\/\w+;base64,/', '', $base64Data);
        } else {
            $extension = 'jpg';
        }

        $imageData = base64_decode($base64Data);
        if ($imageData === false) {
            return null;
        }

        $storedName = Str::uuid().'.'.$extension;
        $filePath = "prospects/{$userId}/{$storedName}";

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

        return $filePath;
    }

    /**
     * 명함 이미지 삭제
     */
    public function deleteBusinessCard(TenantProspect $prospect): bool
    {
        return $this->deleteAttachment($prospect, 'business_card');
    }

    /**
     * 첨부파일 삭제
     */
    public function deleteAttachment(TenantProspect $prospect, string $type): bool
    {
        $pathField = $type.'_path';

        if (! $prospect->$pathField) {
            return false;
        }

        if (Storage::disk('tenant')->exists($prospect->$pathField)) {
            Storage::disk('tenant')->delete($prospect->$pathField);
        }

        $prospect->update([$pathField => null]);

        return true;
    }
}
