<?php

namespace App\Http\Controllers\Sales;

use App\Http\Controllers\Controller;
use App\Models\Sales\SalesCommission;
use App\Models\Sales\SalesPartner;
use App\Models\Sales\SalesScenarioChecklist;
use App\Models\Sales\SalesTenantManagement;
use App\Models\Sales\TenantProspect;
use App\Models\User;
use App\Services\SalesCommissionService;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\View\View;

/**
 * 관리자용 전체 영업파트너 고객 관리 컨트롤러
 * 관리자/슈퍼관리자만 접근 가능
 */
class AdminProspectController extends Controller
{
    /**
     * 관리자 권한 체크
     */
    private function checkAdminAccess(): void
    {
        if (! auth()->user()->isAdmin() && ! auth()->user()->isSuperAdmin()) {
            abort(403, '관리자만 접근할 수 있습니다.');
        }
    }

    /**
     * 필드명에 따라 payment_type 결정 (1차→deposit, 2차→balance)
     */
    private function getPaymentTypeForField(string $field): string
    {
        return in_array($field, ['second_payment_at', 'second_partner_paid_at'])
            ? SalesCommission::PAYMENT_BALANCE
            : SalesCommission::PAYMENT_DEPOSIT;
    }

    /**
     * deposit/balance 커미션 레코드를 병합하여 뷰용 객체 반환
     */
    private function loadMergedCommission(?SalesTenantManagement $management): ?object
    {
        if (! $management) {
            return null;
        }

        $commissions = SalesCommission::where('management_id', $management->id)->get();
        if ($commissions->isEmpty()) {
            return null;
        }

        $deposit = $commissions->firstWhere('payment_type', SalesCommission::PAYMENT_DEPOSIT);
        $balance = $commissions->firstWhere('payment_type', SalesCommission::PAYMENT_BALANCE);

        // balance 레코드가 없으면 기존 단일 레코드 그대로 반환 (하위호환)
        if (! $balance) {
            return $deposit ?? $commissions->first();
        }

        // 1차 필드는 deposit, 2차 필드는 balance에서 가져옴
        $merged = new \stdClass;
        $merged->first_payment_at = $deposit?->first_payment_at;
        $merged->first_partner_paid_at = $deposit?->first_partner_paid_at;
        $merged->second_payment_at = $balance->second_payment_at;
        $merged->second_partner_paid_at = $balance->second_partner_paid_at;
        $merged->first_subscription_at = $deposit?->first_subscription_at;
        $merged->manager_paid_at = $deposit?->manager_paid_at;
        $merged->referrer_commission = ($deposit?->referrer_commission ?? 0) + ($balance?->referrer_commission ?? 0);

        return $merged;
    }

    /**
     * 전체 고객 목록 페이지
     */
    public function index(Request $request): View|Response
    {
        $this->checkAdminAccess();
        if ($request->header('HX-Request')) {
            return response('', 200)->header('HX-Redirect', route('sales.admin-prospects.index'));
        }

        $data = $this->getIndexData($request);

        return view('sales.admin-prospects.index', $data);
    }

    /**
     * 고객 상세 모달
     */
    public function modalShow(int $id): View
    {
        $this->checkAdminAccess();

        $prospect = TenantProspect::with(['registeredBy', 'tenant'])->findOrFail($id);

        // 진행률
        $progress = SalesScenarioChecklist::getProspectProgress($prospect->id);
        $prospect->sales_progress = $progress['sales']['percentage'];
        $prospect->manager_progress = $progress['manager']['percentage'];

        // management 정보
        $management = SalesTenantManagement::findOrCreateByProspect($prospect->id);
        $management->load(['contractProducts.product', 'contractProducts.category']);

        // 수당 정보
        $commission = $this->loadMergedCommission($management);

        // 수당 정산 전체 레코드 (상세보기용)
        $commissions = SalesCommission::where('management_id', $management->id)
            ->with(['partner.user', 'manager'])
            ->get();

        // 파트너 타입
        $partnerType = $management->salesPartner?->partner_type;
        if (! $partnerType && $prospect->registered_by) {
            $partnerType = SalesPartner::where('user_id', $prospect->registered_by)->value('partner_type');
        }
        $partnerType = $partnerType ?? 'individual';

        return view('sales.admin-prospects.partials.show-modal', compact('prospect', 'management', 'progress', 'commission', 'commissions', 'partnerType'));
    }

    /**
     * 콘텐츠 새로고침 (HTMX)
     */
    public function refresh(Request $request): View
    {
        $this->checkAdminAccess();

        $data = $this->getIndexData($request);

        return view('sales.admin-prospects.partials.content', $data);
    }

    /**
     * index 데이터 조회 (공통)
     */
    private function getIndexData(Request $request): array
    {
        // 영업 역할을 가진 사용자 목록 (영업파트너)
        $salesPartners = User::whereHas('userRoles', function ($q) {
            $q->whereHas('role', function ($rq) {
                $rq->whereIn('name', ['sales', 'manager']);
            });
        })->orderBy('name')->get();

        // 필터
        $filters = [
            'search' => $request->get('search'),
            'status' => $request->get('status'),
            'registered_by' => $request->get('registered_by'),
        ];

        // 쿼리 빌드
        $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}%");
            });
        }

        // 상태 필터
        $isProgressCompleteFilter = ($filters['status'] === 'progress_complete');
        $isHandoverFilter = ($filters['status'] === 'handover');
        if (! empty($filters['status']) && ! $isProgressCompleteFilter && ! $isHandoverFilter) {
            $query->where('status', $filters['status']);
        }

        // 인계완료 필터: hq_status가 handover인 prospect만
        if ($isHandoverFilter) {
            $handoverProspectIds = SalesTenantManagement::where('hq_status', 'handover')->pluck('tenant_prospect_id');
            $query->whereIn('id', $handoverProspectIds);
        }

        // 영업파트너 필터
        if (! empty($filters['registered_by'])) {
            $query->where('registered_by', $filters['registered_by']);
        }

        // progress_complete 필터: 전체 조회 후 PHP에서 필터링
        if ($isProgressCompleteFilter) {
            $allProspects = $query->orderByDesc('created_at')->get();

            // 진행률 계산 및 부가정보 세팅
            foreach ($allProspects as $prospect) {
                $progress = SalesScenarioChecklist::getProspectProgress($prospect->id);
                $prospect->sales_progress = $progress['sales']['percentage'];
                $prospect->manager_progress = $progress['manager']['percentage'];

                if ($progress['sales']['percentage'] === 100 && $progress['manager']['percentage'] === 100) {
                    SalesScenarioChecklist::checkAndConvertProspectStatus($prospect->id);
                    $prospect->refresh();
                }

                $management = SalesTenantManagement::where('tenant_prospect_id', $prospect->id)->first();
                $prospect->hq_status = $management?->hq_status ?? 'pending';
                $prospect->hq_status_label = $management?->hq_status_label ?? '대기';
                $prospect->manager_user = $management?->manager;
                $prospect->contracted_at = $management?->contracted_at;
                $prospect->handover_at = $management?->handover_at;

                $prospect->commission = $this->loadMergedCommission($management);

                // 파트너 타입: management → registered_by 순으로 조회
                $partnerType = $management?->salesPartner?->partner_type;
                if (! $partnerType && $prospect->registered_by) {
                    $partnerType = SalesPartner::where('user_id', $prospect->registered_by)->value('partner_type');
                }
                $prospect->partner_type = $partnerType ?? 'individual';
            }

            // 두 시나리오 모두 100%인 것만 필터링
            $filtered = $allProspects->filter(function ($prospect) {
                return $prospect->sales_progress === 100 && $prospect->manager_progress === 100;
            });

            // 수동 페이지네이션
            $page = request()->get('page', 1);
            $perPage = 20;
            $prospects = new \Illuminate\Pagination\LengthAwarePaginator(
                $filtered->forPage($page, $perPage)->values(),
                $filtered->count(),
                $perPage,
                $page,
                ['path' => request()->url(), 'query' => request()->query()]
            );
        } else {
            $prospects = $query->orderByDesc('created_at')->paginate(20);

            // 각 가망고객의 진행률 계산 및 상태 자동 전환
            foreach ($prospects as $prospect) {
                $progress = SalesScenarioChecklist::getProspectProgress($prospect->id);
                $prospect->sales_progress = $progress['sales']['percentage'];
                $prospect->manager_progress = $progress['manager']['percentage'];

                // 진행률 100% 시 상태 자동 전환 체크
                if ($progress['sales']['percentage'] === 100 && $progress['manager']['percentage'] === 100) {
                    SalesScenarioChecklist::checkAndConvertProspectStatus($prospect->id);
                    $prospect->refresh();
                }

                // management 정보
                $management = SalesTenantManagement::where('tenant_prospect_id', $prospect->id)->first();
                $prospect->hq_status = $management?->hq_status ?? 'pending';
                $prospect->hq_status_label = $management?->hq_status_label ?? '대기';
                $prospect->manager_user = $management?->manager;
                $prospect->contracted_at = $management?->contracted_at;
                $prospect->handover_at = $management?->handover_at;

                // 수당 정보 (management가 있는 경우)
                $prospect->commission = $this->loadMergedCommission($management);

                // 파트너 타입: management → registered_by 순으로 조회
                $partnerType = $management?->salesPartner?->partner_type;
                if (! $partnerType && $prospect->registered_by) {
                    $partnerType = SalesPartner::where('user_id', $prospect->registered_by)->value('partner_type');
                }
                $prospect->partner_type = $partnerType ?? 'individual';
            }
        }

        // 진행완료 건수 계산 (전체 prospect 중 두 시나리오 모두 100%인 건수)
        $progressCompleteCount = 0;
        $allForStats = TenantProspect::all();
        foreach ($allForStats as $p) {
            $prog = SalesScenarioChecklist::getProspectProgress($p->id);
            if ($prog['sales']['percentage'] === 100 && $prog['manager']['percentage'] === 100) {
                $progressCompleteCount++;
            }
        }

        // 전체 통계
        $stats = [
            'total' => TenantProspect::count(),
            'active' => TenantProspect::where('status', TenantProspect::STATUS_ACTIVE)->count(),
            'completed' => TenantProspect::where('status', TenantProspect::STATUS_COMPLETED)->count(),
            'handover' => SalesTenantManagement::where('hq_status', 'handover')->count(),
        ];

        // 영업파트너별 통계
        $partnerStats = TenantProspect::selectRaw('registered_by, COUNT(*) as total')
            ->groupBy('registered_by')
            ->with('registeredBy')
            ->get()
            ->map(function ($item) {
                return [
                    'user' => $item->registeredBy,
                    'total' => $item->total,
                ];
            });

        $isSuperAdmin = auth()->user()->isSuperAdmin();

        return compact('prospects', 'stats', 'salesPartners', 'partnerStats', 'filters', 'isSuperAdmin');
    }

    /**
     * 개발 진행 상태 변경
     */
    public function updateHqStatus(int $id, Request $request)
    {
        $this->checkAdminAccess();

        $request->validate([
            'hq_status' => 'required|in:'.implode(',', array_keys(SalesTenantManagement::$hqStatusLabels)),
        ]);

        $prospect = TenantProspect::findOrFail($id);
        $management = SalesTenantManagement::findOrCreateByProspect($prospect->id);

        $newStatus = $request->input('hq_status');
        $updateData = ['hq_status' => $newStatus];

        // 인계로 변경 시 오늘 날짜 자동 세팅, 다른 상태로 변경 시 초기화
        if ($newStatus === SalesTenantManagement::HQ_STATUS_HANDOVER) {
            $updateData['handover_at'] = now();
        } else {
            $updateData['handover_at'] = null;
        }

        $management->update($updateData);

        return response()->json([
            'success' => true,
            'hq_status' => $management->hq_status,
            'hq_status_label' => $management->hq_status_label,
            'handover_at' => $management->handover_at?->format('Y-m-d'),
        ]);
    }

    /**
     * 계약일 변경
     */
    public function updateContractedDate(int $id, Request $request)
    {
        $this->checkAdminAccess();

        $request->validate([
            'contracted_at' => 'nullable|date',
        ]);

        $prospect = TenantProspect::findOrFail($id);
        $management = SalesTenantManagement::findOrCreateByProspect($prospect->id);

        $management->update([
            'contracted_at' => $request->input('contracted_at') ?: null,
        ]);

        return response()->json([
            'success' => true,
            'contracted_at' => $management->contracted_at?->format('Y-m-d'),
        ]);
    }

    /**
     * 인계일 수동 변경
     */
    public function updateHandoverDate(int $id, Request $request)
    {
        $this->checkAdminAccess();

        $request->validate([
            'handover_at' => 'required|date',
        ]);

        $prospect = TenantProspect::findOrFail($id);
        $management = SalesTenantManagement::findOrCreateByProspect($prospect->id);

        $management->update([
            'handover_at' => $request->input('handover_at'),
        ]);

        return response()->json([
            'success' => true,
            'handover_at' => $management->handover_at?->format('Y-m-d'),
        ]);
    }

    /**
     * 수당 날짜 기록/수정
     */
    public function updateCommissionDate(int $id, Request $request)
    {
        $this->checkAdminAccess();

        $request->validate([
            'field' => 'required|in:first_payment_at,first_partner_paid_at,second_payment_at,second_partner_paid_at,first_subscription_at,manager_paid_at',
            'date' => 'nullable|date',
        ]);

        $prospect = TenantProspect::findOrFail($id);
        $management = SalesTenantManagement::findOrCreateByProspect($prospect->id);

        $field = $request->input('field');

        // 1차 필드 → deposit 레코드, 2차 필드 → balance 레코드
        $paymentType = $this->getPaymentTypeForField($field);

        // 파트너 resolve → 요율 결정
        $partner = $management->salesPartner;
        if (! $partner && $prospect->registered_by) {
            $partner = SalesPartner::where('user_id', $prospect->registered_by)->first();
        }
        $isGroup = $partner?->isGroup() ?? false;
        $partnerRate = $partner?->commission_rate
            ?? ($isGroup ? SalesCommissionService::DEFAULT_GROUP_RATE : SalesCommissionService::DEFAULT_PARTNER_RATE);
        $referrerRate = $isGroup
            ? SalesCommissionService::DEFAULT_GROUP_REFERRER_RATE
            : SalesCommissionService::DEFAULT_INDIVIDUAL_REFERRER_RATE;

        // Commission 레코드 조회 또는 생성 (payment_type별 분리)
        $commission = SalesCommission::firstOrCreate(
            ['management_id' => $management->id, 'payment_type' => $paymentType],
            [
                'tenant_id' => $prospect->tenant_id ?? 1,
                'payment_amount' => 0,
                'payment_date' => now(),
                'base_amount' => 0,
                'partner_rate' => $partnerRate,
                'manager_rate' => 0,
                'partner_commission' => 0,
                'manager_commission' => 0,
                'referrer_rate' => $referrerRate,
                'referrer_commission' => 0,
                'scheduled_payment_date' => now()->addMonth()->day(10),
                'status' => SalesCommission::STATUS_PENDING,
                'partner_id' => $partner?->id ?? $management->sales_partner_id ?? 0,
                'manager_user_id' => $management->manager_user_id,
            ]
        );
        $date = $request->input('date') ?: now()->format('Y-m-d');

        // 수당지급일 필드는 개발상태가 '인계'일 때만 저장 가능
        $paidFields = ['first_partner_paid_at', 'second_partner_paid_at', 'manager_paid_at'];
        if (in_array($field, $paidFields) && $management->hq_status !== 'handover') {
            return response()->json([
                'success' => false,
                'message' => '개발상태가 인계일 때만 수당이 지급됩니다.',
            ], 422);
        }

        $updateData = [$field => $date];

        // 납입일 입력 시 수당지급일 자동 계산 (익월 10일) - 인계 상태일 때만
        $autoFields = [
            'first_payment_at' => 'first_partner_paid_at',
            'second_payment_at' => 'second_partner_paid_at',
        ];

        $autoField = null;
        $autoDate = null;
        if (isset($autoFields[$field]) && $management->hq_status === 'handover') {
            $autoField = $autoFields[$field];
            $autoDate = \Carbon\Carbon::parse($date)->addMonth()->day(10)->format('Y-m-d');
            $updateData[$autoField] = $autoDate;
        }

        // 납입일 변경 시 지급예정일 + 입금일(payment_date)도 함께 업데이트
        if (in_array($field, ['first_payment_at', 'second_payment_at'])) {
            $updateData['scheduled_payment_date'] = \Carbon\Carbon::parse($date)->addMonth()->day(10)->format('Y-m-d');
            $updateData['payment_date'] = $date;
        }

        $commission->update($updateData);

        $response = [
            'success' => true,
            'field' => $field,
            'date' => $commission->$field?->format('Y-m-d'),
            'date_display' => $commission->$field?->format('m/d'),
        ];

        if ($autoField) {
            $response['auto_field'] = $autoField;
            $response['auto_date'] = $autoDate;
        }

        return response()->json($response);
    }

    /**
     * 상태 토글 (영업중 ↔ 완료)
     */
    public function toggleStatus(int $id)
    {
        $this->checkAdminAccess();

        $prospect = TenantProspect::findOrFail($id);

        if ($prospect->status === TenantProspect::STATUS_ACTIVE) {
            $prospect->update(['status' => TenantProspect::STATUS_COMPLETED]);
        } elseif ($prospect->status === TenantProspect::STATUS_COMPLETED) {
            $prospect->update(['status' => TenantProspect::STATUS_ACTIVE]);
        } else {
            return response()->json([
                'success' => false,
                'message' => '영업중 또는 완료 상태만 변경할 수 있습니다.',
            ], 422);
        }

        return response()->json([
            'success' => true,
            'status' => $prospect->status,
            'status_label' => $prospect->status_label,
            'status_color' => $prospect->status_color,
        ]);
    }

    /**
     * 가망고객 삭제 (슈퍼관리자 전용)
     */
    public function destroy(int $id)
    {
        $prospect = TenantProspect::findOrFail($id);

        // 연관 데이터 삭제
        $management = SalesTenantManagement::where('tenant_prospect_id', $prospect->id)->first();
        if ($management) {
            SalesCommission::where('management_id', $management->id)->delete();
            $management->delete();
        }
        SalesScenarioChecklist::where('tenant_prospect_id', $prospect->id)->delete();

        $prospect->delete();

        return response()->json([
            'success' => true,
            'message' => "'{$prospect->company_name}' 가망고객이 삭제되었습니다.",
        ]);
    }

    /**
     * 협업지원금(referrer_commission) 금액 수정
     */
    public function updateReferrerCommission(int $id, Request $request)
    {
        $this->checkAdminAccess();

        $request->validate([
            'amount' => 'required|numeric|min:0',
        ]);

        $prospect = TenantProspect::findOrFail($id);
        $management = SalesTenantManagement::findOrCreateByProspect($prospect->id);

        // 단체 파트너는 수동 수정 불가
        $partner = $management->salesPartner;
        if (! $partner && $prospect->registered_by) {
            $partner = SalesPartner::where('user_id', $prospect->registered_by)->first();
        }
        if ($partner && $partner->isGroup()) {
            return response()->json([
                'success' => false,
                'message' => '단체 파트너는 협업지원금을 수동 변경할 수 없습니다.',
            ], 422);
        }

        $isGroup = $partner?->isGroup() ?? false;
        $partnerRate = $partner?->commission_rate
            ?? ($isGroup ? SalesCommissionService::DEFAULT_GROUP_RATE : SalesCommissionService::DEFAULT_PARTNER_RATE);

        // Commission 레코드 조회 또는 생성
        $commission = SalesCommission::firstOrCreate(
            ['management_id' => $management->id],
            [
                'tenant_id' => $prospect->tenant_id ?? 1,
                'payment_type' => 'deposit',
                'payment_amount' => 0,
                'payment_date' => now(),
                'base_amount' => 0,
                'partner_rate' => $partnerRate,
                'manager_rate' => 0,
                'partner_commission' => 0,
                'manager_commission' => 0,
                'referrer_rate' => $isGroup
                    ? SalesCommissionService::DEFAULT_GROUP_REFERRER_RATE
                    : SalesCommissionService::DEFAULT_INDIVIDUAL_REFERRER_RATE,
                'referrer_commission' => 0,
                'scheduled_payment_date' => now()->addMonth()->day(10),
                'status' => SalesCommission::STATUS_PENDING,
                'partner_id' => $partner?->id ?? $management->sales_partner_id ?? 0,
                'manager_user_id' => $management->manager_user_id,
            ]
        );

        $commission->update([
            'referrer_commission' => $request->input('amount'),
        ]);

        return response()->json([
            'success' => true,
            'amount' => (int) $commission->referrer_commission,
        ]);
    }

    /**
     * 수당 날짜 삭제 (초기화)
     */
    public function clearCommissionDate(int $id, Request $request)
    {
        $this->checkAdminAccess();

        $request->validate([
            'field' => 'required|in:first_payment_at,first_partner_paid_at,second_payment_at,second_partner_paid_at,first_subscription_at,manager_paid_at',
        ]);

        $prospect = TenantProspect::findOrFail($id);
        $management = SalesTenantManagement::where('tenant_prospect_id', $prospect->id)->first();

        if (! $management) {
            return response()->json(['success' => false, 'message' => '관리 정보가 없습니다.']);
        }

        $field = $request->input('field');

        // 1차 필드 → deposit 레코드, 2차 필드 → balance 레코드
        $paymentType = $this->getPaymentTypeForField($field);

        $commission = SalesCommission::where('management_id', $management->id)
            ->where('payment_type', $paymentType)
            ->first();

        if (! $commission) {
            return response()->json(['success' => false, 'message' => '수당 정보가 없습니다.']);
        }
        $updateData = [$field => null];

        // 납입일 삭제 시 수당지급일도 함께 초기화
        $autoFields = [
            'first_payment_at' => 'first_partner_paid_at',
            'second_payment_at' => 'second_partner_paid_at',
        ];

        $autoField = null;
        if (isset($autoFields[$field])) {
            $autoField = $autoFields[$field];
            $updateData[$autoField] = null;
        }

        $commission->update($updateData);

        return response()->json([
            'success' => true,
            'field' => $field,
            'auto_field' => $autoField,
        ]);
    }
}
