<?php

require_once '../../core/config.php';
require_once '../../core/session.php';
require_once '../../core/permissions.php';
require_once '../../services/crm/CustomerService.php';
require_once '../../services/crm/PaymentStatusService.php';
require_once '../../core/notifications.php';

require_login();
require_permission('module.crm');

$sessionUser = current_user();
$currentUser = !empty($sessionUser['name']) ? $sessionUser['name'] : (!empty($sessionUser['email']) ? $sessionUser['email'] : 'Sistema');

$pdo = db();
$customerService = new CustomerService($pdo);

$customerId = isset($_POST['customer_id']) && $_POST['customer_id'] !== '' ? (int)$_POST['customer_id'] : null;

$title = isset($_POST['title']) ? trim($_POST['title']) : '';
$stage = isset($_POST['stage']) ? trim($_POST['stage']) : '';
$expectedValue = isset($_POST['expected_value']) ? (float)$_POST['expected_value'] : 0;
$probability = isset($_POST['probability']) ? (int)$_POST['probability'] : 20;
$ownerName = isset($_POST['owner_name']) ? trim($_POST['owner_name']) : '';
$ownerUserId = isset($_POST['owner_user_id']) && $_POST['owner_user_id'] !== '' ? (int)$_POST['owner_user_id'] : null;
$source = isset($_POST['source']) ? trim($_POST['source']) : '';
$competitor = isset($_POST['competitor']) ? trim($_POST['competitor']) : '';
$expectedCloseDate = isset($_POST['expected_close_date']) && $_POST['expected_close_date'] !== '' ? $_POST['expected_close_date'] : null;
$nextAction = isset($_POST['next_action']) ? trim($_POST['next_action']) : '';
$nextActionDate = isset($_POST['next_action_date']) && $_POST['next_action_date'] !== '' ? $_POST['next_action_date'] : null;
$notes = isset($_POST['notes']) ? trim($_POST['notes']) : '';
$paymentStatus = isset($_POST['payment_status']) ? trim($_POST['payment_status']) : 'no_facturado';
$paymentDueDate = isset($_POST['payment_due_date']) && $_POST['payment_due_date'] !== '' ? $_POST['payment_due_date'] : null;
$paymentPaidDate = isset($_POST['payment_paid_date']) && $_POST['payment_paid_date'] !== '' ? $_POST['payment_paid_date'] : null;

$newCustomerName = isset($_POST['new_customer_name']) ? trim($_POST['new_customer_name']) : '';
$newCustomerTaxId = isset($_POST['new_customer_tax_id']) ? $customerService->normalizeRut($_POST['new_customer_tax_id']) : '';
$contactName = isset($_POST['contact_name']) ? trim($_POST['contact_name']) : '';
$email = isset($_POST['email']) ? trim($_POST['email']) : '';
$phone = isset($_POST['phone']) ? trim($_POST['phone']) : '';
$address = isset($_POST['address']) ? trim($_POST['address']) : '';
$district = isset($_POST['district']) ? trim($_POST['district']) : '';
$city = isset($_POST['city']) ? trim($_POST['city']) : '';
$region = isset($_POST['region']) ? trim($_POST['region']) : '';
$country = isset($_POST['country']) ? trim($_POST['country']) : 'Chile';
$latitude = isset($_POST['latitude']) ? trim($_POST['latitude']) : '';
$longitude = isset($_POST['longitude']) ? trim($_POST['longitude']) : '';
$geocodeStatus = isset($_POST['geocode_status']) ? trim($_POST['geocode_status']) : '';
$geocodeSource = isset($_POST['geocode_source']) ? trim($_POST['geocode_source']) : '';
$geocodeQuery = isset($_POST['geocode_query']) ? trim($_POST['geocode_query']) : '';
$website = isset($_POST['website']) ? trim($_POST['website']) : '';
$restockDays = isset($_POST['restock_days']) && $_POST['restock_days'] !== '' ? (int)$_POST['restock_days'] : null;

$errors = array();

if ($title === '') $errors['title'] = 'Debe ingresar un título de oportunidad.';
if ($stage === '') $errors['stage'] = 'Debe seleccionar una etapa.';
if ($source === '') $errors['source'] = 'Debe seleccionar un origen.';
if ($expectedCloseDate === null) $errors['expected_close_date'] = 'Debe indicar una fecha estimada de cierre.';
if ($nextAction === '') $errors['next_action'] = 'Debe seleccionar una próxima acción.';
if ($nextActionDate === null) $errors['next_action_date'] = 'Debe indicar una fecha para la próxima acción.';

if (!$customerId) {
    $interactedWithNewCustomer = ($newCustomerName !== '' || $newCustomerTaxId !== '' || $contactName !== '' || $email !== '' || $phone !== '' || $address !== '' || $district !== '' || $city !== '' || $region !== '' || $website !== '' || $restockDays !== null);

    if ($interactedWithNewCustomer) {
        if ($newCustomerName === '') $errors['new_customer_name'] = 'Debe ingresar la razón social o nombre del cliente.';

        if (!empty($errors) && empty($_POST['new_customer_name'])) {
            $_POST['new_customer_name'] = 'force_open';
        }
    } else {
        $errors['customer_id'] = 'Debe seleccionar un cliente válido o completar el formulario de cliente nuevo.';
    }
}

if (!empty($errors)) {
    $_SESSION['form_errors'] = $errors;
    $_SESSION['form_old'] = $_POST;
    header('Location: /modules/crm/opportunity_create.php');
    exit;
}

try {
    $customerName = '';
    $customerTaxId = null;

    if ($customerId) {
        $customer = $customerService->requireActiveById($customerId, 'El cliente seleccionado ya no existe o está desactivado.');
        $customerName = $customer['customer_name'];
        $customerTaxId = $customer['customer_tax_id'];
    } else {
        $result = $customerService->create(array(
            'customer_name' => $newCustomerName,
            'commercial_name' => $newCustomerName,
            'legal_name' => $newCustomerName,
            'customer_tax_id' => $newCustomerTaxId,
            'contact_name' => $contactName,
            'email' => $email,
            'phone' => $phone,
            'address' => $address,
            'district' => $district,
            'city' => $city,
            'region' => $region,
            'country' => $country,
            'latitude' => $latitude,
            'longitude' => $longitude,
            'geocode_status' => $geocodeStatus,
            'geocode_source' => $geocodeSource,
            'geocode_query' => $geocodeQuery,
            'website' => $website,
            'payment_terms' => $_POST['payment_terms'] ?? 'contado',
            'restock_days' => $restockDays,
            'owner_name' => $ownerName,
            'source' => 'manual'
        ), array('reuse_existing' => true, 'require_location' => true));

        $customer = $result['customer'];
        $customerId = (int)$result['customer_id'];
        $customerName = $customer['customer_name'];
        $customerTaxId = $customer['customer_tax_id'];
    }

    $billingAdjustment = PaymentStatusService::applyFacturadaRules(array(
        'stage' => $stage,
        'old_stage' => '',
        'payment_status' => $paymentStatus,
        'payment_due_date' => $paymentDueDate,
        'payment_paid_date' => $paymentPaidDate,
        'payment_terms' => $customer['payment_terms'] ?? ($customer['facto_payment_term'] ?? 'contado'),
        'base_date' => date('Y-m-d'),
        'force_recalculate' => true,
    ));
    $paymentStatus = $billingAdjustment['payment_status'];
    $paymentDueDate = $billingAdjustment['payment_due_date'];
    $paymentPaidDate = $billingAdjustment['payment_paid_date'];
    $billingChanges = $billingAdjustment['changes'];

    $stmt = $pdo->prepare("\n        INSERT INTO crm_opportunities\n        (\n            customer_id, title, customer_name, customer_tax_id, stage, payment_status, payment_due_date, payment_paid_date,\n            expected_value, probability, owner_name, owner_user_id, source, competitor, expected_close_date, next_action, next_action_date, notes\n        )\n        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n    ");

    $stmt->execute(array(
        $customerId, $title, $customerName, $customerTaxId, $stage, $paymentStatus, $paymentDueDate, $paymentPaidDate,
        $expectedValue, $probability, $ownerName, $ownerUserId, $source, $competitor, $expectedCloseDate, $nextAction, $nextActionDate, $notes
    ));

    $opportunityId = (int)$pdo->lastInsertId();

    $stmt = $pdo->prepare("\n        INSERT INTO crm_activities\n        (opportunity_id, customer_id, customer_name, activity_type, title, description, owner_name, activity_date)\n        VALUES (?, ?, ?, 'sistema', 'Oportunidad creada', ?, ?, NOW())\n    ");

    $description = 'Etapa inicial: ' . $stage;
    if ($expectedValue > 0) $description .= "\nValor esperado: " . $expectedValue;
    if ($nextAction !== '') $description .= "\nPróxima acción: " . $nextAction;
    if ($notes !== '') $description .= "\nNotas iniciales añadidas.";
    if (!empty($billingChanges)) $description .= "\n" . implode("\n", $billingChanges);

    $stmt->execute(array($opportunityId, $customerId, $customerName, $description, $currentUser));


    $opportunityUrl = '/modules/crm/opportunity.php?id=' . $opportunityId;

    notify_high_value_opportunity_event(
        $opportunityId,
        $title,
        $customerName,
        (float)$expectedValue,
        $ownerUserId,
        array('dedupe_key' => 'opportunity.high_value:' . $opportunityId)
    );

    if ($ownerUserId) {
        notify_crm_user_event(
            'opportunity.assigned',
            $ownerUserId,
            'Nueva oportunidad asignada: ' . $title,
            'Cliente: ' . $customerName . "\nEtapa: " . $stage . ($expectedValue > 0 ? "\nValor esperado: " . number_format($expectedValue, 0, ',', '.') : ''),
            $opportunityUrl,
            'opportunity',
            $opportunityId,
            array('dedupe_key' => 'opportunity.assigned:' . $opportunityId . ':' . $ownerUserId)
        );
    }

    if ($stage === 'facturada') {
        notify_crm_owner_or_admin_event(
            'opportunity.facturada',
            $ownerUserId,
            'Oportunidad facturada: ' . $title,
            'Cliente: ' . $customerName . "\nCobranza: " . $paymentStatus . ($paymentDueDate ? "\nVencimiento: " . $paymentDueDate : ''),
            $opportunityUrl,
            'opportunity',
            $opportunityId,
            array('dedupe_key' => 'opportunity.facturada:' . $opportunityId)
        );
    }

    if (in_array($paymentStatus, array('por_cobrar', 'atrasado', 'pagado'), true)) {
        $billingEvent = $paymentStatus === 'pagado' ? 'billing.paid' : ($paymentStatus === 'atrasado' ? 'billing.overdue' : 'billing.por_cobrar');
        $billingTitle = $paymentStatus === 'pagado' ? 'Cobranza pagada' : ($paymentStatus === 'atrasado' ? 'Cobranza atrasada' : 'Cobranza por cobrar');
        notify_crm_owner_or_admin_event(
            $billingEvent,
            $ownerUserId,
            $billingTitle . ': ' . $title,
            'Cliente: ' . $customerName . ($paymentDueDate ? "\nVencimiento: " . $paymentDueDate : '') . ($paymentPaidDate ? "\nFecha de pago: " . $paymentPaidDate : ''),
            $opportunityUrl,
            'opportunity',
            $opportunityId,
            array('dedupe_key' => $billingEvent . ':' . $opportunityId . ':' . ($paymentDueDate ?: $paymentPaidDate ?: date('Y-m-d')))
        );
    }

    if ($ownerUserId) {
        require_once '../../services/crm/CrmCalendarService.php';
        try {
            $calendar = new CrmCalendarService($ownerUserId);
            $calendar->syncOpportunity($opportunityId, $customerName, $title, $_POST);
        } catch (Exception $e) {
            error_log('Error Calendar Store: ' . $e->getMessage());
        }
    }

    header('Location: /modules/crm/opportunity.php?id=' . $opportunityId);
    exit;
} catch (Throwable $e) {
    $_SESSION['form_errors'] = array('customer_id' => $e->getMessage());
    $_SESSION['form_old'] = $_POST;
    header('Location: /modules/crm/opportunity_create.php');
    exit;
}
