<?php

namespace Aura\Export\Http\Livewire;

use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Database\Eloquent\Collection;
use LivewireUI\Modal\ModalComponent;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Facades\Excel;

class ExportSelectedModal extends ModalComponent
{
    public $action;

    public $exportFields = [];

    public $exportFormat = 'csv';

    public $fields;

    public $filepath;

    public $model;

    public $selected;

    public function export()
    {
        // Retrieve the records to export
        $records = $this->model::findMany($this->selected);

        // Select only the fields to export
        $records = $records->map(function ($record) {
            $data = array_merge($record->toArray(), $record['fields']->toArray());

            return collect($data)->only($this->exportFields)->toArray();
        });

        // Export the records
        switch ($this->exportFormat) {
            case 'csv':
                // Handle CSV export
                $this->exportCsv($records);
                break;
            case 'excel':
                // Handle Excel export
                $this->exportExcel($records);
                break;
            case 'pdf':
                // Handle PDF export
                $this->exportPdf($records);
                break;
            case 'xml':
                // Handle XML export
                $this->exportXml($records);
                break;
        }
    }

    public function exportCsv($posts)
    {
        $posts = $posts->toArray();

        $filename = 'posts_'.date('YmdHis').'.csv';
        $filepath = storage_path('exports/'.$filename);

        if (! file_exists(dirname($filepath))) {
            mkdir(dirname($filepath), 0777, true);
        }

        $handle = fopen($filepath, 'w');

        $header = []; // Declare $header here

        foreach ($posts as $post) {
            // Only fetch data fields that are in the $this->exportFields
            // merge post and post['fields']
            // $post = array_merge($post, $post['fields']);

            $data = array_intersect_key($post, array_flip($this->exportFields));

            if (empty($header)) {
                $header = array_keys($data);
                fputcsv($handle, $header);
            }
            $dataValues = array_values($data);
            fputcsv($handle, $dataValues);
        }

        fclose($handle);

        $this->filepath = $filepath;
    }

    public function exportExcel($posts)
    {
        $filename = 'posts_'.date('YmdHis').'.xlsx';
        $filepath = 'exports/'.$filename;

        // Define an exportable collection with headings
        $exportable = new class($posts, $this->exportFields) implements FromCollection, WithHeadings
        {
            private $posts;

            private $fields;

            public function __construct($posts, $fields)
            {
                $this->resources = $posts;
                $this->fields = $fields;
            }

            // Define the collection of records to export
            public function collection()
            {
                return $this->resources->map(function ($post) {
                    // Only fetch data fields that are in the $this->exportFields
                    return collect($post)->only($this->fields)->values();
                });
            }

            // Define the headings based on export fields
            public function headings(): array
            {
                return $this->fields;
            }
        };

        // Store the Excel file and check if it was stored successfully
        $stored = Excel::store($exportable, $filepath);

        if ($stored) {
            $this->filepath = $filepath;

            return 'File stored successfully at '.$filepath;
        } else {
            return 'Failed to store file';
        }

    }

    public function exportPdf($posts)
    {
        $filename = 'posts_'.date('YmdHis').'.pdf';
        $filepath = storage_path('exports/'.$filename);

        $pdf = Pdf::loadView('export::pdf.export', ['posts' => $posts]);

        $pdf->save($filepath);

        return $pdf->download($filepath);
    }

    public function exportXml($posts)
    {
        $xml = new \SimpleXMLElement('<root/>');

        foreach ($posts as $post) {
            $postNode = $xml->addChild('resource');
            foreach ($post as $key => $value) {
                $postNode->addChild($key, $value);
            }
        }

        $filename = 'posts_'.date('YmdHis').'.xml';
        $filepath = storage_path('exports/'.$filename);

        $xml->asXML($filepath);

        return 'XML stored successfully at '.$filepath;
    }

    public static function modalMaxWidth(): string
    {
        return '7xl';
    }

    public function mount($selected)
    {
        // Set exportFields to the fields of the model of a selected Item
        // get first item from selected array
        $this->model = app($this->model);
        $this->exportFields = array_keys($this->model->getColumns());
        $this->fields = array_keys($this->model->getColumns());

    }

    public function render()
    {
        return view('export::livewire.export-selected-modal');
    }
}
