<?php

namespace App\Services;

use App\Models\Business;
use App\Models\Loan;

class LoanContractPdfService
{
    public function generate(Loan $loan, Business $business): string
    {
        $loan->loadMissing(['customer','branch','product','guarantor','collaterals','installments']);
        $currency = trim(($business->currency_symbol ?: $business->currency ?: '').' ');
        $lines = [
            strtoupper($business->name ?: 'MICROFINANCE'),
            'LOAN AGREEMENT / CONTRACT',
            '',
            'Loan Number: '.$loan->loan_number,
            'Branch: '.$loan->branch->name,
            'Contract Date: '.now()->format('d M Y'),
            '',
            'BUSINESS DETAILS',
            'Business: '.$business->name,
            'Registration No: '.($business->registration_number ?: 'N/A').'   TIN: '.($business->tin ?: 'N/A'),
            'Address: '.collect([$business->address,$business->district,$business->region,$business->country])->filter()->join(', '),
            'Phone: '.($business->phone ?: 'N/A').'   Email: '.($business->email ?: 'N/A'),
            '',
            'BORROWER',
            'Customer: '.$loan->customer->full_name.' ('.$loan->customer->customer_number.')',
            'Phone: '.$loan->customer->phone.'   NIN: '.($loan->customer->nin ?: 'Not provided'),
            '',
            'LOAN TERMS',
            'Product: '.$loan->product->name,
            'Purpose: '.$loan->purpose,
            'Principal: '.$currency.number_format((float)$loan->principal,2),
            'Interest: '.$currency.number_format((float)$loan->interest,2),
            'Processing Fee: '.$currency.number_format((float)$loan->processing_fee,2),
            'Insurance Fee: '.$currency.number_format((float)$loan->insurance_fee,2),
            'Other Charges: '.$currency.number_format((float)$loan->other_charges,2),
            'Total Fees: '.$currency.number_format((float)$loan->fees,2),
            'TOTAL REPAYMENT: '.$currency.number_format((float)$loan->total_repayment,2),
            'Interest Method: '.str($loan->product->interest_calculation_method)->replace('_',' ')->title(),
            'Repayment Frequency: '.str($loan->product->repayment_frequency)->replace('_',' ')->title(),
            'Late Payment Rule: '.str($loan->late_payment_penalty_type)->replace('_',' ')->title().' '.$loan->late_payment_penalty_value,
            '',
            'COLLATERAL',
        ];

        if ($loan->collaterals->isEmpty()) $lines[] = 'No collateral linked to this application.';
        foreach ($loan->collaterals as $item) {
            $lines[] = $item->code.' - '.$item->item.' - accepted value '.$currency.number_format((float)($item->accepted_value ?? 0),2);
        }

        $lines[] = '';
        $lines[] = 'GUARANTOR';
        $lines[] = $loan->guarantor
            ? $loan->guarantor->full_name.' - '.$loan->guarantor->phone.' - NIN '.($loan->guarantor->nin ?: 'N/A')
            : 'No guarantor linked to this application.';
        $lines[] = '';
        $lines[] = 'REPAYMENT SCHEDULE';
        $lines[] = '#   Due Date     Principal     Interest     Fees        Amount Due';
        foreach ($loan->installments as $installment) {
            $lines[] = sprintf(
                '%-3d %-12s %12s %12s %10s %14s',
                $installment->installment_number,
                $installment->due_date->format('Y-m-d'),
                number_format((float)$installment->principal,2),
                number_format((float)$installment->interest,2),
                number_format((float)$installment->fees,2),
                number_format((float)$installment->amount_due,2),
            );
        }

        array_push($lines,
            '',
            'BORROWER OBLIGATIONS',
            '1. The borrower agrees to repay the loan according to the schedule above.',
            '2. Payments must be made through channels authorized by the lender and properly receipted.',
            '3. Late payments may attract the product penalty stated in this contract.',
            '4. The borrower must keep contact and address information current during the loan term.',
            '5. Pledged collateral must not be sold, transferred or encumbered without written approval.',
            '6. Collateral release is subject to full settlement and the lender custody-release process.',
            '',
            'ACKNOWLEDGEMENT',
            'The borrower confirms that the loan terms, charges, schedule, collateral obligations and late-payment rules have been explained and accepted.',
            '',
            'Borrower Name: '.$loan->customer->full_name,
            'Borrower Signature: __________________________   Date: _______________',
            '',
            'Guarantor Signature: _________________________   Date: _______________',
            '',
            'For '.$business->name.': _____________________   Date: _______________',
            'Name / Position: ____________________________________________________',
            '',
            'This contract is generated from the loan application record '.$loan->loan_number.'.'
        );

        return $this->pdf($this->wrapLines($lines));
    }

    private function wrapLines(array $lines, int $width = 98): array
    {
        $out = [];
        foreach ($lines as $line) {
            $parts = $line === '' ? [''] : explode("\n", wordwrap((string)$line, $width, "\n", true));
            foreach ($parts as $part) $out[] = $part;
        }
        return $out;
    }

    private function pdf(array $lines): string
    {
        $pages = array_chunk($lines, 48);
        $objects = [];
        $objects[1] = '<< /Type /Catalog /Pages 2 0 R >>';
        $objects[3] = '<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>';
        $kids = [];

        foreach ($pages as $i => $pageLines) {
            $pageObj = 4 + ($i * 2);
            $contentObj = $pageObj + 1;
            $kids[] = $pageObj.' 0 R';
            $stream = "BT\n/F1 10 Tf\n50 792 Td\n14 TL\n";
            foreach ($pageLines as $line) {
                $stream .= '('.$this->escape($line).") Tj\nT*\n";
            }
            $stream .= "ET";
            $objects[$pageObj] = '<< /Type /Page /Parent 2 0 R /MediaBox [0 0 595 842] /Resources << /Font << /F1 3 0 R >> >> /Contents '.$contentObj.' 0 R >>';
            $objects[$contentObj] = '<< /Length '.strlen($stream)." >>\nstream\n".$stream."\nendstream";
        }

        $objects[2] = '<< /Type /Pages /Kids ['.implode(' ', $kids).'] /Count '.count($pages).' >>';
        ksort($objects);
        $pdf = "%PDF-1.4\n";
        $offsets = [0];
        foreach ($objects as $number => $body) {
            $offsets[$number] = strlen($pdf);
            $pdf .= $number." 0 obj\n".$body."\nendobj\n";
        }
        $xref = strlen($pdf);
        $max = max(array_keys($objects));
        $pdf .= "xref\n0 ".($max + 1)."\n0000000000 65535 f \n";
        for ($i = 1; $i <= $max; $i++) {
            $pdf .= sprintf('%010d 00000 n ', $offsets[$i] ?? 0)."\n";
        }
        $pdf .= "trailer\n<< /Size ".($max + 1).' /Root 1 0 R >>'."\nstartxref\n{$xref}\n%%EOF";
        return $pdf;
    }

    private function escape(string $text): string
    {
        $text = iconv('UTF-8', 'Windows-1252//TRANSLIT//IGNORE', $text) ?: $text;
        return str_replace(['\\','(',')'], ['\\\\','\\(','\\)'], $text);
    }
}
