<?php

declare(strict_types=1);

namespace App\Services;

use InvalidArgumentException;
use PDO;

final class BackupService
{
    public function __construct(private PDO $pdo)
    {
    }

    public function files(string $pattern = 'backup_*.sql'): array
    {
        $files = [];
        foreach (glob(backups_dir() . DIRECTORY_SEPARATOR . $pattern) as $p) {
            $files[] = ['name' => basename($p), 'size' => filesize($p) ?: 0, 'mtime' => filemtime($p) ?: 0];
        }
        usort($files, fn($a, $b) => $b['mtime'] <=> $a['mtime']);
        return $files;
    }

    public function create(string $note): string
    {
        return create_sql_backup($this->pdo, $note);
    }

    public function safePath(string $file): string
    {
        $file = basename($file);
        $path = backups_dir() . DIRECTORY_SEPARATOR . $file;
        if ($file === '' || !is_file($path)) {
            throw new InvalidArgumentException('الملف غير موجود');
        }
        return $path;
    }

    public function delete(string $file): void
    {
        $path = $this->safePath($file);
        @unlink($path);
        if (table_exists($this->pdo, 'db_backups')) {
            $this->pdo->prepare("DELETE FROM db_backups WHERE file_name=?")->execute([basename($file)]);
        }
        audit_log('BACKUP_DELETE', 'db_backup', null, ['file' => basename($file)]);
    }

    private function validateUploadedSql(array $file): void
    {
        $err = (int) ($file['error'] ?? UPLOAD_ERR_NO_FILE);
        if ($err !== UPLOAD_ERR_OK) {
            throw new InvalidArgumentException('فشل رفع ملف النسخة.');
        }

        $tmp = (string) ($file['tmp_name'] ?? '');
        if ($tmp === '' || !is_uploaded_file($tmp)) {
            throw new InvalidArgumentException('ملف النسخة غير صالح.');
        }

        $size = (int) ($file['size'] ?? 0);
        if ($size <= 0 || $size > 20 * 1024 * 1024) {
            throw new InvalidArgumentException('حجم ملف النسخة يجب ألا يتجاوز 20MB.');
        }

        $ext = strtolower(pathinfo((string) ($file['name'] ?? ''), PATHINFO_EXTENSION));
        if ($ext !== 'sql') {
            throw new InvalidArgumentException('يُسمح فقط بملفات SQL.');
        }

        $head = (string) (file_get_contents($tmp, false, null, 0, 4096) ?: '');
        if (!preg_match('/(CREATE TABLE|INSERT INTO|START TRANSACTION|-- phpMyAdmin SQL Dump)/i', $head)) {
            throw new InvalidArgumentException('الملف لا يبدو نسخة SQL صالحة.');
        }
    }

    public function restore(array $post, array $files): array
    {
        $confirm = trim((string)($post['confirm'] ?? ''));
        if ($confirm !== 'RESTORE') {
            throw new InvalidArgumentException('اكتب RESTORE للتأكيد');
        }

        $path = null;
        $selected = basename((string)($post['file'] ?? ''));
        if (!empty($files['upload']['name'] ?? '')) {
            $this->validateUploadedSql($files['upload']);
            $tmp = $files['upload']['tmp_name'] ?? '';
            if ($tmp && is_uploaded_file($tmp)) {
                $name = 'upload_' . date('Ymd_His') . '.sql';
                $dest = backups_dir() . DIRECTORY_SEPARATOR . $name;
                if (!move_uploaded_file($tmp, $dest)) {
                    throw new InvalidArgumentException('تعذر حفظ ملف النسخة المرفوعة.');
                }
                $path = $dest;
            }
        } elseif ($selected !== '') {
            $path = $this->safePath($selected);
        }
        if (!$path) {
            throw new InvalidArgumentException('اختر ملف نسخة أو ارفع ملف');
        }
        return restore_sql_backup($this->pdo, $path);
    }
}
