<?php
if (!isset($GLOBALS['con']) || !($GLOBALS['con'] instanceof mysqli)) {
    if (file_exists('../../../' . ($_REQUEST['tenant'] ?? '') . '/config.php')) {
        require_once('../../../' . ($_REQUEST['tenant'] ?? '') . '/config.php');
    }
    if (file_exists('/config.php')) {
        require_once('/config.php');
    }
}

if (!isset($GLOBALS['con']) || !($GLOBALS['con'] instanceof mysqli)) {
    http_response_code(500);
    exit('DB connection unavailable');
}

function jumpPlantCsvDownloadHeaders(string $filename): void
{
    while (ob_get_level() > 0) {
        ob_end_clean();
    }

    header('Content-Type: text/csv; charset=utf-8');
    header('Content-Disposition: attachment; filename="' . $filename . '"');
    header('Pragma: no-cache');
    header('Expires: 0');
}

function jumpPlantCsvJson(array $data, int $status = 200): void
{
    while (ob_get_level() > 0) {
        ob_end_clean();
    }

    http_response_code($status);
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($data);
    exit;
}

function jumpPlantCsvHeaderKey(string $value): string
{
    $value = preg_replace('/^\xEF\xBB\xBF/', '', $value);
    $value = strtolower(trim($value));

    if ($value === 'desc') {
        return 'description';
    }

    if ($value === 'freq') {
        return 'frequency';
    }

    if ($value === 'unit') {
        return 'units';
    }

    return $value;
}

function jumpPlantCsvFindIdByCode(string $code): int
{
    $stmt = $GLOBALS['con']->prepare("SELECT `id` FROM `dd_plant` WHERE `code` = ? LIMIT 1");
    $stmt->bind_param('s', $code);
    $stmt->execute();
    $res = $stmt->get_result();
    $row = $res ? $res->fetch_assoc() : null;
    $stmt->close();

    return (int)($row['id'] ?? 0);
}

function jumpPlantCsvInsert(string $code, string $description, int $frequency, ?float $units): bool
{
    try {
        $stmt = $GLOBALS['con']->prepare("
            INSERT INTO `dd_plant`
                (`code`, `description`, `frequency`, `units`)
            VALUES
                (?, ?, ?, ?)
        ");
        if (!$stmt) {
            return false;
        }

        $stmt->bind_param('ssid', $code, $description, $frequency, $units);
        $ok = $stmt->execute();
        $stmt->close();

        return $ok;
    } catch (Throwable $e) {
        return false;
    }
}

function jumpPlantCsvUpdate(int $id, string $description, int $frequency, ?float $units): bool
{
    try {
        $stmt = $GLOBALS['con']->prepare("
            UPDATE `dd_plant`
            SET `description` = ?,
                `frequency` = ?,
                `units` = ?
            WHERE `id` = ?
        ");
        if (!$stmt) {
            return false;
        }

        $stmt->bind_param('sidi', $description, $frequency, $units, $id);
        $ok = $stmt->execute();
        $stmt->close();

        return $ok;
    } catch (Throwable $e) {
        return false;
    }
}

$action = strtolower(trim((string)($_REQUEST['action'] ?? 'export')));

if ($action === 'template') {
    jumpPlantCsvDownloadHeaders('plant_list_template.csv');
    $out = fopen('php://output', 'w');
    fputcsv($out, ['code', 'description', 'frequency', 'units']);
    fputcsv($out, ['EXAMPLE', 'Example plant description', '6', '1']);
    fclose($out);
    exit;
}

if ($action === 'export') {
    jumpPlantCsvDownloadHeaders('plant_list_' . date('Ymd_His') . '.csv');
    $out = fopen('php://output', 'w');
    fputcsv($out, ['code', 'description', 'frequency', 'units']);

    $stmt = $GLOBALS['con']->prepare("
        SELECT `code`, `description`, `frequency`, `units`
        FROM `dd_plant`
        ORDER BY `code` ASC, `id` ASC
    ");
    if ($stmt) {
        $stmt->execute();
        $res = $stmt->get_result();
        $stmt->close();

        if ($res) {
            while ($row = $res->fetch_assoc()) {
                fputcsv($out, [
                    (string)($row['code'] ?? ''),
                    (string)($row['description'] ?? ''),
                    (string)($row['frequency'] ?? '0'),
                    (string)($row['units'] ?? '0')
                ]);
            }
        }
    }

    fclose($out);
    exit;
}

if ($action !== 'import') {
    jumpPlantCsvJson(['success' => false, 'message' => 'Unknown CSV action.'], 400);
}

if (empty($_FILES['csv']['tmp_name']) || !is_uploaded_file($_FILES['csv']['tmp_name'])) {
    jumpPlantCsvJson(['success' => false, 'message' => 'Choose a CSV file to import.'], 400);
}

$handle = fopen($_FILES['csv']['tmp_name'], 'r');
if (!$handle) {
    jumpPlantCsvJson(['success' => false, 'message' => 'Unable to read CSV file.'], 400);
}

$headers = fgetcsv($handle);
if (!$headers || !is_array($headers)) {
    fclose($handle);
    jumpPlantCsvJson(['success' => false, 'message' => 'CSV header row is missing.'], 400);
}

$columns = [];
foreach ($headers as $index => $header) {
    $columns[jumpPlantCsvHeaderKey((string)$header)] = $index;
}

$required = ['code', 'description', 'frequency'];
foreach ($required as $requiredColumn) {
    if (!isset($columns[$requiredColumn])) {
        fclose($handle);
        jumpPlantCsvJson([
            'success' => false,
            'message' => 'CSV must include code, description and frequency columns. Units are optional and the id column is intentionally ignored.'
        ], 400);
    }
}

$inserted = 0;
$updated = 0;
$skipped = 0;
$failed = 0;
$warnings = [];
$seenCodes = [];
$line = 1;

while (($row = fgetcsv($handle)) !== false) {
    $line++;

    $code = trim((string)($row[$columns['code']] ?? ''));
    $description = trim((string)($row[$columns['description']] ?? ''));
    $frequencyRaw = trim((string)($row[$columns['frequency']] ?? ''));
    $unitsRaw = trim((string)($row[$columns['units']] ?? ''));

    if ($code === '' && $description === '' && $frequencyRaw === '') {
        continue;
    }

    if ($code === '' || $description === '' || $frequencyRaw === '') {
        $skipped++;
        if (count($warnings) < 12) {
            $warnings[] = 'Line ' . $line . ' skipped: code, description and frequency are required.';
        }
        continue;
    }

    if (strlen($code) > 10) {
        $skipped++;
        if (count($warnings) < 12) {
            $warnings[] = 'Line ' . $line . ' skipped: code is longer than 10 characters (' . $code . ').';
        }
        continue;
    }

    if (strlen($description) > 70) {
        $skipped++;
        if (count($warnings) < 12) {
            $warnings[] = 'Line ' . $line . ' skipped: description is longer than 70 characters (' . $code . ').';
        }
        continue;
    }

    if (!preg_match('/^-?\d+$/', $frequencyRaw)) {
        $skipped++;
        if (count($warnings) < 12) {
            $warnings[] = 'Line ' . $line . ' skipped: frequency must be a whole number (' . $code . ').';
        }
        continue;
    }

    if ($unitsRaw !== '' && !is_numeric($unitsRaw)) {
        $skipped++;
        if (count($warnings) < 12) {
            $warnings[] = 'Line ' . $line . ' skipped: units must be numeric (' . $code . ').';
        }
        continue;
    }

    $codeKey = strtolower($code);
    if (isset($seenCodes[$codeKey])) {
        $skipped++;
        if (count($warnings) < 12) {
            $warnings[] = 'Line ' . $line . ' skipped: duplicate code in CSV (' . $code . ').';
        }
        continue;
    }
    $seenCodes[$codeKey] = true;

    $units = $unitsRaw === '' ? null : (float)$unitsRaw;
    $existingId = jumpPlantCsvFindIdByCode($code);

    if ($existingId > 0) {
        if (jumpPlantCsvUpdate($existingId, $description, (int)$frequencyRaw, $units)) {
            $updated++;
        } else {
            $failed++;
            if (count($warnings) < 12) {
                $warnings[] = 'Line ' . $line . ' failed to update existing code (' . $code . ').';
            }
        }
        continue;
    }

    if (jumpPlantCsvInsert($code, $description, (int)$frequencyRaw, $units)) {
        $inserted++;
    } else {
        $failed++;
        if (count($warnings) < 12) {
            $warnings[] = 'Line ' . $line . ' failed to import.';
        }
    }
}

$message = 'Import complete: ' . $inserted . ' added, ' . $updated . ' updated, ' . $skipped . ' skipped' . ($failed ? ', ' . $failed . ' failed' : '') . '.';
if (!empty($warnings[0])) {
    $message .= ' First issue: ' . $warnings[0];
}

fclose($handle);

jumpPlantCsvJson([
    'success' => $failed === 0,
    'message' => $message,
    'inserted' => $inserted,
    'updated' => $updated,
    'skipped' => $skipped,
    'failed' => $failed,
    'warnings' => $warnings
]);
