<?php
declare(strict_types=1);

namespace App\Repositories;

use App\Json\FileStore;

class JsonUserRepository implements UserRepository
{
    public function __construct(private FileStore $store) {}

    private function all_users(): array
    {
        $data = $this->store->read();
        return $data['users'] ?? [];
    }

    public function find(string $id): ?array
    {
        foreach ($this->all_users() as $u) {
            if (($u['id'] ?? null) === $id) return $u;
        }
        return null;
    }

    public function findByEmail(string $email): ?array
    {
        $email = strtolower(trim($email));
        if ($email === '') return null;
        foreach ($this->all_users() as $u) {
            if (strtolower((string)($u['email'] ?? '')) === $email) return $u;
        }
        return null;
    }

    public function findByUsername(string $username): ?array
    {
        $username = strtolower(trim($username));
        if ($username === '') return null;
        foreach ($this->all_users() as $u) {
            if (strtolower((string)($u['username'] ?? '')) === $username) return $u;
        }
        return null;
    }

    public function findByPhone(string $phone): ?array
    {
        $digits = preg_replace('/\D+/', '', $phone);
        if ($digits === '') return null;
        foreach ($this->all_users() as $u) {
            $uDigits = preg_replace('/\D+/', '', (string)($u['phone'] ?? ''));
            if ($uDigits === $digits) return $u;
        }
        return null;
    }

    public function search(string $query, ?string $role = null, int $limit = 25, bool $includeDeleted = false): array
    {
        $q = strtolower(trim($query));
        $results = [];
        foreach ($this->all_users() as $u) {
            // Skip soft-deleted unless explicitly requested
            if (!$includeDeleted && !empty($u['deleted_at'])) continue;
            if ($role !== null && ($u['role'] ?? '') !== $role) continue;
            if ($q === '') {
                $results[] = $u;
            } else {
                $haystack = strtolower(implode(' ', [
                    (string)($u['first_name'] ?? ''),
                    (string)($u['last_name'] ?? ''),
                    (string)($u['email'] ?? ''),
                    (string)($u['phone'] ?? ''),
                    (string)($u['address_line'] ?? ''),
                    (string)($u['username'] ?? ''),
                ]));
                if (str_contains($haystack, $q)) $results[] = $u;
            }
            if (count($results) >= $limit) break;
        }
        return $results;
    }

    public function softDelete(string $id, string $deletedByStaffId): void
    {
        $user = $this->find($id);
        if (!$user) return;
        $this->save(array_merge($user, [
            'deleted_at'        => now_iso(),
            'deleted_by_id'     => $deletedByStaffId,
            'is_active'         => false,
        ]));
    }

    public function save(array $user): array
    {
        $now = now_iso();
        $user['updated_at'] = $now;
        if (empty($user['id'])) {
            $user['id'] = uuid();
            $user['created_at'] = $now;
        }
        $this->store->transaction(function ($data) use (&$user) {
            $list = $data['users'] ?? [];
            $found = false;
            foreach ($list as $i => $existing) {
                if (($existing['id'] ?? null) === $user['id']) {
                    $list[$i] = array_merge($existing, $user);
                    $user = $list[$i];
                    $found = true;
                    break;
                }
            }
            if (!$found) $list[] = $user;
            $data['users'] = $list;
            return $data;
        });
        return $user;
    }

    public function delete(string $id): void
    {
        $this->store->transaction(function ($data) use ($id) {
            $list = $data['users'] ?? [];
            $data['users'] = array_values(array_filter($list, fn($u) => ($u['id'] ?? null) !== $id));
            return $data;
        });
    }

    public function all(array $filters = []): array
    {
        $users = $this->all_users();
        if (!empty($filters['role'])) {
            $users = array_values(array_filter($users, fn($u) => ($u['role'] ?? '') === $filters['role']));
        }
        if (array_key_exists('is_active', $filters)) {
            $users = array_values(array_filter($users, fn($u) => (bool)($u['is_active'] ?? true) === (bool)$filters['is_active']));
        }
        usort($users, fn($a, $b) => strcmp((string)($b['created_at'] ?? ''), (string)($a['created_at'] ?? '')));
        return $users;
    }
}
