@page "/check"
@attribute [Authorize]
@rendermode InteractiveServer

@inject ICVCheckService CVCheckService
@inject NavigationManager NavigationManager
@inject AuthenticationStateProvider AuthenticationStateProvider
@inject ILogger<Check> Logger

<PageTitle>Upload CV - TrueCV</PageTitle>

<div class="container py-5">
    <div class="row justify-content-center">
        <div class="col-lg-8">
            <div class="text-center mb-4">
                <h1 class="fw-bold">Upload CV for Verification</h1>
                <p class="text-muted lead">Upload a CV in PDF or DOCX format to begin the verification process</p>
            </div>

            @if (!string.IsNullOrEmpty(_errorMessage))
            {
                <div class="alert alert-danger alert-dismissible fade show" role="alert">
                    @_errorMessage
                    <button type="button" class="btn-close" @onclick="() => _errorMessage = null" aria-label="Close"></button>
                </div>
            }

            <div class="card border-0 shadow">
                <div class="card-body p-5">
                    @if (_isUploading)
                    {
                        <div class="text-center py-5">
                            <div class="spinner-border text-primary mb-3" role="status" style="width: 3rem; height: 3rem;">
                                <span class="visually-hidden">Uploading...</span>
                            </div>
                            <h5 class="mb-2">Uploading your CV...</h5>
                            <p class="text-muted">Please wait while we process your file</p>
                            <div class="progress" style="height: 8px;">
                                <div class="progress-bar progress-bar-striped progress-bar-animated"
                                     role="progressbar"
                                     style="width: @(_uploadProgress)%"
                                     aria-valuenow="@_uploadProgress"
                                     aria-valuemin="0"
                                     aria-valuemax="100">
                                </div>
                            </div>
                        </div>
                    }
                    else
                    {
                        <div class="upload-area @(_isDragging ? "dragging" : "")"
                             @ondragenter="HandleDragEnter"
                             @ondragleave="HandleDragLeave"
                             @ondragover:preventDefault
                             @ondrop="HandleDrop"
                             @ondrop:preventDefault>

                            <InputFile OnChange="HandleFileSelected"
                                       accept=".pdf,.docx"
                                       class="d-none"
                                       id="fileInput" />

                            <label for="fileInput" class="d-block text-center py-5 cursor-pointer">
                                <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" fill="currentColor" class="bi bi-cloud-arrow-up text-primary mb-3" viewBox="0 0 16 16">
                                    <path fill-rule="evenodd" d="M7.646 5.146a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1-.708.708L8.5 6.707V10.5a.5.5 0 0 1-1 0V6.707L6.354 7.854a.5.5 0 1 1-.708-.708l2-2z"/>
                                    <path d="M4.406 3.342A5.53 5.53 0 0 1 8 2c2.69 0 4.923 2 5.166 4.579C14.758 6.804 16 8.137 16 9.773 16 11.569 14.502 13 12.687 13H3.781C1.708 13 0 11.366 0 9.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383zm.653.757c-.757.653-1.153 1.44-1.153 2.056v.448l-.445.049C2.064 6.805 1 7.952 1 9.318 1 10.785 2.23 12 3.781 12h8.906C13.98 12 15 10.988 15 9.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 4.825 10.328 3 8 3a4.53 4.53 0 0 0-2.941 1.1z"/>
                                </svg>
                                <h5 class="mb-2">Drag and drop your CV here</h5>
                                <p class="text-muted mb-3">or click to browse files</p>
                                <span class="badge bg-light text-dark">Accepted formats: PDF, DOCX</span>
                            </label>
                        </div>

                        @if (_selectedFile is not null)
                        {
                            <div class="mt-4 p-3 bg-light rounded d-flex align-items-center justify-content-between">
                                <div class="d-flex align-items-center">
                                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-file-earmark-text text-primary me-3" viewBox="0 0 16 16">
                                        <path d="M5.5 7a.5.5 0 0 0 0 1h5a.5.5 0 0 0 0-1h-5zM5 9.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5zm0 2a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5z"/>
                                        <path d="M9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V4.5L9.5 0zm0 1v2A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h5.5z"/>
                                    </svg>
                                    <div>
                                        <p class="mb-0 fw-medium">@_selectedFile.Name</p>
                                        <small class="text-muted">@FormatFileSize(_selectedFile.Size)</small>
                                    </div>
                                </div>
                                <button class="btn btn-outline-danger btn-sm" @onclick="ClearFile">
                                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x-lg" viewBox="0 0 16 16">
                                        <path d="M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8 2.146 2.854Z"/>
                                    </svg>
                                </button>
                            </div>

                            <div class="mt-4 text-center">
                                <button class="btn btn-primary btn-lg px-5" @onclick="UploadFile">
                                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-upload me-2" viewBox="0 0 16 16">
                                        <path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5z"/>
                                        <path d="M7.646 1.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708L8.5 2.707V11.5a.5.5 0 0 1-1 0V2.707L5.354 4.854a.5.5 0 1 1-.708-.708l3-3z"/>
                                    </svg>
                                    Start Verification
                                </button>
                            </div>
                        }
                    }
                </div>
            </div>

            <div class="mt-4 text-center">
                <small class="text-muted">
                    <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" class="bi bi-shield-check me-1" viewBox="0 0 16 16">
                        <path d="M5.338 1.59a61.44 61.44 0 0 0-2.837.856.481.481 0 0 0-.328.39c-.554 4.157.726 7.19 2.253 9.188a10.725 10.725 0 0 0 2.287 2.233c.346.244.652.42.893.533.12.057.218.095.293.118a.55.55 0 0 0 .101.025.615.615 0 0 0 .1-.025c.076-.023.174-.061.294-.118.24-.113.547-.29.893-.533a10.726 10.726 0 0 0 2.287-2.233c1.527-1.997 2.807-5.031 2.253-9.188a.48.48 0 0 0-.328-.39c-.651-.213-1.75-.56-2.837-.855C9.552 1.29 8.531 1.067 8 1.067c-.53 0-1.552.223-2.662.524zM5.072.56C6.157.265 7.31 0 8 0s1.843.265 2.928.56c1.11.3 2.229.655 2.887.87a1.54 1.54 0 0 1 1.044 1.262c.596 4.477-.787 7.795-2.465 9.99a11.775 11.775 0 0 1-2.517 2.453 7.159 7.159 0 0 1-1.048.625c-.28.132-.581.24-.829.24s-.548-.108-.829-.24a7.158 7.158 0 0 1-1.048-.625 11.777 11.777 0 0 1-2.517-2.453C1.928 10.487.545 7.169 1.141 2.692A1.54 1.54 0 0 1 2.185 1.43 62.456 62.456 0 0 1 5.072.56z"/>
                        <path d="M10.854 5.146a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 1 1 .708-.708L7.5 7.793l2.646-2.647a.5.5 0 0 1 .708 0z"/>
                    </svg>
                    Your files are processed securely and stored encrypted
                </small>
            </div>
        </div>
    </div>
</div>

<style>
    .upload-area {
        border: 2px dashed #dee2e6;
        border-radius: 0.5rem;
        transition: all 0.3s ease;
        cursor: pointer;
    }

    .upload-area:hover,
    .upload-area.dragging {
        border-color: var(--bs-primary);
        background-color: rgba(var(--bs-primary-rgb), 0.05);
    }

    .cursor-pointer {
        cursor: pointer;
    }
</style>

@code {
    private IBrowserFile? _selectedFile;
    private bool _isUploading;
    private bool _isDragging;
    private int _uploadProgress;
    private string? _errorMessage;

    private const long MaxFileSize = 10 * 1024 * 1024; // 10MB

    // Magic bytes for file type validation
    private static readonly byte[] PdfMagicBytes = [0x25, 0x50, 0x44, 0x46]; // %PDF
    private static readonly byte[] DocxMagicBytes = [0x50, 0x4B, 0x03, 0x04]; // PK.. (ZIP signature)

    private void HandleDragEnter()
    {
        _isDragging = true;
    }

    private void HandleDragLeave()
    {
        _isDragging = false;
    }

    private void HandleDrop()
    {
        _isDragging = false;
    }

    private void HandleFileSelected(InputFileChangeEventArgs e)
    {
        _errorMessage = null;
        var file = e.File;

        if (!IsValidFileType(file.Name))
        {
            _errorMessage = "Invalid file type. Please upload a PDF or DOCX file.";
            return;
        }

        if (file.Size > MaxFileSize)
        {
            _errorMessage = "File size exceeds 10MB limit.";
            return;
        }

        _selectedFile = file;
    }

    private void ClearFile()
    {
        _selectedFile = null;
        _errorMessage = null;
    }

    private CancellationTokenSource? _progressCts;

    private async Task UploadFile()
    {
        if (_selectedFile is null) return;

        _progressCts = new CancellationTokenSource();
        Task? progressTask = null;

        try
        {
            _isUploading = true;
            _uploadProgress = 0;
            _errorMessage = null;

            var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
            var userIdClaim = authState.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;

            if (string.IsNullOrEmpty(userIdClaim) || !Guid.TryParse(userIdClaim, out var userId))
            {
                _errorMessage = "Unable to identify user. Please log in again.";
                _isUploading = false;
                return;
            }

            // Simulate progress for better UX
            progressTask = SimulateProgress(_progressCts.Token);

            await using var stream = _selectedFile.OpenReadStream(MaxFileSize);
            using var memoryStream = new MemoryStream();
            await stream.CopyToAsync(memoryStream);
            memoryStream.Position = 0;

            // Validate file content (magic bytes)
            if (!await ValidateFileContentAsync(memoryStream, _selectedFile.Name))
            {
                _errorMessage = "Invalid file content. The file appears to be corrupted or not a valid PDF/DOCX.";
                return;
            }

            var checkId = await CVCheckService.CreateCheckAsync(userId, memoryStream, _selectedFile.Name);

            _uploadProgress = 100;
            await InvokeAsync(StateHasChanged);
            await Task.Delay(500); // Brief pause to show completion

            NavigationManager.NavigateTo($"/report/{checkId}");
        }
        catch (Exception ex)
        {
            Logger.LogError(ex, "Error uploading CV");
            _errorMessage = "An error occurred while uploading. Please try again.";
        }
        finally
        {
            _isUploading = false;
            _progressCts?.Cancel();
            if (progressTask is not null)
            {
                try { await progressTask; } catch (OperationCanceledException) { }
            }
            _progressCts?.Dispose();
            _progressCts = null;
        }
    }

    private async Task SimulateProgress(CancellationToken cancellationToken)
    {
        try
        {
            while (_uploadProgress < 90 && _isUploading && !cancellationToken.IsCancellationRequested)
            {
                await Task.Delay(200, cancellationToken);
                _uploadProgress += 10;
                await InvokeAsync(StateHasChanged);
            }
        }
        catch (OperationCanceledException)
        {
            // Expected when upload completes
        }
    }

    private async Task<bool> ValidateFileContentAsync(MemoryStream stream, string fileName)
    {
        var extension = Path.GetExtension(fileName).ToLowerInvariant();
        var header = new byte[4];

        stream.Position = 0;
        var bytesRead = await stream.ReadAsync(header.AsMemory(0, 4));
        stream.Position = 0;

        if (bytesRead < 4)
            return false;

        return extension switch
        {
            ".pdf" => header.AsSpan().StartsWith(PdfMagicBytes),
            ".docx" => header.AsSpan().StartsWith(DocxMagicBytes),
            _ => false
        };
    }

    private bool IsValidFileType(string fileName)
    {
        var extension = Path.GetExtension(fileName).ToLowerInvariant();
        return extension is ".pdf" or ".docx";
    }

    private static string FormatFileSize(long bytes)
    {
        string[] sizes = ["B", "KB", "MB", "GB"];
        int order = 0;
        double size = bytes;

        while (size >= 1024 && order < sizes.Length - 1)
        {
            order++;
            size /= 1024;
        }

        return $"{size:0.##} {sizes[order]}";
    }
}
