<?php

declare(strict_types=1);

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Database\Query\Builder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

/**
 * SaaS-admin «Лиды» (L3) — сквозная вложенность дашборда до конечного источника.
 * Серверная пагинация/фильтры (масштаб: десятки тысяч лидов).
 * Цепочка: supplier_leads.supplier_project_id → источник (канал+identifier),
 * platform = поставщик (B1/B2/B3), resolved_subject_code = регион,
 * deals.source_crm_id = supplier_leads.vid → сделки клиентов.
 * Группа ['saas-admin','admin-db'] → cross-tenant через pgsql_admin.
 * Spec: docs/superpowers/specs/2026-06-28-dashboard-drilldown-scale-design.md
 */
class AdminLeadsController extends Controller
{
    private const PER_PAGE_DEFAULT = 25;

    private const PER_PAGE_MAX = 100;

    private const STUCK_HOURS = 4;

    /** Маска телефона по 152-ФЗ: «+7 9** *** ** 07» (видны код страны и 2 последние). */
    private function maskPhone(?string $phone): string
    {
        if (! $phone) {
            return '—';
        }
        $digits = preg_replace('/\D/', '', $phone);
        if (strlen((string) $digits) < 4) {
            return '***';
        }
        $last2 = substr((string) $digits, -2);
        $first = substr((string) $digits, 0, 2);

        return $first.'** *** ** '.$last2;
    }

    /** Производный статус лида для UI. */
    private function statusOf(object $r): string
    {
        if ($r->error !== null && $r->error !== '') {
            return 'error';
        }
        if ($r->processed_at !== null) {
            return ((int) ($r->deals_created_count ?? 0)) > 0 ? 'delivered' : 'no_match';
        }

        return 'pending'; // визуально «завис» определяет фронт по времени, но базово pending
    }

    /** Базовый запрос лидов с присоединённым источником (supplier_projects). */
    private function baseQuery(Request $request): Builder
    {
        $q = DB::table('supplier_leads as sl')
            ->leftJoin('supplier_projects as sp', 'sp.id', '=', 'sl.supplier_project_id');

        if (($df = (string) $request->query('date_from', '')) !== '' && ($dt = (string) $request->query('date_to', '')) !== '') {
            $q->whereBetween('sl.received_at', [$df.' 00:00:00', $dt.' 23:59:59']);
        }
        if (($channel = (string) $request->query('channel', '')) !== '') {
            $q->where('sp.signal_type', $channel);
        }
        if (($platform = (string) $request->query('platform', '')) !== '') {
            $q->where('sl.platform', $platform);
        }
        if (($search = trim((string) $request->query('search', ''))) !== '') {
            $q->where(function ($w) use ($search) {
                $w->where('sl.phone', 'like', '%'.$search.'%')
                    ->orWhere('sp.unique_key', 'like', '%'.$search.'%')
                    ->orWhere('sl.vid', '=', ctype_digit($search) ? (int) $search : 0);
            });
        }
        if (($status = (string) $request->query('status', '')) !== '') {
            $this->applyStatusFilter($q, $status);
        }
        if (($tenantId = (int) $request->query('tenant_id', 0)) > 0) {
            $q->whereExists(function ($e) use ($tenantId) {
                $e->select(DB::raw(1))->from('deals')
                    ->whereColumn('deals.source_crm_id', 'sl.vid')
                    ->where('deals.tenant_id', $tenantId);
            });
        }

        return $q;
    }

    private function applyStatusFilter(Builder $q, string $status): void
    {
        match ($status) {
            'error' => $q->whereNotNull('sl.error')->where('sl.error', '<>', ''),
            'delivered' => $q->whereNotNull('sl.processed_at')->where('sl.deals_created_count', '>', 0),
            'no_match' => $q->whereNotNull('sl.processed_at')
                ->where(fn ($w) => $w->whereNull('sl.deals_created_count')->orWhere('sl.deals_created_count', '=', 0)),
            'stuck' => $q->whereNull('sl.processed_at')->where('sl.received_at', '<', now()->subHours(self::STUCK_HOURS)),
            'pending' => $q->whereNull('sl.processed_at'),
            default => null,
        };
    }

    /** @return array<string,mixed> */
    private function rowToArray(object $r): array
    {
        return [
            'id' => (int) $r->id,
            'received_at' => $r->received_at,
            'platform' => $r->platform,
            'channel' => $r->channel,
            'source' => $r->unique_key,
            'region_code' => $r->resolved_subject_code !== null ? (int) $r->resolved_subject_code : null,
            'phone_masked' => $this->maskPhone($r->phone),
            'deals_created_count' => (int) ($r->deals_created_count ?? 0),
            'status' => $this->statusOf($r),
        ];
    }

    /** GET /api/admin/leads — серверный список с фильтрами/пагинацией. */
    public function index(Request $request): JsonResponse
    {
        $perPage = min(self::PER_PAGE_MAX, max(1, (int) $request->query('per_page', self::PER_PAGE_DEFAULT)));
        $page = max(1, (int) $request->query('page', 1));

        $base = $this->baseQuery($request);
        $total = (clone $base)->count();

        $rows = $base
            ->orderByDesc('sl.received_at')
            ->offset(($page - 1) * $perPage)
            ->limit($perPage)
            ->get([
                'sl.id', 'sl.received_at', 'sl.platform', 'sl.phone', 'sl.deals_created_count',
                'sl.processed_at', 'sl.error', 'sl.resolved_subject_code',
                'sp.signal_type as channel', 'sp.unique_key',
            ])
            ->map(fn ($r) => $this->rowToArray($r));

        return response()->json([
            'data' => $rows,
            'total' => $total,
            'page' => $page,
            'per_page' => $perPage,
        ]);
    }

    /** GET /api/admin/leads/{id} — карточка лида: источник + сделки клиентов (цепочка). */
    public function show(int $id): JsonResponse
    {
        $lead = DB::table('supplier_leads as sl')
            ->leftJoin('supplier_projects as sp', 'sp.id', '=', 'sl.supplier_project_id')
            ->where('sl.id', $id)
            ->first([
                'sl.id', 'sl.received_at', 'sl.processed_at', 'sl.error', 'sl.platform', 'sl.phone',
                'sl.vid', 'sl.deals_created_count', 'sl.resolved_subject_code', 'sl.region_source',
                'sl.phone_operator', 'sp.signal_type as channel', 'sp.unique_key', 'sp.id as supplier_project_id',
            ]);

        if ($lead === null) {
            return response()->json(['message' => 'Лид не найден'], 404);
        }

        $deals = DB::table('deals')
            ->join('tenants', 'tenants.id', '=', 'deals.tenant_id')
            ->where('deals.source_crm_id', $lead->vid)
            ->orderByDesc('deals.received_at')
            ->limit(50)
            ->get([
                'deals.id', 'deals.tenant_id', 'tenants.organization_name', 'tenants.subdomain',
                'deals.status', 'deals.project_id', 'deals.received_at',
            ])
            ->map(fn ($d) => [
                'id' => (int) $d->id,
                'tenant_id' => (int) $d->tenant_id,
                'tenant_name' => $d->organization_name ?: $d->subdomain,
                'subdomain' => $d->subdomain,
                'status' => $d->status,
                'project_id' => $d->project_id !== null ? (int) $d->project_id : null,
                'received_at' => $d->received_at,
            ]);

        return response()->json([
            'lead' => [
                'id' => (int) $lead->id,
                'platform' => $lead->platform,
                'phone_masked' => $this->maskPhone($lead->phone),
                'received_at' => $lead->received_at,
                'processed_at' => $lead->processed_at,
                'error' => $lead->error,
                'region_code' => $lead->resolved_subject_code !== null ? (int) $lead->resolved_subject_code : null,
                'region_source' => $lead->region_source,
                'phone_operator' => $lead->phone_operator,
                'deals_created_count' => (int) ($lead->deals_created_count ?? 0),
                'status' => $this->statusOf($lead),
            ],
            'source' => [
                'platform' => $lead->platform,
                'channel' => $lead->channel,
                'identifier' => $lead->unique_key,
                'supplier_project_id' => $lead->supplier_project_id !== null ? (int) $lead->supplier_project_id : null,
            ],
            'deals' => $deals,
        ]);
    }
}
