<?php

namespace App\Services;

use App\Models\NumberingRule;
use Illuminate\Pagination\LengthAwarePaginator;

class NumberingRuleService
{
    public function getRules(array $filters = [], int $perPage = 20): LengthAwarePaginator
    {
        $tenantId = session('selected_tenant_id');
        $query = NumberingRule::query();

        if ($tenantId) {
            $query->where('tenant_id', $tenantId);
        }
        if (! empty($filters['document_type'])) {
            $query->where('document_type', $filters['document_type']);
        }
        if (isset($filters['is_active']) && $filters['is_active'] !== '') {
            $query->where('is_active', (bool) $filters['is_active']);
        }
        if (! empty($filters['search'])) {
            $query->where('rule_name', 'like', "%{$filters['search']}%");
        }

        return $query->orderBy('document_type')->paginate($perPage);
    }

    public function getRule(int $id): ?NumberingRule
    {
        $tenantId = session('selected_tenant_id');
        $query = NumberingRule::query();

        if ($tenantId) {
            $query->where('tenant_id', $tenantId);
        }

        return $query->find($id);
    }

    public function createRule(array $data): NumberingRule
    {
        $tenantId = session('selected_tenant_id');

        return NumberingRule::create([
            'tenant_id' => $tenantId,
            'document_type' => $data['document_type'],
            'rule_name' => $data['rule_name'] ?? null,
            'pattern' => $data['pattern'],
            'reset_period' => $data['reset_period'] ?? 'daily',
            'sequence_padding' => $data['sequence_padding'] ?? 2,
            'is_active' => $data['is_active'] ?? true,
            'created_by' => auth()->id(),
        ]);
    }

    public function updateRule(int $id, array $data): bool
    {
        $rule = $this->getRule($id);

        if (! $rule) {
            return false;
        }

        return $rule->update([
            'document_type' => $data['document_type'] ?? $rule->document_type,
            'rule_name' => $data['rule_name'] ?? $rule->rule_name,
            'pattern' => $data['pattern'] ?? $rule->pattern,
            'reset_period' => $data['reset_period'] ?? $rule->reset_period,
            'sequence_padding' => $data['sequence_padding'] ?? $rule->sequence_padding,
            'is_active' => $data['is_active'] ?? $rule->is_active,
            'updated_by' => auth()->id(),
        ]);
    }

    public function deleteRule(int $id): bool
    {
        $rule = $this->getRule($id);

        if (! $rule) {
            return false;
        }

        return $rule->delete();
    }

    public function getUsedDocumentTypes(?int $excludeId = null): array
    {
        $tenantId = session('selected_tenant_id');
        $query = NumberingRule::where('tenant_id', $tenantId);

        if ($excludeId) {
            $query->where('id', '!=', $excludeId);
        }

        return $query->pluck('document_type')->toArray();
    }

    public function generatePreview(array $pattern, int $sequencePadding = 2): string
    {
        $result = '';
        foreach ($pattern as $segment) {
            $result .= match ($segment['type'] ?? '') {
                'static' => $segment['value'] ?? '',
                'separator' => $segment['value'] ?? '',
                'date' => now()->format($segment['format'] ?? 'ymd'),
                'param' => $segment['default'] ?? '{'.($segment['key'] ?? '?').'}',
                'mapping' => $segment['default'] ?? '{'.($segment['key'] ?? '?').'}',
                'sequence' => str_pad('1', $sequencePadding, '0', STR_PAD_LEFT),
                default => '',
            };
        }

        return $result;
    }
}
