<?php

namespace App\Exports;

use App\Models\Partner;
use App\Models\JournalEntryLine;
use App\Services\AccountingService;
use App\Models\Account;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Carbon\Carbon;

class PartnerLedgerDetailExport implements FromCollection, WithHeadings, WithMapping, ShouldAutoSize
{
    protected $partnerId;
    protected $dateFrom;
    protected $dateTo;
    
    // Internal state for running balance
    protected $runningBalance = 0;
    protected $partnerTypeGroup = 'customer'; // customer or supplier to determine balance sign

    public function __construct($partnerId, $dateFrom, $dateTo)
    {
        $this->partnerId = $partnerId;
        $this->dateFrom = $dateFrom;
        $this->dateTo = $dateTo;
        
        $partner = Partner::with('partnerType')->find($partnerId);
        if ($partner && $partner->partnerType) {
            if ($partner->partnerType->is_supplier_group && !$partner->partnerType->is_customer_group) {
                $this->partnerTypeGroup = 'supplier';
            }
        }
    }

    public function collection()
    {
        $accountIds = Account::whereIn('code', [
            AccountingService::ACCOUNTS_RECEIVABLE, 
            AccountingService::ACCOUNTS_PAYABLE
        ])->pluck('id');
        
        if ($accountIds->isEmpty()) {
            return collect([]);
        }

        return JournalEntryLine::query()
            ->whereIn('account_id', $accountIds)
            ->whereHas('journalEntry', function ($q) {
                $q->where('partner_id', $this->partnerId)
                  ->whereBetween('date', [$this->dateFrom, $this->dateTo]);
            })
            ->with(['journalEntry'])
            ->get()
            ->sortBy(fn($line) => $line->journalEntry->date);
    }

    public function map($line): array
    {
        if ($this->partnerTypeGroup === 'customer') {
            $this->runningBalance += $line->debit - $line->credit;
        } else {
            $this->runningBalance += $line->credit - $line->debit;
        }
        
        return [
            $line->journalEntry->date->format('Y-m-d'),
            $line->journalEntry->reference,
            $line->description,
            number_format($line->debit, 2),
            number_format($line->credit, 2),
            number_format($this->runningBalance, 2),
        ];
    }

    public function headings(): array
    {
        return [
            'Date',
            'Ref',
            'Description',
            'Debit',
            'Credit',
            'Running Balance',
        ];
    }
}
