<?php
/**
 * Download Controller
 *
 * @package Jeremias\WcLicensedProduct\Frontend
 */

declare(strict_types=1);

namespace Jeremias\WcLicensedProduct\Frontend;

use Jeremias\WcLicensedProduct\License\LicenseManager;
use Jeremias\WcLicensedProduct\Product\VersionManager;

/**
 * Handles secure file downloads for licensed customers
 */
final class DownloadController
{
    private LicenseManager $licenseManager;
    private VersionManager $versionManager;

    public function __construct(LicenseManager $licenseManager, VersionManager $versionManager)
    {
        $this->licenseManager = $licenseManager;
        $this->versionManager = $versionManager;
        $this->registerHooks();
    }

    /**
     * Register WordPress hooks
     */
    private function registerHooks(): void
    {
        // Add download endpoint
        add_action('init', [$this, 'addDownloadEndpoint']);

        // Register query var for the endpoint
        add_filter('query_vars', [$this, 'addDownloadQueryVar']);

        // Handle download requests
        add_action('template_redirect', [$this, 'handleDownloadRequest']);
    }

    /**
     * Add download endpoint
     */
    public function addDownloadEndpoint(): void
    {
        add_rewrite_endpoint('license-download', EP_ROOT | EP_PAGES);
    }

    /**
     * Register the download query var
     */
    public function addDownloadQueryVar(array $vars): array
    {
        $vars[] = 'license-download';
        return $vars;
    }

    /**
     * Handle download request
     */
    public function handleDownloadRequest(): void
    {
        global $wp_query;

        if (!isset($wp_query->query_vars['license-download'])) {
            return;
        }

        $downloadKey = sanitize_text_field($wp_query->query_vars['license-download']);

        if (empty($downloadKey)) {
            wp_die(
                __('Invalid download link.', 'wc-licensed-product'),
                __('Download Error', 'wc-licensed-product'),
                ['response' => 403]
            );
        }

        // Parse download key: format is "license_id-version_id-hash"
        $parts = explode('-', $downloadKey);
        if (count($parts) < 3) {
            wp_die(
                __('Invalid download link format.', 'wc-licensed-product'),
                __('Download Error', 'wc-licensed-product'),
                ['response' => 403]
            );
        }

        $licenseId = absint($parts[0]);
        $versionId = absint($parts[1]);
        $hash = $parts[2];

        // Verify hash
        $expectedHash = $this->generateDownloadHash($licenseId, $versionId);
        if (!hash_equals($expectedHash, $hash)) {
            wp_die(
                __('Invalid download link.', 'wc-licensed-product'),
                __('Download Error', 'wc-licensed-product'),
                ['response' => 403]
            );
        }

        // Check user authentication
        if (!is_user_logged_in()) {
            wp_redirect(wp_login_url(home_url('license-download/' . $downloadKey)));
            exit;
        }

        // Get license
        $license = $this->licenseManager->getLicenseById($licenseId);
        if (!$license) {
            wp_die(
                __('License not found.', 'wc-licensed-product'),
                __('Download Error', 'wc-licensed-product'),
                ['response' => 404]
            );
        }

        // Verify user owns the license
        $currentUserId = get_current_user_id();
        if ($license->getCustomerId() !== $currentUserId) {
            wp_die(
                __('You do not have permission to download this file.', 'wc-licensed-product'),
                __('Download Error', 'wc-licensed-product'),
                ['response' => 403]
            );
        }

        // Check license status
        if ($license->getStatus() !== 'active') {
            wp_die(
                __('Your license is not active. Please contact support.', 'wc-licensed-product'),
                __('Download Error', 'wc-licensed-product'),
                ['response' => 403]
            );
        }

        // Get version
        $version = $this->versionManager->getVersionById($versionId);
        if (!$version) {
            wp_die(
                __('Version not found.', 'wc-licensed-product'),
                __('Download Error', 'wc-licensed-product'),
                ['response' => 404]
            );
        }

        // Verify version belongs to licensed product
        if ($version->getProductId() !== $license->getProductId()) {
            wp_die(
                __('Version does not match your licensed product.', 'wc-licensed-product'),
                __('Download Error', 'wc-licensed-product'),
                ['response' => 403]
            );
        }

        // Check if version is active
        if (!$version->isActive()) {
            wp_die(
                __('This version is no longer available for download.', 'wc-licensed-product'),
                __('Download Error', 'wc-licensed-product'),
                ['response' => 403]
            );
        }

        // Get download file
        $attachmentId = $version->getAttachmentId();
        $downloadUrl = $version->getDownloadUrl();

        if ($attachmentId) {
            // Increment download count before serving
            $this->versionManager->incrementDownloadCount($versionId);
            $this->serveAttachment($attachmentId, $version->getVersion());
        } elseif ($downloadUrl) {
            // Increment download count before redirect
            $this->versionManager->incrementDownloadCount($versionId);
            // Redirect to external URL
            wp_redirect($downloadUrl);
            exit;
        } else {
            wp_die(
                __('No download file available for this version.', 'wc-licensed-product'),
                __('Download Error', 'wc-licensed-product'),
                ['response' => 404]
            );
        }
    }

    /**
     * Serve attachment file for download
     */
    private function serveAttachment(int $attachmentId, string $version): void
    {
        $filePath = get_attached_file($attachmentId);

        if (!$filePath || !file_exists($filePath)) {
            wp_die(
                __('Download file not found.', 'wc-licensed-product'),
                __('Download Error', 'wc-licensed-product'),
                ['response' => 404]
            );
        }

        $filename = wp_basename($filePath);
        $mimeType = mime_content_type($filePath) ?: 'application/octet-stream';
        $fileSize = filesize($filePath);

        // Prevent caching
        nocache_headers();

        // Set headers for download
        header('Content-Type: ' . $mimeType);
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        header('Content-Length: ' . $fileSize);
        header('Content-Transfer-Encoding: binary');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Expires: 0');
        header('Pragma: public');

        // Clear output buffer
        if (ob_get_level()) {
            ob_end_clean();
        }

        // Read file and output
        readfile($filePath);
        exit;
    }

    /**
     * Generate download hash for security
     */
    public function generateDownloadHash(int $licenseId, int $versionId): string
    {
        $data = $licenseId . '-' . $versionId . '-' . wp_salt('auth');
        return substr(hash('sha256', $data), 0, 16);
    }

    /**
     * Generate download URL for a license and version
     */
    public function generateDownloadUrl(int $licenseId, int $versionId): string
    {
        $hash = $this->generateDownloadHash($licenseId, $versionId);
        $downloadKey = $licenseId . '-' . $versionId . '-' . $hash;

        return home_url('license-download/' . $downloadKey);
    }
}
