<?php
// asana-form-builder/includes/functions/taskdate/task-date.php
if (!defined('ABSPATH')) exit;

/**
 * Parse various date formats into Asana's YYYY-MM-DD (or return null).
 * Supported inputs (non-exhaustive):
 *  - YYYY-MM-DD, YYYY/MM/DD
 *  - DD/MM/YY (pivot), DD/MM/YYYY
 *  - DD-MM-YYYY, DD.MM.YYYY
 *  - "04 Nov 2025", "4 November 2025", "Nov 4 2025"
 *
 * Two-digit year pivot: <= 70 -> 2000+, >70 -> 1900+
 *
 * @param string $raw
 * @return string|null ISO date 'YYYY-MM-DD' or null
 */
function afb_parse_date_to_iso($raw) {
    if (empty($raw) || !is_string($raw)) return null;
    $s = trim($raw);

    // Quick direct ISO-ish match (YYYY-MM-DD or YYYY/MM/DD)
    if (preg_match('/^\d{4}[-\/]\d{2}[-\/]\d{2}$/', $s)) {
        $s = str_replace('/', '-', $s);
        $d = DateTime::createFromFormat('Y-m-d', $s);
        if ($d && $d->format('Y-m-d') === $s) return $s;
    }

    // Common explicit: DD/MM/YY or DD/MM/YYYY
    if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{2,4})$/', $s, $m)) {
        $d = (int)$m[1]; $mo = (int)$m[2]; $y = (int)$m[3];
        if ($y < 100) {
            $pivot = 70; // <=70 => 2000+, adjust if you want a different pivot
            $y = ($y <= $pivot) ? (2000 + $y) : (1900 + $y);
        }
        if (checkdate($mo, $d, $y)) {
            return sprintf('%04d-%02d-%02d', $y, $mo, $d);
        }
        return null;
    }

    // YYYY/MM/DD or YYYY-MM-DD with single-digit month/day
    if (preg_match('/^(\d{4})[\/\-](\d{1,2})[\/\-](\d{1,2})$/', $s, $m)) {
        $y = (int)$m[1]; $mo = (int)$m[2]; $d = (int)$m[3];
        if (checkdate($mo, $d, $y)) {
            return sprintf('%04d-%02d-%02d', $y, $mo, $d);
        }
        return null;
    }

    // D-M-YYYY or D.M.YYYY
    if (preg_match('/^(\d{1,2})[-\.](\d{1,2})[-\.](\d{4})$/', $s, $m)) {
        $d = (int)$m[1]; $mo = (int)$m[2]; $y = (int)$m[3];
        if (checkdate($mo, $d, $y)) {
            return sprintf('%04d-%02d-%02d', $y, $mo, $d);
        }
    }

    // Sanitise and attempt textual formats
    $try = trim(preg_replace('/[^\dA-Za-z ,\-\/\.]/', ' ', $s));
    $formats = [
        'j M Y', 'd M Y', 'j F Y', 'd F Y',
        'M j Y', 'F j Y', 'Y-m-d',
        'd-M-Y', 'j-M-Y', 'j.n.Y', 'd.n.Y'
    ];
    foreach ($formats as $fmt) {
        $dt = DateTime::createFromFormat($fmt, $try);
        if ($dt) {
            // If createFromFormat succeeded, return ISO (no strict string-equals required)
            return $dt->format('Y-m-d');
        }
    }

    // As last resort use strtotime when there are alphabetic month names (reduces accidental numeric ambiguity)
    if (preg_match('/[A-Za-z]/', $s)) {
        $ts = strtotime($s);
        if ($ts !== false) {
            return date('Y-m-d', $ts);
        }
    }

    return null;
}

/**
 * Find a best candidate date from POST payload and custom fields.
 * Priority:
 * 1) explicit keys: 'date', 'start_date', 'end_date' (in that order)
 * 2) any top-level scalar POST entries that look like DD/MM/YY or DD/MM/YYYY
 * 3) custom_fields values (strings) that contain DD/MM/YY or DD/MM/YYYY
 *
 * Returns ISO YYYY-MM-DD or null.
 *
 * @param array $post
 * @param array $custom_fields
 * @return string|null
 */
function afb_get_due_date_from_request($post, $custom_fields = []) {
    $keys = ['date', 'start_date', 'end_date'];

    // 1) explicit POST keys (string or array with scalar first element)
    foreach ($keys as $k) {
        if (isset($post[$k])) {
            $val = $post[$k];
            if (is_array($val)) {
                $val = (isset($val[0]) && is_string($val[0])) ? $val[0] : null;
            }
            if (is_string($val) && $val !== '') {
                $iso = afb_parse_date_to_iso($val);
                if ($iso) return $iso;
            }
        }
    }

    // 2) top-level POST scalar values
    if (is_array($post)) {
        foreach ($post as $k => $v) {
            if (is_string($v) && preg_match('/^\s*\d{1,2}\/\d{1,2}\/\d{2,4}\s*$/', $v)) {
                $iso = afb_parse_date_to_iso($v);
                if ($iso) return $iso;
            }
        }
    }

// 3) custom fields (try any string – supports ISO, DD/MM/YY, etc.)
if (is_array($custom_fields)) {
    foreach ($custom_fields as $k => $v) {
        if (!is_string($v) || $v === '') continue;
        $iso = afb_parse_date_to_iso($v);
        if ($iso) return $iso;
    }
}


    return null;
}

/**
 * Scan a task name for common date patterns (DD/MM/YY, DD/MM/YYYY, YYYY-MM-DD, textual month).
 * Returns ISO YYYY-MM-DD or null.
 *
 * @param string $task_name
 * @return string|null
 */
function afb_get_due_date_from_task_name($task_name) {
    if (empty($task_name) || !is_string($task_name)) return null;

    // 1) DD/MM/YY or DD/MM/YYYY
    if (preg_match('/\b(\d{1,2}\/\d{1,2}\/\d{2,4})\b/', $task_name, $m)) {
        $iso = afb_parse_date_to_iso($m[1]);
        if ($iso) return $iso;
    }

    // 2) YYYY-MM-DD or YYYY/MM/DD
    if (preg_match('/\b(\d{4}[-\/]\d{2}[-\/]\d{2})\b/', $task_name, $m)) {
        $iso = afb_parse_date_to_iso($m[1]);
        if ($iso) return $iso;
    }

    // 3) textual date like "4 Nov 2025" or "04 November 2025"
    if (preg_match('/\b(\d{1,2}\s+(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Sept|Oct|Nov|Dec|January|February|March|April|May|June|July|August|September|October|November|December)[^\d]{0,3}\s*\d{4})/i', $task_name, $m)) {
        $iso = afb_parse_date_to_iso($m[1]);
        if ($iso) return $iso;
    }

    return null;
}

/**
 * Attempt to extract start/end dates from arbitrary POST fields as a safety-net.
 * Scans POST keys that contain "date", "window", "run", "start", "end" (case-insensitive)
 * and looks for DD/MM/YY or DD/MM/YYYY tokens. Returns array: ['start'=>ISO|null,'end'=>ISO|null].
 *
 * Useful as a temporary fallback while rolling out client changes.
 *
 * @param array $post
 * @return array
 */
function afb_extract_dates_from_post_fields($post) {
    $out = ['start' => null, 'end' => null];
    if (!is_array($post)) return $out;

    foreach ($post as $k => $v) {
        if (!is_string($v)) continue;
        // only inspect keys that likely contain date info
        if (!preg_match('/date|window|run|start|end/i', $k)) continue;

        if (preg_match_all('/\b(\d{1,2}\/\d{1,2}\/\d{2,4})\b/', $v, $m)) {
            $dates = $m[1];
            // first match -> start, second -> end (if present)
            $iso1 = afb_parse_date_to_iso($dates[0] ?? '');
            if ($iso1 && !$out['start']) $out['start'] = $iso1;
            $iso2 = afb_parse_date_to_iso($dates[1] ?? '');
            if ($iso2 && !$out['end']) $out['end'] = $iso2;
        }
    }

    return $out;
}

/**
 * Combined resolver that attempts multiple strategies and returns array:
 * [ 'date' => 'YYYY-MM-DD' | null, 'source' => 'post'|'custom_fields'|'task_name'|'extracted'|null ]
 *
 * @param array $post
 * @param array $custom_fields
 * @param string $task_name
 * @return array
 */
function afb_resolve_due_date($post, $custom_fields = [], $task_name = '') {
    // 1) direct request keys & custom fields
    $from_request = afb_get_due_date_from_request($post, $custom_fields);
    if ($from_request) {
        return ['date' => $from_request, 'source' => 'post/custom_fields'];
    }

    // 2) attempt to extract from other post fields (safety-net)
    $extracted = afb_extract_dates_from_post_fields($post);
    if (!empty($extracted['start'])) {
        return ['date' => $extracted['start'], 'source' => 'extracted'];
    }
    if (!empty($extracted['end'])) {
        return ['date' => $extracted['end'], 'source' => 'extracted'];
    }

    // 3) try task name
    $from_name = afb_get_due_date_from_task_name($task_name);
    if ($from_name) {
        return ['date' => $from_name, 'source' => 'task_name'];
    }

    return ['date' => null, 'source' => null];
}

/*
 * USAGE NOTE:
 * - Replace existing task-date.php with this file.
 * - In your task handler (includes/task-handler.php) you can call:
 *     $resolved = afb_resolve_due_date($_POST, $custom_fields, $task_name ?? '');
 *     if (!empty($resolved['date'])) { $task_data['due_on'] = $resolved['date']; afb_log("Set due_on from {$resolved['source']}: {$resolved['date']}", 'afb-debug.log'); }
 *
 * This provides robustness while your client starts POSTing canonical 'start_date'/'end_date' keys.
 */
