<?php

namespace App\Http\Resources;

use App\Facades\Settings;
use App\Http\Resources\Traits\BuildsDealTitle;
use App\Traits\FormatAsCurrency;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Mtc\Checkout\Invoice;
use Mtc\MercuryDataModels\Customer;
use Mtc\MercuryDataModels\DealBuilder\Deal;
use Mtc\MercuryDataModels\DealBuilder\DealHistory;
use Mtc\MercuryDataModels\DealBuilder\DealMessage;
use Mtc\MercuryDataModels\DealBuilder\DealNote;
use Mtc\MercuryDataModels\DealBuilder\DealAddOn;
use Mtc\MercuryDataModels\DealBuilder\DealPartExchange;
use Mtc\MercuryDataModels\DealBuilder\Status;

class DealResource extends JsonResource
{
    use BuildsDealTitle;
    use FormatAsCurrency;

    public static $wrap = '';

    /**
     * Transform the resource into an array.
     *
     * @return array<string, mixed>
     */
    public function toArray(Request $request): array
    {
        $this->resource->load([
            'status',
            'customer',
            'partExchange',
            'addOns.addOn.mediaUses.media',
            'finance' => fn($query) => $query->where('selected', 1),
            'invoices.payments',
            'notes.author',
            'notes.attachments',
            'messages.user',
            'messages.customer',
            'messages.attachments',
            'history.author',
            'history.customer',
            'history.status',
            'deliveryLocation',
        ]);

        $this->resource->partExchange
            ->each(fn(DealPartExchange $vehicle) => $vehicle->preview_image = $this->partExPreviewImage($vehicle));
        $resource = $this->resource->toArray();
        $resource['assignee'] = $this->resource->assignee_id > 0
            ? $this->resource->user->name ?? __('labels.unknown_user')
            : __('labels.unassigned');
        $resource['time_since_submitted'] = $this->resource->time_since_submitted;
        $resource['time_since_updated'] = $this->resource->time_since_updated;
        $resource['status_name'] = $this->resource->status_id > 0
            ? $this->resource->status?->name ?? __('labels.unknown_status')
            : __('labels.draft');
        $resource['vehicle'] = new VehicleDetailsResource($this->resource->vehicle);
        $resource['history'] = $this->resource->history->map(fn(DealHistory $history) => $this->mapHistory($history));
        $resource['notes'] = $this->resource->notes->map(fn(DealNote $note) => $this->mapNote($note));
        $resource['messages'] = $this->resource->messages->map(fn(DealMessage $message) => $this->mapMessage($message));
        $resource['invoices'] = $this->resource->invoices->map(fn(Invoice $invoice) => $this->mapInvoice($invoice));
        $resource['add_ons'] = $this->resource->addOns->map(fn(DealAddOn $addOn) => $this->mapAddOn($addOn));
        $resource['customer_info'] = $this->mapCustomerInfo($this->resource);
        $resource['title'] = $this->buildDealTitle($this->resource);
        $resource['created_at'] = $this->resource->created_at?->format('d/m/Y H:i');
        $resource['total_amount'] = $this->asCurrency($this->resource->total_amount, null, 2);
        $resource['deposit_amount'] = $this->asCurrency($this->resource->deposit_amount, null, 2);
        $resource['payable_amount'] = $this->asCurrency($this->resource->payable_amount, null, 2);
        $resource['fulfilment'] = $this->mapFulfilment($this->resource);

        return [
            'deal' => $resource,
            'statuses' => Status::query()->select(['id', 'name'])->get(),
        ];
    }

    protected function mapFulfilment(Deal $deal): ?array
    {
        if (!$deal->fulfilment_type) {
            return null;
        }

        $typeLabels = [
            'pickup' => 'Collection from dealership',
            'delivery_location' => 'Delivery to location',
            'home_delivery' => 'Home delivery',
        ];
        $type = $deal->fulfilment_type->value;
        $address = $deal->delivery_address;

        return [
            'type' => $type,
            'type_label' => $typeLabels[$type] ?? ucfirst(str_replace('_', ' ', $type)),
            'date' => $deal->fulfilment_date?->format('d/m/Y'),
            'time_window' => $deal->fulfilment_time_window,
            'fee' => $deal->fulfilment_fee !== null
                ? $this->asCurrency($deal->fulfilment_fee, null, 2)
                : null,
            'location' => $deal->deliveryLocation ? [
                'id' => $deal->deliveryLocation->id,
                'name' => $deal->deliveryLocation->name,
                'address' => collect([
                    $deal->deliveryLocation->address1,
                    $deal->deliveryLocation->address2,
                    $deal->deliveryLocation->city,
                    $deal->deliveryLocation->county,
                    $deal->deliveryLocation->postcode,
                ])->filter()->implode(', '),
            ] : null,
            'address' => is_array($address) ? collect([
                $address['line1'] ?? null,
                $address['line2'] ?? null,
                $address['city'] ?? null,
                $address['postcode'] ?? null,
            ])->filter()->implode(', ') : null,
        ];
    }

    protected function mapHistory(DealHistory $history): array
    {
        // Determine who made the change
        if ($history->user_id) {
            $author = $history->author?->name ?? __('labels.unknown_user');
            $authorType = 'team';
        } elseif ($history->customer_id) {
            $author = $history->customer?->first_name
                ? trim($history->customer->first_name . ' ' . $history->customer->last_name)
                : __('labels.customer');
            $authorType = 'customer';
        } else {
            $author = 'System';
            $authorType = 'system';
        }

        return [
            'id' => $history->id,
            'author' => $author,
            'author_type' => $authorType,
            'message' => __('deal_builder.status_changed_message', [
                'new_status' => $history->status?->name ?? __('labels.unknown_status'),
            ]),
            'timestamp' => $history->created_at->format('d/m/Y H:i'),
        ];
    }

    protected function mapNote(DealNote $note): array
    {
        return  [
            'id' => $note->id,
            'author' => $note->author?->name ?? __('labels.unknown_user'),
            'message' => $note->message,
            'timestamp' => $note->created_at->format('d/m/Y H:i'),
            'attachments' => $note->attachments->map(fn($attachment) => $this->mapAttachment($attachment)),
        ];
    }

    protected function mapMessage(DealMessage $message): array
    {
        return  [
            'id' => $message->id,
            'is_customer' => !empty($message->customer_id),
            'author_type' => $message->customer_id ? __('labels.customer') : __('labels.team'),
            'author' => $message->customer_id
                ? $message->customer?->first_name . ' ' . $message->customer?->last_name
                : $message->user?->name ?? __('labels.unknown_user'),
            'message' => $message->message,
            'timestamp' => $message->created_at->format('d/m/Y H:i'),
            'attachments' => $message->attachments->map(fn($attachment) => $this->mapAttachment($attachment)),
        ];
    }

    protected function mapAttachment($attachment): array
    {
        return [
            'id' => $attachment->id,
            'filename' => $attachment->original_filename,
            'url' => $attachment->url,
            'mime_type' => $attachment->mime_type,
            'size' => $attachment->size,
            'size_formatted' => $this->formatFileSize($attachment->size),
        ];
    }

    protected function formatFileSize(?int $bytes): string
    {
        if (!$bytes) {
            return '0 B';
        }

        $units = ['B', 'KB', 'MB', 'GB'];
        $i = 0;

        while ($bytes >= 1024 && $i < count($units) - 1) {
            $bytes /= 1024;
            $i++;
        }

        return round($bytes, 1) . ' ' . $units[$i];
    }

    public function partExPreviewImage(DealPartExchange $vehicle): string
    {
        return 'https://cdn.imagin.studio/getImage?' . http_build_query([
                'customer' => Settings::get('imagin-placeholders-client-key') ?: config('services.imagin-studio.key'),
                'make' => $vehicle->make,
                'modelFamily' => $vehicle->model,
                'paintdescription' => $vehicle->colour,
                'modelYear' => $vehicle->manufacture_year,
                'aspectRatio' => '16:9',
                'zoomLevel' => 50,
            ]);
    }

    protected function mapInvoice(Invoice $invoice): array
    {
        $payments = $invoice->payments
            ->filter(fn($payment) => $payment->confirmed_at !== null)
            ->map(fn($payment) => [
                'id' => $payment->id,
                'amount' => $this->asCurrency($payment->amount, null, 2),
                'amount_raw' => $payment->amount,
                'reference' => $payment->reference,
                'provider' => ucfirst($payment->provider),
                'date' => $payment->confirmed_at?->format('d/m/Y H:i'),
            ]);

        return [
            'id' => $invoice->id,
            'reference' => $invoice->reference,
            'amount' => $this->asCurrency($invoice->amount, null, 2),
            'amount_raw' => $invoice->amount,
            'outstanding_amount' => $this->asCurrency($invoice->outstanding_amount, null, 2),
            'outstanding_amount_raw' => $invoice->outstanding_amount,
            'status' => $invoice->status,
            'status_name' => $invoice->status_name,
            'is_paid' => $invoice->isPaid(),
            'currency' => $invoice->currency,
            'created_at' => $invoice->created_at?->format('d/m/Y H:i'),
            'due_at' => $invoice->due_at?->format('d/m/Y'),
            'payments' => $payments,
        ];
    }

    protected function mapAddOn(DealAddOn $dealAddOn): array
    {
        $addOn = $dealAddOn->addOn;
        $image = $addOn?->mediaUses?->sortByDesc('primary')->first();
        $imageSrc = $image
            ? ($image->getUrl('square-tile') ?? $image->media?->getOriginalUrlAttribute())
            : null;

        return [
            'id' => $dealAddOn->id,
            'name' => $addOn?->name ?? 'Unknown add-on',
            'description' => $addOn?->description,
            'image' => $imageSrc ? [
                'src' => $imageSrc,
                'alt' => $image->alt_text,
            ] : null,
            'price' => $this->asCurrency($dealAddOn->price, null, 2),
            'price_raw' => $dealAddOn->price,
            'payment_term' => $dealAddOn->payment_term,
            'payment_term_label' => $dealAddOn->payment_term === 'monthly' ? 'Rolled into monthly' : 'One-time payment',
        ];
    }

    protected function mapCustomerInfo($deal): array
    {
        $customer = $deal->customer;

        // Contact details from deal (primary) or customer (fallback)
        $contactInfo = [
            'first_name' => $deal->first_name ?? $customer?->first_name,
            'last_name' => $deal->last_name ?? $customer?->last_name,
            'email' => $deal->email ?? $customer?->email,
            'phone' => $deal->contact_number ?? $customer?->phone_number,
        ];

        // If no customer record exists, return just the contact info
        if (!$customer) {
            return [
                'contact' => $contactInfo,
                'has_account' => false,
                'customer_id' => null,
                'account_created' => null,
                'account_age' => null,
                'stats' => null,
            ];
        }

        // Calculate account age
        $accountAge = null;
        if ($customer->created_at) {
            $diff = $customer->created_at->diff(now());
            $parts = [];
            if ($diff->y > 0) {
                $parts[] = $diff->y . ' ' . ($diff->y === 1 ? 'year' : 'years');
            }
            if ($diff->m > 0) {
                $parts[] = $diff->m . ' ' . ($diff->m === 1 ? 'month' : 'months');
            }
            if (empty($parts) && $diff->d > 0) {
                $parts[] = $diff->d . ' ' . ($diff->d === 1 ? 'day' : 'days');
            }
            $accountAge = implode(', ', $parts) ?: 'Today';
        }

        // Get customer statistics
        $dealsCount = Deal::where('customer_id', $customer->id)->where('status_id', '>', 0)->count();
        $enquiriesCount = $customer->enquiries()->count();
        $bookingsCount = $customer->bookings()->count();
        $reservationsCount = $customer->reservations()->count();

        return [
            'contact' => $contactInfo,
            'has_account' => true,
            'customer_id' => $customer->id,
            'account_created' => $customer->created_at?->format('d/m/Y'),
            'account_age' => $accountAge,
            'marketing' => [
                'email' => $customer->marketing_email,
                'phone' => $customer->marketing_phone,
                'sms' => $customer->marketing_sms,
            ],
            'stats' => [
                'deals' => $dealsCount,
                'enquiries' => $enquiriesCount,
                'bookings' => $bookingsCount,
                'reservations' => $reservationsCount,
            ],
        ];
    }
}
