<?php

declare(strict_types=1);

namespace App\Business\DataImport\Support;

use App\Business\DataImport\DataImportRow;
use App\Business\MasterData\Enums\SettlementMethod;
use App\Business\MasterData\Enums\WarehouseType;
use Illuminate\Support\Carbon;

final class DataImportValueParser
{
    public static function trimmed(?string $value): ?string
    {
        if ($value === null) {
            return null;
        }

        $trimmed = trim($value);

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

    public static function parseBoolean(?string $value, bool $default = true): bool
    {
        $normalized = self::trimmed($value);

        if ($normalized === null) {
            return $default;
        }

        if (in_array($normalized, ['1', 'true', 'TRUE', 'yes', 'YES', '是', '启用', 'Y', 'y'], true)) {
            return true;
        }

        if (in_array($normalized, ['0', 'false', 'FALSE', 'no', 'NO', '否', '停用', 'N', 'n'], true)) {
            return false;
        }

        throw new \InvalidArgumentException((string) __('dberp.data_import.validation.invalid_boolean'));
    }

    public static function parseSort(?string $value, int $default = 0): int
    {
        return self::parseSortOrder($value, $default);
    }

    public static function parseMasterRecordStatus(?string $value, string $default = 'active'): string
    {
        $normalized = self::trimmed($value);

        if ($normalized === null) {
            return $default;
        }

        $lower = strtolower($normalized);

        if (in_array($lower, ['active', '1', 'enabled', 'enable', '启用', '启用中'], true)) {
            return 'active';
        }

        if (in_array($lower, ['inactive', '0', 'disabled', 'disable', '停用', '已停用'], true)) {
            return 'inactive';
        }

        throw new \InvalidArgumentException((string) __('dberp.data_import.validation.invalid_master_record_status'));
    }

    public static function parseSettlementMethod(?string $value): string
    {
        $normalized = self::trimmed($value);

        if ($normalized === null) {
            return SettlementMethod::Cash->value;
        }

        $method = SettlementMethod::tryFrom(strtolower($normalized));

        if ($method !== null) {
            return $method->value;
        }

        $labels = SettlementMethod::options();
        $allowed = [];

        foreach (SettlementMethod::cases() as $case) {
            $allowed[] = sprintf('%s（%s）', $case->value, $labels[$case->value] ?? $case->value);
        }

        throw new \InvalidArgumentException((string) __('dberp.data_import.validation.invalid_settlement_method', [
            'allowed' => implode('、', $allowed),
        ]));
    }

    public static function parseOptionalEmail(?string $value): ?string
    {
        $normalized = self::trimmed($value);

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

        if (filter_var($normalized, FILTER_VALIDATE_EMAIL) === false) {
            throw new \InvalidArgumentException((string) __('dberp.data_import.validation.invalid_email'));
        }

        return $normalized;
    }

    public static function parseNonNegativeInteger(?string $value, ?int $default = null): ?int
    {
        $normalized = self::trimmed($value);

        if ($normalized === null) {
            return $default;
        }

        if (! preg_match('/^\d+$/', $normalized)) {
            throw new \InvalidArgumentException((string) __('dberp.data_import.validation.invalid_non_negative_integer'));
        }

        return (int) $normalized;
    }

    public static function parseNonNegativeDecimal(?string $value, ?string $default = null): ?string
    {
        $normalized = self::trimmed($value);

        if ($normalized === null) {
            return $default;
        }

        if (! is_numeric($normalized) || (float) $normalized < 0) {
            throw new \InvalidArgumentException((string) __('dberp.data_import.validation.invalid_non_negative_decimal'));
        }

        return number_format((float) $normalized, 4, '.', '');
    }

    public static function parsePositiveDecimal(?string $value): string
    {
        $normalized = self::trimmed($value);

        if ($normalized === null) {
            throw new \InvalidArgumentException((string) __('dberp.data_import.validation.quantity_required'));
        }

        if (! is_numeric($normalized) || (float) $normalized <= 0) {
            throw new \InvalidArgumentException((string) __('dberp.data_import.validation.invalid_positive_decimal'));
        }

        return number_format((float) $normalized, 4, '.', '');
    }

    public static function parseOptionalDate(?string $value): ?string
    {
        $normalized = self::trimmed($value);

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

        try {
            return Carbon::parse($normalized)->format('Y-m-d');
        } catch (\Throwable) {
            throw new \InvalidArgumentException((string) __('dberp.data_import.validation.invalid_date'));
        }
    }

    public static function parseOptionalDateTime(?string $value): ?\DateTimeInterface
    {
        $normalized = self::trimmed($value);

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

        try {
            return Carbon::parse($normalized);
        } catch (\Throwable) {
            throw new \InvalidArgumentException((string) __('dberp.data_import.validation.invalid_datetime'));
        }
    }

    public static function parseWarehouseType(?string $value): string
    {
        $normalized = self::trimmed($value);

        if ($normalized === null) {
            return WarehouseType::General->value;
        }

        $type = WarehouseType::tryFrom(strtolower($normalized));

        if ($type === null) {
            throw new \InvalidArgumentException((string) __('dberp.data_import.validation.invalid_warehouse_type'));
        }

        return $type->value;
    }

    public static function parseSortOrder(?string $value, int $default = 0): int
    {
        $normalized = self::trimmed($value);

        if ($normalized === null) {
            return $default;
        }

        if (! preg_match('/^-?\d+$/', $normalized)) {
            throw new \InvalidArgumentException((string) __('dberp.data_import.validation.invalid_sort_order'));
        }

        return (int) $normalized;
    }

    public static function rowError(int $rowNumber, string $message): string
    {
        return (string) __('dberp.data_import.validation.row_prefix', [
            'row' => $rowNumber,
            'message' => $message,
        ]);
    }

    /**
     * @param  list<DataImportRow>  $rows
     * @return array<string, list<int>>
     */
    public static function groupRowsByFieldValue(array $rows, string $field): array
    {
        $groups = [];

        foreach ($rows as $row) {
            $value = self::trimmed($row->value($field));

            if ($value === null) {
                continue;
            }

            $groups[$value][] = $row->rowNumber;
        }

        return $groups;
    }
}
