<?php

namespace App\Http\Controllers;

use App\Models\Contact;
use Illuminate\Http\Request;

class ContactExportController extends Controller
{
    private const COLUMN_LABELS = [
        'id'             => 'ID',
        'email'          => 'Email',
        'prefix'         => 'Prefix',
        'first_name'     => 'First Name',
        'last_name'      => 'Last Name',
        'phone'          => 'Phone',
        'status'         => 'Status',
        'contact_type'   => 'Contact Type',
        'source'         => 'Source',
        'date_of_birth'  => 'Date of Birth',
        'address_line_1' => 'Address Line 1',
        'address_line_2' => 'Address Line 2',
        'city'           => 'City',
        'state'          => 'State',
        'postal_code'    => 'ZIP Code',
        'country'        => 'Country',
        'ip'             => 'IP Address',
        'lists'          => 'Lists',
        'tags'           => 'Tags',
        'created_at'     => 'Created At',
        'last_activity'  => 'Last Activity',
    ];

    public function __invoke(Request $request)
    {
        $columns = $request->input('columns', ['email', 'first_name', 'last_name', 'status']);
        $columns = array_intersect($columns, array_keys(self::COLUMN_LABELS));

        if (empty($columns)) {
            $columns = ['email', 'first_name', 'last_name', 'status'];
        }

        $needsRelations = in_array('lists', $columns) || in_array('tags', $columns);

        $query = Contact::query()
            ->when($needsRelations, fn($q) => $q->with(['lists:id,title', 'tags:id,title']))
            ->when($request->search,  fn($q, $s) => $q->where(fn($q) =>
                $q->where('email', 'like', "%{$s}%")
                  ->orWhere('first_name', 'like', "%{$s}%")
                  ->orWhere('last_name', 'like', "%{$s}%")
            ))
            ->when($request->list_id, fn($q, $id) => $q->whereHas('lists', fn($q) => $q->where('lists.id', $id)))
            ->when($request->tag_id,  fn($q, $id) => $q->whereHas('tags',  fn($q) => $q->where('tags.id',  $id)))
            ->when($request->status,  fn($q, $s)  => $q->where('status', $s));

        $filename = 'contacts_' . date('Y-m-d') . '.csv';

        return response()->streamDownload(function () use ($query, $columns) {
            $handle = fopen('php://output', 'w');

            // BOM for Excel UTF-8 compatibility
            fwrite($handle, "\xEF\xBB\xBF");

            // Header row
            $labels = array_map(fn($c) => self::COLUMN_LABELS[$c] ?? $c, $columns);
            fputcsv($handle, $labels);

            $query->orderBy('id')->chunk(500, function ($contacts) use ($handle, $columns) {
                foreach ($contacts as $contact) {
                    $row = [];
                    foreach ($columns as $col) {
                        $row[] = match($col) {
                            'lists'      => $contact->lists->pluck('title')->join(', '),
                            'tags'       => $contact->tags->pluck('title')->join(', '),
                            'created_at' => $contact->created_at?->format('Y-m-d H:i:s') ?? '',
                            'last_activity' => $contact->last_activity?->format('Y-m-d H:i:s') ?? '',
                            'date_of_birth' => $contact->date_of_birth?->format('Y-m-d') ?? '',
                            default      => $contact->{$col} ?? '',
                        };
                    }
                    fputcsv($handle, $row);
                }
            });

            fclose($handle);
        }, $filename, [
            'Content-Type'        => 'text/csv; charset=UTF-8',
            'Content-Disposition' => "attachment; filename=\"{$filename}\"",
        ]);
    }
}
