<?php
namespace App\Services;

final class InvoicePdfService
{
    public function render(array $invoice,array $settings): string
    {
        $lines=[];
        $lines[]=['CARREFOUR DES ARTS DE BRAY-DUNES',18,true];
        $lines[]=[(string)($settings['legal_name']??'Carrefour des Arts'),11,false];
        $lines[]=[trim((string)($settings['address_line1']??'96, rue Auguste Coolen')),10,false];
        $lines[]=[trim((string)($settings['postal_code']??'59123').' '.(string)($settings['city']??'BRAY-DUNES')),10,false];
        $lines[]=['SIRET '.(string)($settings['siret']??'945 373 116 00017'),10,false];
        $lines[]=['',8,false];
        $type=(string)($invoice['document_type']??'invoice');
        $title=$type==='credit'?'AVOIR':($type==='proforma'?'FACTURE PRO FORMA':'FACTURE');
        $lines[]=[$title.' '.(string)($invoice['document_number']??''),16,true];
        $lines[]=['Date : '.$this->date((string)($invoice['issue_date']??'')),10,false];
        if(!empty($invoice['due_date']))$lines[]=['Échéance : '.$this->date((string)$invoice['due_date']),10,false];
        $lines[]=['',8,false];
        $lines[]=['DESTINATAIRE',11,true];
        $lines[]=[trim((string)($invoice['prenom']??'').' '.(string)($invoice['nom']??'')),11,false];
        $lines[]=['Compte adhérent : '.(string)($invoice['client_account']??''),10,false];
        if(!empty($invoice['adresse_ligne1']))$lines[]=[(string)$invoice['adresse_ligne1'],10,false];
        $city=trim((string)($invoice['code_postal']??'').' '.(string)($invoice['ville']??''));
        if($city!=='')$lines[]=[$city,10,false];
        $lines[]=['',8,false];
        $lines[]=['DÉSIGNATION                                             MONTANT',11,true];
        foreach(($invoice['lines']??[]) as $line){
            $label=$this->fit((string)($line['description']??''),58);
            $amount=number_format((float)($line['net_amount']??0),2,',',' ').' EUR';
            $lines[]=[$label.str_repeat(' ',max(2,66-strlen($label)-strlen($amount))).$amount,10,false];
            $period=trim((string)($line['service_start']??''));
            if(!empty($line['service_end']))$period.=' au '.(string)$line['service_end'];
            if($period!=='')$lines[]=['  Période : '.$period,8,false];
        }
        $lines[]=['',8,false];
        $lines[]=['TOTAL NET À PAYER : '.number_format((float)($invoice['total_amount']??0),2,',',' ').' EUR',13,true];
        if($type==='proforma')$lines[]=['Document pro forma sans valeur comptable.',10,true];
        $lines[]=['',8,false];
        $lines[]=[(string)($settings['vat_mention']??'Association non assujettie à la TVA.'),9,false];
        $lines[]=['Document officiel généré par AXIOM CDA.',8,false];
        return $this->document($lines);
    }

    private function document(array $lines): string
    {
        $content="BT\n";
        $y=790;
        foreach($lines as [$text,$size,$bold]){
            $font=$bold?'F2':'F1';
            $encoded=$this->pdfText($text);
            $content.="/$font $size Tf 1 0 0 1 50 $y Tm ($encoded) Tj\n";
            $y-=max(14,$size+5);
        }
        $content.="ET\n";
        $objects=[
            '<< /Type /Catalog /Pages 2 0 R >>',
            '<< /Type /Pages /Kids [3 0 R] /Count 1 >>',
            '<< /Type /Page /Parent 2 0 R /MediaBox [0 0 595 842] /Resources << /Font << /F1 5 0 R /F2 6 0 R >> >> /Contents 4 0 R >>',
            '<< /Length '.strlen($content)." >>\nstream\n".$content.'endstream',
            '<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >>',
            '<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding >>',
        ];
        $pdf="%PDF-1.4\n";
        $offsets=[0];
        foreach($objects as $index=>$object){
            $offsets[]=strlen($pdf);
            $pdf.=($index+1)." 0 obj\n".$object."\nendobj\n";
        }
        $xref=strlen($pdf);
        $pdf.="xref\n0 ".(count($objects)+1)."\n0000000000 65535 f \n";
        for($i=1;$i<=count($objects);$i++)$pdf.=sprintf("%010d 00000 n \n",$offsets[$i]);
        return $pdf."trailer\n<< /Size ".(count($objects)+1)." /Root 1 0 R >>\nstartxref\n$xref\n%%EOF";
    }

    private function pdfText(string $value): string
    {
        $value=iconv('UTF-8','Windows-1252//TRANSLIT',$value)?:$value;
        return str_replace(['\\','(',')',"\r","\n"],['\\\\','\\(','\\)',' ',' '],$value);
    }

    private function fit(string $value,int $length): string
    {
        $value=trim(preg_replace('/\s+/u',' ',$value)??$value);
        if(mb_strlen($value,'UTF-8')<=$length)return $value;
        return rtrim(mb_substr($value,0,$length-1,'UTF-8')).'…';
    }

    private function date(string $value): string
    {
        $timestamp=strtotime($value);
        return $timestamp?date('d/m/Y',$timestamp):'—';
    }
}
