<?php

namespace App\Filament\Pages;

use App\Exports\ReportArrayExport;
use App\Support\AccountingReportPdfBuilder;
use Filament\Pages\Page;
use App\Services\AccountingReportService;
use BezhanSalleh\FilamentShield\Traits\HasPageShield;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Schemas\Schema;
use Filament\Tables\Concerns\InteractsWithTable;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Table;
use Filament\Tables\Columns\TextColumn;
use Maatwebsite\Excel\Facades\Excel;

class TrialBalanceReport extends Page implements HasForms, HasTable
{
    use InteractsWithForms, InteractsWithTable, HasPageShield;

    protected static \BackedEnum|string|null $navigationIcon = 'heroicon-o-scale';

    protected string $view = 'filament.pages.trial-balance-report';

    protected static string|\UnitEnum|null $navigationGroup = 'التقارير المحاسبية';

    protected static ?int $navigationSort = 1;

    public ?string $startDate = null;
    public ?string $endDate = null;

    protected AccountingReportService $reportService;

    public function boot(AccountingReportService $reportService): void
    {
        $this->reportService = $reportService;
    }

    public function mount(): void
    {
        $this->startDate = now()->startOfYear()->toDateString();
        $this->endDate = now()->toDateString();

        $this->form->fill([
            'start_date' => $this->startDate,
            'end_date' => $this->endDate,
        ]);
    }

    public static function getNavigationLabel(): string
    {
        return __('filament/admin/custom.trial_balance.navigation');
    }

    public function getTitle(): string
    {
        return __('filament/admin/custom.trial_balance.title');
    }

    protected function getHeaderActions(): array
    {
        return [
            \Filament\Actions\Action::make('export_pdf')
                ->label(__('filament/admin/custom.actions.export_pdf'))
                ->icon('heroicon-o-document-arrow-down')
                ->action('exportPdf'),
            
            \Filament\Actions\Action::make('export_excel')
                ->label(__('filament/admin/custom.actions.export_excel'))
                ->icon('heroicon-o-table-cells')
                ->action('exportExcel'),
        ];
    }

    public function form(Schema $schema): Schema
    {
        return $schema
            ->components([
                DatePicker::make('start_date')
                    ->label(__('filament/admin/custom.trial_balance.from_date'))
                    ->default(now()->startOfYear())
                    ->required()
                    ->reactive()
                    ->afterStateUpdated(fn($state) => $this->startDate = $state),

                DatePicker::make('end_date')
                    ->label(__('filament/admin/custom.trial_balance.to_date'))
                    ->default(now())
                    ->required()
                    ->reactive()
                    ->afterStateUpdated(fn($state) => $this->endDate = $state),
            ])
            ->columns(2);
    }

    public function table(Table $table): Table
    {
        $data = $this->reportService->trialBalance($this->startDate, $this->endDate);

        return $table
            ->query(
                \Illuminate\Database\Eloquent\Builder::query()
                    ->from('chart_of_accounts')
                    ->whereRaw('1=0') // Empty query, we'll use $data directly
            )
            ->columns([
                TextColumn::make('account_code')
                    ->label(__('filament/admin/custom.trial_balance.account_code'))
                    ->sortable(),
                
                TextColumn::make('account_name')
                    ->label(__('filament/admin/custom.trial_balance.account_name'))
                    ->searchable()
                    ->sortable(),
                
                TextColumn::make('debit')
                    ->label(__('filament/admin/custom.trial_balance.debit'))
                    ->numeric(decimalPlaces: 2)
                    ->alignEnd()
                    ->summarize([
                        \Filament\Tables\Columns\Summarizers\Sum::make()
                            ->label(__('filament/admin/custom.trial_balance.total'))
                            ->numeric(decimalPlaces: 2),
                    ]),
                
                TextColumn::make('credit')
                    ->label(__('filament/admin/custom.trial_balance.credit'))
                    ->numeric(decimalPlaces: 2)
                    ->alignEnd()
                    ->summarize([
                        \Filament\Tables\Columns\Summarizers\Sum::make()
                            ->label(__('filament/admin/custom.trial_balance.total'))
                            ->numeric(decimalPlaces: 2),
                    ]),
                
                TextColumn::make('balance')
                    ->label(__('filament/admin/custom.trial_balance.balance'))
                    ->numeric(decimalPlaces: 2)
                    ->alignEnd()
                    ->formatStateUsing(fn($record) => 
                        $record['balance_type'] === 'debit' 
                            ? $record['balance'] . ' (' . __('filament/admin/custom.trial_balance.balance_debit') . ')'
                            : $record['balance'] . ' (' . __('filament/admin/custom.trial_balance.balance_credit') . ')'
                    ),
            ])
            ->paginated(false)
            ->defaultSort('account_code')
                    ->heading(__('filament/admin/custom.trial_balance.heading', ['start' => $this->startDate, 'end' => $this->endDate]));
    }

    public function getTableRecords(): \Illuminate\Support\Collection
    {
        return $this->reportService->trialBalance($this->startDate, $this->endDate);
    }

    public function exportPdf(): \Symfony\Component\HttpFoundation\StreamedResponse
    {
        $data = $this->reportService->trialBalance($this->startDate, $this->endDate);

        $rows = $data->map(fn(array $item) => [
            $item['account_code'] ?? '',
            $item['account_name'] ?? '',
            number_format((float) ($item['debit'] ?? 0), 2),
            number_format((float) ($item['credit'] ?? 0), 2),
            number_format((float) ($item['balance'] ?? 0), 2),
            ($item['balance_type'] ?? 'debit') === 'debit' ? __('filament/admin/custom.trial_balance.balance_debit') : __('filament/admin/custom.trial_balance.balance_credit'),
        ])->all();

        return AccountingReportPdfBuilder::download(
            title: __('filament/admin/custom.trial_balance.title'),
            subtitle: __('filament/admin/custom.trial_balance.subtitle', ['start' => $this->startDate, 'end' => $this->endDate]),
            headings: [__('filament/admin/custom.trial_balance.account_code'), __('filament/admin/custom.trial_balance.account_name'), __('filament/admin/custom.trial_balance.debit'), __('filament/admin/custom.trial_balance.credit'), __('filament/admin/custom.trial_balance.balance'), __('filament/admin/custom.trial_balance.balance')],
            rows: $rows,
            summary: [
                __('filament/admin/custom.trial_balance.summary_total_debit') => number_format($data->sum('debit'), 2),
                __('filament/admin/custom.trial_balance.summary_total_credit') => number_format($data->sum('credit'), 2),
            ],
            fileName: sprintf('trial-balance-%s-to-%s.pdf', $this->startDate, $this->endDate),
        );
    }

    public function exportExcel(): \Symfony\Component\HttpFoundation\StreamedResponse
    {
        $rows = $this->reportService->trialBalance($this->startDate, $this->endDate)
            ->map(fn(array $item) => [
                $item['account_code'] ?? '',
                $item['account_name'] ?? '',
                (float) ($item['debit'] ?? 0),
                (float) ($item['credit'] ?? 0),
                (float) ($item['balance'] ?? 0),
                $item['balance_type'] === 'debit' ? __('filament/admin/custom.trial_balance.balance_debit') : __('filament/admin/custom.trial_balance.balance_credit'),
            ])
            ->values()
            ->all();

        $filename = sprintf('trial-balance-%s-to-%s.xlsx', $this->startDate, $this->endDate);

        return response()->streamDownload(function () use ($rows) {
            echo Excel::raw(
                new ReportArrayExport(
                    headings: [__('filament/admin/custom.trial_balance.account_code'), __('filament/admin/custom.trial_balance.account_name'), __('filament/admin/custom.trial_balance.debit'), __('filament/admin/custom.trial_balance.credit'), __('filament/admin/custom.trial_balance.balance'), __('filament/admin/custom.trial_balance.balance')],
                    rows: $rows,
                ),
                \Maatwebsite\Excel\Excel::XLSX,
            );
        }, $filename);
    }

    protected function getViewData(): array
    {
        return [
            'data' => $this->reportService->trialBalance($this->startDate, $this->endDate),
            'startDate' => $this->startDate,
            'endDate' => $this->endDate,
        ];
    }
}
