<?php

declare(strict_types=1);

namespace App\Support\Imports;

use DateTimeInterface;
use Illuminate\Support\Carbon;
use PhpOffice\PhpSpreadsheet\Shared\Date as ExcelDate;
use Throwable;

/**
 * Cell-parsing shared by every ImportModule — trimming a blank cell to null,
 * reading a date (Excel serial, native date/time, or a handful of typed
 * formats a hand-filled template is likely to contain), and reading a
 * yes/no-shaped cell as a boolean. Kept here rather than duplicated per
 * module so all five import modules read the same kind of cell the same way.
 */
trait ParsesImportCells
{
    private function nullable(mixed $value): ?string
    {
        $value = trim((string) $value);

        return $value === '' ? null : $value;
    }

    /**
     * Reads an Excel serial date, a native date/time value, or one of a
     * handful of common typed formats. Spreadsheet software hands back dates
     * in whichever of these the sheet happens to be formatted as, and a
     * template filled in by hand is more likely to have a typed string than
     * a real date cell.
     */
    private function parseDate(mixed $value): ?Carbon
    {
        if ($value instanceof DateTimeInterface) {
            return Carbon::instance($value);
        }

        if (is_numeric($value)) {
            try {
                return Carbon::instance(ExcelDate::excelToDateTimeObject((float) $value));
            } catch (Throwable) {
                return null;
            }
        }

        $value = trim((string) $value);

        foreach (['d-m-Y', 'd/m/Y', 'Y-m-d', 'Y/m/d', 'm/d/Y'] as $format) {
            if (Carbon::hasFormat($value, $format)) {
                return Carbon::createFromFormat('!'.$format, $value) ?: null;
            }
        }

        return null;
    }

    /**
     * A blank cell defaults true (active) — the common case for a freshly
     * imported record — rather than forcing every row to spell it out.
     */
    private function parseActive(mixed $value): bool
    {
        $value = mb_strtolower(trim((string) $value));

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

        return in_array($value, ['1', 'yes', 'y', 'true', 'active'], true);
    }
}
