<?php

namespace App\Http\Resources;

use App\Mail\NewReservationCustomerCopyNotification;
use App\Models\LeadExport;
use App\Traits\IconForType;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Str;
use Mtc\Crm\Http\Resources\FormViewResource as BaseFormViewResource;
use Mtc\Crm\Contracts\FormQuestionModel as FormQuestion;
use Mtc\Crm\Contracts\FormSectionModel as FormSection;
use Mtc\Crm\Models\EnquiryStatus;
use Mtc\Crm\Models\EnquiryType;
use Mtc\MercuryDataModels\Dealership;
use Mtc\MercuryDataModels\Enquiry;
use Mtc\MercuryDataModels\FormActivity;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MercuryDataModels\VehicleValuation;
use Mtc\VehicleReservations\Reservation;
use Ramsey\Uuid\Uuid;

class FormViewResource extends BaseFormViewResource
{
    use IconForType;

    public static $wrap = '';

    /**
     * Transform the resource into an array.
     *
     * @param Request $request
     * @return array
     */
    #[\Override]
    public function toArray($request)
    {
        $this->resource->available_actions = $this->getAvailableActions();
        $this->resource->load([
            'sections.questions',
            'dealerships',
        ]);

        $this->setActions();

        $resource = $this->resource->toArray();
        $resource['sections'] = $this->setSections();
        $resource['multistep'] = $resource['data']['multistep'] ?? false;
        $resource['partial_submissions'] = $resource['data']['partial_submissions'] ?? false;
        $resource['preview_content'] = $this->getTemplateContent();

        $resource['dealership_ids'] = $this->resource->dealerships->pluck('id')->values();

        return [
            'form' => $resource,
            'types' => EnquiryType::query()->orderBy('name')->get(),
            'statuses' => EnquiryStatus::query()->orderBy('name')->get(),
            'dealerships' => Dealership::query()->orderBy('name')->get(['id', 'name']),
            'activity' => $this->getActivityData(),
        ];
    }

    /**
     * Get activity data for the last 7 days
     */
    private function getActivityData(): array
    {
        $formId = $this->resource->id;
        $days = collect();

        for ($i = 0; $i < 7; $i++) {
            $days->push(Carbon::now()->subDays($i)->toDateString());
        }

        $activityRecords = FormActivity::query()
            ->where('form_id', $formId)
            ->whereIn('date', $days)
            ->get()
            ->keyBy(fn ($record) => $record->date->toDateString());

        return $days->map(function ($date) use ($activityRecords) {
            $record = $activityRecords->get($date);

            return [
                'date' => $date,
                'label' => Carbon::parse($date)->format('D j M'),
                'total' => $record?->total_submissions ?? 0,
                'success' => $record?->success_count ?? 0,
                'validation_error' => $record?->validation_error_count ?? 0,
                'failure' => $record?->failure_count ?? 0,
            ];
        })->toArray();
    }

    /**
     * Get list of available actions on forms.
     *
     * Static integrations come from config('crm.form_actions') (each a resolvable
     * class); UI-configurable lead exports are appended dynamically per active map.
     * The two sources are kept separate so a synthetic "lead-export:<id>" key is
     * never resolved through the container.
     *
     * @return Collection
     */
    #[\Override]
    protected function getAvailableActions()
    {
        return collect(config('crm.form_actions'))
            ->filter(fn ($class) => App::make($class)->enabled())
            ->map(fn ($class, $key) => [
                'name' => Str::title(str_replace('-', ' ', $key)),
                'enabled' => false,
                'question_fields' => collect(App::make($class)->formQuestionDataFields() ?? []),
                'fields' => collect(App::make($class)->formAdditionalDataFields() ?? [])
                    ->map(function ($field) {
                        $field['value'] = null;
                        return $field;
                    }),
            ])
            ->merge($this->getLeadExportActions());
    }

    /**
     * Available actions for active CRM lead exports, keyed by their provider key
     * (the action_name stored on the form). In mapped mode each export exposes a
     * per-question select whose choices are its configured destination fields.
     *
     * @return Collection
     */
    private function getLeadExportActions(): Collection
    {
        return LeadExport::query()
            ->where('active', true)
            ->get()
            ->mapWithKeys(fn (LeadExport $leadExport) => [
                $leadExport->providerKey() => [
                    'name' => $leadExport->name,
                    'enabled' => false,
                    'question_fields' => collect($this->leadExportQuestionFields($leadExport)),
                    'fields' => collect(),
                ],
            ]);
    }

    /**
     * Per-question mapping field for a lead export. Passthrough exports send answers
     * under their form field names, so they need no per-question select.
     *
     * @return array<string, mixed>
     */
    private function leadExportQuestionFields(LeadExport $leadExport): array
    {
        if (!$leadExport->isMapped()) {
            return [];
        }

        $choices = collect($leadExport->field_map ?? [])
            ->filter(fn ($field) => !empty($field['destination']))
            ->mapWithKeys(fn ($field) => [$field['destination'] => $field['label'] ?? $field['destination']])
            ->all();

        return [
            $leadExport->providerKey() => [
                'type' => 'select',
                'label' => 'Field mapped against ' . $leadExport->name,
                'choices' => $choices,
            ],
        ];
    }

    private function setActions()
    {
        $actions = $this->resource->available_actions->toArray();
        $enabledActions = $this->resource->actions()
            ->get()
            ->keyBy('action_name');

        foreach ($actions as $id => $availableAction) {
            $actions[$id]['trigger'] = $enabledActions[$id]['fields']['trigger'] ?? 'all';

            if (isset($enabledActions[$id])) {
                $actions[$id]['enabled'] = true;
                $actions[$id]['fields'] = collect($actions[$id]['fields'])
                    ->map(function ($field, $fieldName) use ($id, $enabledActions) {
                        $field['value'] = $enabledActions[$id]['fields'][$fieldName] ?? null;
                        return $field;
                    });
            }
        }

        $this->resource->action_data = $actions;
    }

    private function setSections()
    {
        return $this->resource
            ->sections
            ->map(fn (FormSection $section) => [
                'id' => $section->id,
                'name' => $section->name,
                'is_active' => $section->is_active,
                'settings' => $section->settings,
                'sections' => collect($section->segments ?? [])
                    ->map(fn ($segment) => [
                        'id' => Uuid::uuid4(),
                        'name' => $segment,
                        'questions' => $section->questions
                            ->where('segment', $segment)
                            ->map(fn (FormQuestion $question) => [
                                'id' => $question->id,
                                'name' => $question->name,
                                'cssId' => $question->data['cssId'] ?? null,
                                'cssClass' => $question->data['cssClass'] ?? null,
                                'fieldId' => $question->type,
                                'component' => $question->data['component'] ?? null,
                                'componentName' => $question->data['componentName'] ?? null,
                                'optionsMenuVisible' => false,
                                'meta' => $question->data['meta'] ?? null,
                                'type' => $question->type,
                                'is_active' => $question->is_active,
                                'validation' => is_array($question->validation)
                                    ? $question->validation
                                    : json_decode($question->validation, true),
                                'is_customers_email' => $question->is_customers_email,
                                'is_enquiry_subject' => $question->is_enquiry_subject,
                                'description' => $question->description,
                                'placeholder' => $question->placeholder,
                                'data' => $question->data ?? [],
                                'editable' => true,
                                'error' => $this->questionError($question),
                                'icon' => $this->getIcon($question->type),
                            ])->values(),
                    ])
            ]);
    }


    private function questionError(FormQuestion $question)
    {
        return match ($question->type) {
            'offer_id', 'page_id', 'vehicle_id' => ['This field is hidden, auto-filled by the value of viewed page'],
            default => [],
        };
    }

    private function getTemplateContent(): string
    {
        try {
            if ($this->resource?->type?->name === 'Reservation') {
                $reservation = Reservation::factory()->make();
                return (new NewReservationCustomerCopyNotification($reservation))->render();
            }

            $enquiry = Enquiry::query()
                ->where('form_id', $this->resource->id)->first();
            if (empty($enquiry)) {
                $enquiry = Enquiry::factory()->make([
                    'form_id' => $this->resource->id,
                ]);
                $valuation = VehicleValuation::factory()->make();
                $enquiry->valuation = $valuation;
            }

            if (empty($enquiry->reason)) {
                $vehicle = Vehicle::query()->first();
                $enquiry->reason = $vehicle;
            }

            $class = config('crm.enquiry_confirmation_mail');
            return (new $class($enquiry))->render();
        } catch (\InvalidArgumentException $e) {
            return 'Email template not found. Please check the enquiry type configuration.';
        }
    }
}
