<?php

declare(strict_types=1);

namespace App\Framework\Exception\Core;

use App\Framework\Exception\ErrorCode;

/**
 * Filesystem error codes
 *
 * Covers file operations, directory operations, permissions, and I/O errors
 */
enum FilesystemErrorCode: string implements ErrorCode
{
    case FILE_NOT_FOUND = 'FS001';
    case FILE_READ_FAILED = 'FS002';
    case FILE_WRITE_FAILED = 'FS003';
    case FILE_DELETE_FAILED = 'FS004';
    case FILE_COPY_FAILED = 'FS005';
    case FILE_METADATA_FAILED = 'FS006';
    case PERMISSION_DENIED = 'FS007';
    case DIRECTORY_CREATE_FAILED = 'FS008';
    case DIRECTORY_LIST_FAILED = 'FS009';
    case PATH_TRAVERSAL_ATTEMPT = 'FS010';
    case INVALID_PATH = 'FS011';
    case DISK_FULL = 'FS012';
    case FILE_LOCKED = 'FS013';
    case SYMLINK_FAILED = 'FS014';
    case COMPRESSION_FAILED = 'FS015';
    case SERIALIZER_NOT_FOUND = 'FS016';

    public function getValue(): string
    {
        return $this->value;
    }

    public function getCategory(): string
    {
        return 'FS';
    }

    public function getNumericCode(): int
    {
        return (int) substr($this->value, 2); // Extract numeric part after 'FS'
    }

    public function getSeverity(): ErrorSeverity
    {
        return match ($this) {
            self::PATH_TRAVERSAL_ATTEMPT => ErrorSeverity::CRITICAL,
            self::PERMISSION_DENIED,
            self::DISK_FULL => ErrorSeverity::ERROR,
            self::FILE_NOT_FOUND,
            self::FILE_LOCKED,
            self::DIRECTORY_LIST_FAILED => ErrorSeverity::WARNING,
            default => ErrorSeverity::NOTICE
        };
    }

    public function getDescription(): string
    {
        return match ($this) {
            self::FILE_NOT_FOUND => 'The requested file could not be found',
            self::FILE_READ_FAILED => 'Failed to read file contents',
            self::FILE_WRITE_FAILED => 'Failed to write to file',
            self::FILE_DELETE_FAILED => 'Failed to delete file',
            self::FILE_COPY_FAILED => 'Failed to copy file',
            self::FILE_METADATA_FAILED => 'Failed to retrieve file metadata',
            self::PERMISSION_DENIED => 'Insufficient permissions for file operation',
            self::DIRECTORY_CREATE_FAILED => 'Failed to create directory',
            self::DIRECTORY_LIST_FAILED => 'Failed to list directory contents',
            self::PATH_TRAVERSAL_ATTEMPT => 'Path traversal attempt detected',
            self::INVALID_PATH => 'Invalid file path',
            self::DISK_FULL => 'Disk space exhausted',
            self::FILE_LOCKED => 'File is locked by another process',
            self::SYMLINK_FAILED => 'Failed to create symbolic link',
            self::COMPRESSION_FAILED => 'File compression/decompression failed',
            self::SERIALIZER_NOT_FOUND => 'Serializer not found in registry',
        };
    }

    public function getRecoveryHint(): string
    {
        return match ($this) {
            self::FILE_NOT_FOUND => 'Verify the file path exists',
            self::PERMISSION_DENIED => 'Check file/directory permissions and ownership',
            self::DISK_FULL => 'Free up disk space or increase storage capacity',
            self::FILE_LOCKED => 'Wait for other process to release the file lock',
            self::DIRECTORY_CREATE_FAILED => 'Verify parent directory exists and is writable',
            self::SERIALIZER_NOT_FOUND => 'Register the required serializer in SerializerRegistry',
            self::PATH_TRAVERSAL_ATTEMPT => 'Use validated paths only, avoid user-controlled path components',
            default => 'Check file system logs for more details'
        };
    }

    public function isRecoverable(): bool
    {
        return match ($this) {
            self::FILE_LOCKED,
            self::DISK_FULL => true,
            default => false
        };
    }

    public function getRetryAfterSeconds(): ?int
    {
        return match ($this) {
            self::FILE_LOCKED => 5,  // Retry after 5 seconds
            self::DISK_FULL => 60,   // Retry after 1 minute
            default => null
        };
    }
}
