<?php

class FactoFileStorageService
{
    private $baseDir;

    public function __construct($baseDir = null)
    {
        $this->baseDir = $baseDir ?: dirname(__DIR__, 2) . '/storage/billing';
    }

    public function saveElectronicDocumentFiles($factoDocumentId, array $electronicDocument, $environment = 'production')
    {
        $saved = array(
            'pdf_file_path' => null,
            'xml_file_path' => null,
            'transfer_copy_pdf_file_path' => null,
            'stamp_img_file_path' => null
        );

        if (isset($electronicDocument['document_pdf']) && $electronicDocument['document_pdf']) {
            $saved['pdf_file_path'] = $this->saveBase64File(
                $electronicDocument['document_pdf'],
                $environment,
                'pdf',
                $factoDocumentId . '.pdf'
            );
        }

        if (isset($electronicDocument['document_xml']) && $electronicDocument['document_xml']) {
            $saved['xml_file_path'] = $this->saveBase64File(
                $electronicDocument['document_xml'],
                $environment,
                'xml',
                $factoDocumentId . '.xml'
            );
        }

        if (isset($electronicDocument['document_transfer_copy_pdf']) && $electronicDocument['document_transfer_copy_pdf']) {
            $saved['transfer_copy_pdf_file_path'] = $this->saveBase64File(
                $electronicDocument['document_transfer_copy_pdf'],
                $environment,
                'pdf_transfer_copy',
                $factoDocumentId . '_transfer_copy.pdf'
            );
        }

        if (isset($electronicDocument['stamp_img']) && $electronicDocument['stamp_img']) {
            $saved['stamp_img_file_path'] = $this->saveBase64File(
                $electronicDocument['stamp_img'],
                $environment,
                'stamp',
                $factoDocumentId . '_stamp.png'
            );
        }

        return $saved;
    }

    public function saveBase64File($base64, $environment, $type, $filename)
    {
        $environment = $this->safeSegment($environment ?: 'production');
        $type = $this->safeSegment($type ?: 'misc');
        $filename = $this->safeFilename($filename);

        $dir = $this->baseDir . '/' . $environment . '/' . $type;
        $this->ensureDirectory($dir);

        $binary = $this->decodeBase64Payload($base64);
        if ($binary === false) {
            throw new Exception('No fue posible decodificar archivo base64 FACTO.');
        }

        $path = $dir . '/' . $filename;
        $temporary = @tempnam($dir, '.facto-');
        if ($temporary === false || @file_put_contents($temporary, $binary, LOCK_EX) === false || !@rename($temporary, $path)) {
            if ($temporary !== false && is_file($temporary)) @unlink($temporary);
            error_log('FACTO storage write failed in ' . $dir . ' (writable=' . (is_writable($dir) ? 'yes' : 'no') . ')');
            throw new Exception('No fue posible guardar archivo FACTO en storage.');
        }
        @chmod($path, 0640);
        clearstatcache(true, $path);

        return $this->relativePath($path);
    }

    private function decodeBase64Payload($value)
    {
        $value = trim((string) $value);

        if ($value === '') {
            return false;
        }

        if (strpos($value, 'base64,') !== false) {
            $parts = explode('base64,', $value, 2);
            $value = $parts[1];
        }

        $value = preg_replace('/\s+/', '', $value);
        return base64_decode($value, true);
    }

    private function ensureDirectory($dir)
    {
        if (!is_dir($dir) && !mkdir($dir, 0775, true) && !is_dir($dir)) {
            throw new Exception('No fue posible crear directorio: ' . $dir);
        }
        @chmod($dir, 0775);
        if (!is_writable($dir)) {
            throw new Exception('Directorio FACTO sin permisos de escritura.');
        }

        $htaccess = $dir . '/.htaccess';
        if (!file_exists($htaccess)) {
            @file_put_contents($htaccess, "Deny from all\n");
        }
    }

    private function relativePath($absolutePath)
    {
        $root = dirname(__DIR__, 2);
        if (strpos($absolutePath, $root) === 0) {
            return ltrim(str_replace($root, '', $absolutePath), '/');
        }

        return $absolutePath;
    }

    private function safeSegment($value)
    {
        $value = strtolower(trim((string) $value));
        $value = preg_replace('/[^a-z0-9_\-]/', '_', $value);
        return $value ?: 'default';
    }

    private function safeFilename($value)
    {
        $value = trim((string) $value);
        $value = preg_replace('/[^A-Za-z0-9_\.\-]/', '_', $value);
        return $value ?: ('facto_' . date('YmdHis'));
    }
}
