<?php

require_once __DIR__ . '/../../core/format.php';
require_once __DIR__ . '/../../core/notifications.php';

class PaymentStatusService
{
    public static function paymentTermsDays($terms)
    {
        $terms = icylab_normalize_payment_terms($terms);

        switch ($terms) {
            case 'contado':
                return 0;
            case 'credito_15':
                return 15;
            case 'credito_30':
                return 30;
            case 'credito_45':
                return 45;
            default:
                return null;
        }
    }

    public static function calculateDueDate($terms, $baseDate = null)
    {
        $days = self::paymentTermsDays($terms);

        if ($days === null) {
            return null;
        }

        $date = new DateTime($baseDate ?: date('Y-m-d'));

        if ($days > 0) {
            $date->modify('+' . $days . ' days');
        }

        return $date->format('Y-m-d');
    }

    public static function applyFacturadaRules(array $params)
    {
        $stage = trim((string)($params['stage'] ?? ''));
        $oldStage = trim((string)($params['old_stage'] ?? ''));
        $paymentStatus = trim((string)($params['payment_status'] ?? 'no_facturado'));
        $paymentDueDate = self::cleanDate($params['payment_due_date'] ?? null);
        $paymentPaidDate = self::cleanDate($params['payment_paid_date'] ?? null);
        $paymentTerms = $params['payment_terms'] ?? 'contado';
        $baseDate = self::cleanDate($params['base_date'] ?? null) ?: date('Y-m-d');
        $forceRecalculate = !empty($params['force_recalculate']);

        $changes = array();
        $termsLabel = icylab_payment_terms_label($paymentTerms);

        if ($stage === 'facturada') {
            if ($paymentDueDate === null || $oldStage !== 'facturada' || $forceRecalculate) {
                $calculatedDueDate = self::calculateDueDate($paymentTerms, $baseDate);

                if ($calculatedDueDate !== null && $calculatedDueDate !== $paymentDueDate) {
                    $paymentDueDate = $calculatedDueDate;
                    $changes[] = 'Vencimiento de pago calculado automaticamente segun condicion de pago: ' . $termsLabel . ' -> ' . $paymentDueDate;
                } elseif ($calculatedDueDate === null && $paymentDueDate === null) {
                    $changes[] = 'Vencimiento de pago no calculado automaticamente porque la condicion de pago es personalizada.';
                }
            }

            if ($paymentStatus === 'pagado' && $paymentPaidDate === null) {
                $paymentPaidDate = $baseDate;
                $changes[] = 'Fecha de pago registrada automaticamente al marcar la cobranza como Pagada: ' . $paymentPaidDate;
            }

            if ($paymentPaidDate !== null) {
                if ($paymentStatus !== 'pagado') {
                    $paymentStatus = 'pagado';
                    $changes[] = 'Cobranza actualizada automaticamente a Pagado porque existe fecha de pago.';
                }
            } elseif (!in_array($paymentStatus, array('por_cobrar', 'atrasado', 'incobrable'), true)) {
                $paymentStatus = 'por_cobrar';
                $changes[] = 'Cobranza actualizada automaticamente a Por cobrar al pasar la oportunidad a Facturada.';
            }

            if ($paymentPaidDate === null && $paymentDueDate !== null && self::isOverdue($paymentDueDate)) {
                if (!in_array($paymentStatus, array('pagado', 'incobrable'), true) && $paymentStatus !== 'atrasado') {
                    $paymentStatus = 'atrasado';
                    $changes[] = 'Cobranza actualizada automaticamente a Atrasado por vencimiento de pago.';
                }
            }
        }

        return array(
            'payment_status' => $paymentStatus,
            'payment_due_date' => $paymentDueDate,
            'payment_paid_date' => $paymentPaidDate,
            'changes' => $changes,
        );
    }

    public static function processOverdueOpportunities(PDO $pdo)
    {
        $stmt = $pdo->query("
            SELECT id, customer_id, customer_name, title, owner_user_id, payment_due_date
            FROM crm_opportunities
            WHERE deleted_at IS NULL
              AND stage = 'facturada'
              AND payment_status = 'por_cobrar'
              AND payment_paid_date IS NULL
              AND payment_due_date IS NOT NULL
              AND payment_due_date < CURDATE()
        ");

        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

        if (empty($rows)) {
            return 0;
        }

        $update = $pdo->prepare("
            UPDATE crm_opportunities
            SET payment_status = 'atrasado', updated_at = CURRENT_TIMESTAMP
            WHERE id = ?
              AND payment_status = 'por_cobrar'
              AND payment_paid_date IS NULL
        ");

        $activity = $pdo->prepare("
            INSERT INTO crm_activities
            (opportunity_id, customer_id, customer_name, activity_type, title, description, owner_name, activity_date)
            VALUES (?, ?, ?, 'sistema', 'Cobranza atrasada', ?, 'Sistema', NOW())
        ");

        $count = 0;

        foreach ($rows as $row) {
            $update->execute(array((int)$row['id']));

            if ($update->rowCount() > 0) {
                $activity->execute(array(
                    (int)$row['id'],
                    (int)$row['customer_id'],
                    $row['customer_name'],
                    'La oportunidad facturada paso automaticamente a Atrasado. Fecha de vencimiento: ' . $row['payment_due_date'] . '.'
                ));

                notify_crm_owner_or_admin_event(
                    'billing.overdue',
                    !empty($row['owner_user_id']) ? (int)$row['owner_user_id'] : null,
                    'Cobranza atrasada: ' . (!empty($row['title']) ? $row['title'] : $row['customer_name']),
                    'Cliente: ' . $row['customer_name'] . "\nVencimiento: " . $row['payment_due_date'] . "\nLa cobranza fue marcada automaticamente como atrasada.",
                    '/modules/crm/opportunity.php?id=' . (int)$row['id'],
                    'opportunity',
                    (int)$row['id'],
                    array(
                        'force_email' => true,
                        'critical' => true,
                        'dedupe_key' => 'billing.overdue:' . (int)$row['id'] . ':' . $row['payment_due_date']
                    )
                );

                $count++;
            }
        }

        return $count;
    }

    private static function cleanDate($value)
    {
        $value = trim((string)$value);

        if ($value === '') {
            return null;
        }

        return preg_match('/^\d{4}-\d{2}-\d{2}$/', $value) ? $value : null;
    }

    private static function isOverdue($date)
    {
        $today = new DateTime(date('Y-m-d'));
        $dueDate = new DateTime($date);

        return $dueDate < $today;
    }
}
