<?php
namespace App\Controllers;

use App\Core\Auth;
use App\Core\Controller;
use App\Core\Database;
use App\Core\ModuleManager;
use App\Core\ProspectClientService;
use App\Core\RaccordementOtbService;
use PDO;

class ProspectClientsController extends Controller
{
    private PDO $pdo;

    public function __construct()
    {
        $this->pdo = Database::pdo();
        ModuleManager::ensureSchema($this->pdo);
        RaccordementOtbService::ensureSchema($this->pdo);
        ProspectClientService::ensureSchema($this->pdo);

        if (Auth::check()) {
            $this->guardLicensedModuleAccess();
        }
    }

    public function index(): void
    {
        $user = $this->requireUser();
        $scope = $this->resolveScope('list', $user);
        if ($scope === 'none') {
            http_response_code(403);
            echo 'Accès refusé';
            return;
        }

        $filters = [
            'search' => trim((string)($_GET['search'] ?? '')),
            'status' => trim((string)($_GET['status'] ?? '')),
        ];

        $records = ProspectClientService::list($this->pdo, $filters, $user, $scope);
        $summary = ProspectClientService::summary($this->pdo, $user, $scope);
        $studyTechnicians = $this->loadStudyTechnicians();

        $this->view('prospect_clients/index', [
            'title' => 'Gestion Prospects & Clients',
            'records' => $records,
            'summary' => $summary,
            'filters' => $filters,
            'studyTechnicians' => $studyTechnicians,
            'flashSuccess' => trim((string)($_GET['success'] ?? '')),
            'flashError' => trim((string)($_GET['err'] ?? '')),
        ]);
    }

    public function create(): void
    {
        $user = $this->requireRoles(['admin', 'agent', 'manager', 'superviseur', 'supervisor']);
        if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') {
            $this->redirect('/prospect-clients');
            return;
        }

        $fullName = trim((string)(($_POST['last_name'] ?? '') . ' ' . ($_POST['first_name'] ?? '')));
        $phone = trim((string)($_POST['phone'] ?? ''));
        if ($fullName === '' || $phone === '') {
            $this->redirect('/prospect-clients?err=' . urlencode('Le nom complet et le contact téléphonique sont obligatoires.'));
            return;
        }

        ProspectClientService::create($this->pdo, [
            'first_name' => $_POST['first_name'] ?? '',
            'last_name' => $_POST['last_name'] ?? '',
            'full_name' => $fullName,
            'city' => $_POST['city'] ?? '',
            'commune' => $_POST['commune'] ?? '',
            'address' => $_POST['address'] ?? '',
            'latitude' => $_POST['latitude'] ?? null,
            'longitude' => $_POST['longitude'] ?? null,
            'geolocation_mode' => $_POST['geolocation_mode'] ?? 'manual',
            'phone' => $phone,
        ], (int)($user['id'] ?? 0));

        $this->redirect('/prospect-clients?success=created');
    }

    public function recommendation(): void
    {
        $user = $this->requireUser();
        if ($this->resolveScope('view', $user) === 'none') {
            $this->json(['ok' => false, 'error' => 'forbidden'], 403);
            return;
        }

        $latitude = $this->normalizeCoordinate($_GET['latitude'] ?? null);
        $longitude = $this->normalizeCoordinate($_GET['longitude'] ?? null);
        if ($latitude === null || $longitude === null) {
            $this->json(['ok' => false, 'error' => 'missing_coordinates'], 422);
            return;
        }

        $recommendation = ProspectClientService::buildRecommendationSnapshot($this->pdo, $latitude, $longitude);
        $payload = json_decode((string)($recommendation['payload'] ?? '[]'), true);
        $this->json([
            'ok' => true,
            'recommendation' => $payload,
            'snapshot' => $recommendation,
        ]);
    }

    public function uploadReceipt(): void
    {
        $user = $this->requireRoles(['admin', 'agent', 'manager', 'superviseur', 'supervisor']);
        if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') {
            $this->redirect('/prospect-clients');
            return;
        }

        $prospectId = (int)($_POST['prospect_id'] ?? 0);
        $prospect = ProspectClientService::find($this->pdo, $prospectId);
        if (!$prospect) {
            $this->redirect('/prospect-clients?err=' . urlencode('Prospect introuvable pour le reçu.'));
            return;
        }

        $file = $_FILES['payment_receipt'] ?? null;
        $receiptPath = $this->storeReceiptFile($prospectId, $file);
        if ($receiptPath === null) {
            $this->redirect('/prospect-clients?err=' . urlencode('Le reçu est obligatoire et doit être au format PDF, JPG, JPEG, PNG ou WEBP.'));
            return;
        }

        ProspectClientService::saveReceipt($this->pdo, $prospectId, $receiptPath, (int)($user['id'] ?? 0));
        $this->redirect('/prospect-clients?success=receipt_uploaded');
    }

    public function createRaccordement(): void
    {
        $user = $this->requireRoles(['admin', 'agent', 'manager', 'superviseur', 'supervisor']);
        if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') {
            $this->redirect('/prospect-clients');
            return;
        }

        $prospectId = (int)($_POST['prospect_id'] ?? 0);
        try {
            $ticketId = ProspectClientService::createRaccordementTicket($this->pdo, $prospectId, [
                'ref_code' => $_POST['ref_code'] ?? '',
                'client_code' => $_POST['client_code'] ?? '',
                'phone' => $_POST['phone'] ?? '',
                'city' => $_POST['city'] ?? '',
                'commune' => $_POST['commune'] ?? '',
                'address' => $_POST['address'] ?? '',
                'latitude' => $_POST['latitude'] ?? null,
                'longitude' => $_POST['longitude'] ?? null,
                'sro_client' => $_POST['sro_client'] ?? '',
                'jdv_client' => $_POST['jdv_client'] ?? '',
                'pco_client' => $_POST['pco_client'] ?? '',
                'snont' => $_POST['snont'] ?? '',
                'nd' => $_POST['nd'] ?? '',
                'company_name' => $_POST['company_name'] ?? '',
                'description' => $_POST['description'] ?? '',
                'priority' => $_POST['priority'] ?? 'Moyenne',
                'status' => $_POST['status'] ?? 'nouveau',
                'avancement' => $_POST['avancement'] ?? '',
                'technician_id' => $_POST['technician_id'] ?? 0,
                'assignment_notes' => $_POST['assignment_notes'] ?? '',
            ], $user);
        } catch (\Throwable $e) {
            $this->redirect('/prospect-clients?err=' . urlencode($e->getMessage()));
            return;
        }

        $this->redirect('/raccordement-clients/detail?id=' . $ticketId . '&from_prospect=1');
    }

    private function requireUser(): array
    {
        if (!Auth::check()) {
            $this->redirect('/login');
        }

        return Auth::user() ?? [];
    }

    private function requireRoles(array $roles): array
    {
        $user = $this->requireUser();
        if (!in_array((string)($user['role_key'] ?? ''), $roles, true)) {
            http_response_code(403);
            echo 'Accès refusé';
            exit;
        }

        return $user;
    }

    private function resolveScope(string $action, array $user): string
    {
        $scope = Auth::permissionScope('prospect_clients', $action);
        if ($scope !== 'none') {
            return $scope;
        }

        if (in_array((string)($user['role_key'] ?? ''), ['admin', 'agent', 'manager', 'superviseur', 'supervisor'], true)) {
            return 'all';
        }

        return 'none';
    }

    private function guardLicensedModuleAccess(): void
    {
        $module = ModuleManager::find($this->pdo, 'prospect_clients');
        if (!empty($module['accessible'])) {
            return;
        }

        http_response_code(403);
        $this->view('settings/module_blocked', ModuleManager::buildBlockedViewData($module));
        exit;
    }

    private function loadStudyTechnicians(): array
    {
        $stmt = $this->pdo->query("SELECT id, name, technician_type FROM users WHERE active = 1 AND role_key IN ('technicien','technician') AND technician_type IN ('etude','etude_raccordement') ORDER BY name ASC");
        return $stmt ? ($stmt->fetchAll(PDO::FETCH_ASSOC) ?: []) : [];
    }

    private function normalizeCoordinate($value): ?float
    {
        $normalized = trim(str_replace(',', '.', (string)$value));
        if ($normalized === '' || !is_numeric($normalized)) {
            return null;
        }

        return (float)$normalized;
    }

    private function json(array $payload, int $status = 200): void
    {
        http_response_code($status);
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode($payload, JSON_UNESCAPED_UNICODE);
        exit;
    }

    private function storeReceiptFile(int $prospectId, ?array $file): ?string
    {
        if (!$file || !empty($file['error']) || empty($file['tmp_name']) || !is_uploaded_file($file['tmp_name'])) {
            return null;
        }

        $extension = strtolower(pathinfo((string)($file['name'] ?? ''), PATHINFO_EXTENSION));
        $allowed = ['pdf', 'jpg', 'jpeg', 'png', 'webp'];
        if (!in_array($extension, $allowed, true)) {
            return null;
        }

        $directory = upload_public_path('prospect-clients/' . $prospectId);
        if (!is_dir($directory) && !@mkdir($directory, 0777, true) && !is_dir($directory)) {
            return null;
        }

        $fileName = 'receipt_' . date('YmdHis') . '_' . bin2hex(random_bytes(4)) . '.' . $extension;
        $destination = rtrim($directory, '/\\') . DIRECTORY_SEPARATOR . $fileName;
        if (!@move_uploaded_file($file['tmp_name'], $destination)) {
            return null;
        }

        return 'prospect-clients/' . $prospectId . '/' . $fileName;
    }
}