<?php

namespace App\Http\Controllers;

use App\Models\Action;
use App\Models\Client;
use App\Models\Decision;
use App\Models\Import;
use App\Models\ImportTemplate;
use App\Models\ImportTemplateMapping;
use App\Models\Segment;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Inertia\Inertia;

class ImportTemplateController extends Controller
{
    public function index()
    {
        $templates = ImportTemplate::query()
            ->with(['client:id,uuid,person_id', 'client.person:id,full_name'])
            ->orderBy('name')
            ->get();

        // Preload options for import mapping
        $clients = Client::query()
            ->join('person', 'person.id', '=', 'clients.person_id')
            ->orderBy('person.full_name')
            ->get(['clients.uuid', DB::raw('person.full_name as name')]);

        $segments = Segment::query()->orderBy('name')->get(['id', 'name']);
        $decisions = Decision::query()->orderBy('name')->get(['id', 'name']);
        $actions = Action::query()->orderBy('name')->get(['id', 'name']);

        return Inertia::render('Imports/Templates/Index', [
            'templates' => $templates->map(fn ($t) => [
                'uuid' => $t->uuid,
                'name' => $t->name,
                'description' => $t->description,
                'source_type' => $t->source_type,
                'is_active' => $t->is_active,
                'client' => $t->client ? [
                    'uuid' => $t->client->uuid,
                    'name' => $t->client->person?->full_name,
                ] : null,
            ]),
            'clients' => $clients,
            'segments' => $segments,
            'decisions' => $decisions,
            'actions' => $actions,
        ]);
    }

    // Show the template creation page
    public function create()
    {
        // Preload clients for optional association (global when null)
        $clients = Client::query()
            ->join('person', 'person.id', '=', 'clients.person_id')
            ->orderBy('person.full_name')
            ->get([
                'clients.id', // kept for compatibility, UI will use uuid
                'clients.uuid',
                DB::raw('person.full_name as name'),
            ]);

        $segments = Segment::query()->orderBy('name')->get(['id', 'name']);
        $decisions = Decision::query()->orderBy('name')->get(['id', 'name']);
        $actions = Action::with(['decisions:id,name'])
            ->orderBy('name')
            ->get(['id', 'name'])
            ->map(fn ($a) => [
                'id' => $a->id,
                'name' => $a->name,
                'decisions' => $a->decisions->map(fn ($d) => ['id' => $d->id, 'name' => $d->name])->values(),
            ]);

        return Inertia::render('Imports/Templates/Create', [
            'clients' => $clients,
            'segments' => $segments,
            'decisions' => $decisions,
            'actions' => $actions,
        ]);
    }

    public function store(Request $request)
    {
        // Normalize payload to be resilient to UI variations
        $raw = $request->all();
        // Allow passing default segment/decision either inside meta or as top-level
        if (isset($raw['segment_id']) && ! isset($raw['meta']['segment_id'])) {
            $raw['meta']['segment_id'] = $raw['segment_id'];
        }
        if (isset($raw['decision_id']) && ! isset($raw['meta']['decision_id'])) {
            $raw['meta']['decision_id'] = $raw['decision_id'];
        }
        // Resolve client by uuid if provided, or cast string numeric to int
        if (! empty($raw['client_uuid'] ?? null)) {
            $raw['client_id'] = Client::where('uuid', $raw['client_uuid'])->value('id');
        } elseif (isset($raw['client_id']) && is_string($raw['client_id']) && ctype_digit($raw['client_id'])) {
            $raw['client_id'] = (int) $raw['client_id'];
        }
        // Normalize entities to array of strings
        if (isset($raw['entities']) && is_array($raw['entities'])) {
            $raw['entities'] = array_values(array_filter(array_map(function ($e) {
                if (is_string($e)) {
                    return $e;
                }
                if (is_array($e) && array_key_exists('value', $e)) {
                    return (string) $e['value'];
                }

                return null;
            }, $raw['entities'])));
        }

        $data = validator($raw, [
            'name' => 'required|string|max:100',
            'description' => 'nullable|string|max:255',
            'source_type' => 'required|string|in:csv,xml,xls,xlsx,json',
            'default_record_type' => 'nullable|string|max:50',
            'sample_headers' => 'nullable|array',
            'client_id' => 'nullable|integer|exists:clients,id',
            'is_active' => 'boolean',
            'reactivate' => 'boolean',
            'entities' => 'nullable|array',
            'entities.*' => 'string|in:person,person_addresses,person_phones,emails,accounts,contracts,client_cases,case_objects,payments,activities',
            'mappings' => 'array',
            'mappings.*.source_column' => 'required|string',
            'mappings.*.entity' => 'nullable|string|in:person,person_addresses,person_phones,emails,accounts,contracts,client_cases,case_objects,payments,activities',
            'mappings.*.target_field' => 'nullable|string',
            'mappings.*.transform' => 'nullable|string|max:50',
            'mappings.*.apply_mode' => 'nullable|string|in:insert,update,both,keyref',
            'mappings.*.options' => 'nullable|array',
            'mappings.*.position' => 'nullable|integer',
            'meta' => 'nullable|array',
            'meta.segment_id' => 'nullable|integer|exists:segments,id',
            'meta.decision_id' => 'nullable|integer|exists:decisions,id',
            'meta.action_id' => 'nullable|integer|exists:actions,id',
            'meta.activity_action_id' => 'nullable|integer|exists:actions,id',
            'meta.activity_decision_id' => 'nullable|integer|exists:decisions,id',
            'meta.activity_created_at' => 'nullable|date',
            'meta.payments_import' => 'nullable|boolean',
            'meta.history_import' => 'nullable|boolean',
            'meta.contract_key_mode' => 'nullable|string|in:reference',
        ])->validate();

        // Ensure decision belongs to action if both provided in meta
        $meta = $data['meta'] ?? [];
        if (! empty($meta['action_id']) && ! empty($meta['decision_id'])) {
            $belongs = \DB::table('action_decision')
                ->where('action_id', $meta['action_id'])
                ->where('decision_id', $meta['decision_id'])
                ->exists();
            if (! $belongs) {
                return back()->withErrors(['meta.decision_id' => 'Selected decision is not associated with the chosen action.'])->withInput();
            }
        }
        $template = null;
        DB::transaction(function () use (&$template, $request, $data) {
            $paymentsImport = (bool) (data_get($data, 'meta.payments_import') ?? false);
            $historyImport = (bool) (data_get($data, 'meta.history_import') ?? false);
            $entities = $data['entities'] ?? [];
            if ($historyImport) {
                $paymentsImport = false; // history import cannot be combined with payments mode
                $allowedHistoryEntities = ['person', 'person_addresses', 'person_phones', 'contracts', 'activities', 'client_cases'];
                $entities = array_values(array_intersect($entities, $allowedHistoryEntities));
                // If contracts are present, ensure accounts are included implicitly for reference consistency
                if (in_array('contracts', $entities, true) && ! in_array('accounts', $entities, true)) {
                    $entities[] = 'accounts';
                }
                // Reject mappings that target disallowed entities for history import
                $disallowedMappings = collect($data['mappings'] ?? [])->filter(function ($m) use ($allowedHistoryEntities) {
                    if (empty($m['entity'])) {
                        return false;
                    }

                    return ! in_array($m['entity'], $allowedHistoryEntities, true);
                });
                if ($disallowedMappings->isNotEmpty()) {
                    abort(422, 'History import only allows entities: person, person_addresses, person_phones, contracts, activities, client_cases. Remove other mapping entities.');
                }
            }
            if ($paymentsImport) {
                $entities = ['contracts', 'accounts', 'payments'];
            }
            $template = ImportTemplate::create([
                'uuid' => (string) Str::uuid(),
                'name' => $data['name'],
                'description' => $data['description'] ?? null,
                'source_type' => $data['source_type'],
                'default_record_type' => $data['default_record_type'] ?? null,
                'sample_headers' => $data['sample_headers'] ?? null,
                'user_id' => $request->user()?->id,
                'client_id' => $data['client_id'] ?? null,
                'is_active' => $data['is_active'] ?? true,
                'reactivate' => $data['reactivate'] ?? false,
                'meta' => array_filter([
                    'entities' => $entities,
                    'segment_id' => data_get($data, 'meta.segment_id'),
                    'decision_id' => data_get($data, 'meta.decision_id'),
                    'action_id' => data_get($data, 'meta.action_id'),
                    'activity_action_id' => data_get($data, 'meta.activity_action_id'),
                    'activity_decision_id' => data_get($data, 'meta.activity_decision_id'),
                    'activity_created_at' => data_get($data, 'meta.activity_created_at'),
                    'payments_import' => $paymentsImport ?: null,
                    'history_import' => $historyImport ?: null,
                    'contract_key_mode' => data_get($data, 'meta.contract_key_mode'),
                ], fn ($v) => ! is_null($v) && $v !== ''),
            ]);

            foreach (($data['mappings'] ?? []) as $m) {
                ImportTemplateMapping::create([
                    'import_template_id' => $template->id,
                    'entity' => $m['entity'] ?? null,
                    'source_column' => $m['source_column'],
                    'target_field' => $m['target_field'] ?? null,
                    'transform' => $m['transform'] ?? null,
                    'apply_mode' => $m['apply_mode'] ?? 'both',
                    'options' => $m['options'] ?? null,
                    'position' => $m['position'] ?? null,
                ]);
            }
        });

        // Redirect to edit page for the newly created template
        return redirect()
            ->route('importTemplates.edit', ['template' => $template->uuid])
            ->with('success', 'Template created successfully.');
    }

    // Edit template UI (by uuid)
    public function edit(ImportTemplate $template)
    {
        // Eager-load mappings
        $template->load(['mappings']);

        // Preload clients list (uuid + name) for possible reassignment
        $clients = Client::query()
            ->join('person', 'person.id', '=', 'clients.person_id')
            ->orderBy('person.full_name')
            ->get([
                'clients.uuid',
                DB::raw('person.full_name as name'),
            ]);

        $segments = Segment::query()->orderBy('name')->get(['id', 'name']);
        $decisions = Decision::query()->orderBy('name')->get(['id', 'name']);
        $actions = Action::with(['decisions:id,name'])
            ->orderBy('name')
            ->get(['id', 'name'])
            ->map(fn ($a) => [
                'id' => $a->id,
                'name' => $a->name,
                'decisions' => $a->decisions->map(fn ($d) => ['id' => $d->id, 'name' => $d->name])->values(),
            ]);

        return Inertia::render('Imports/Templates/Edit', [
            'template' => [
                'uuid' => $template->uuid,
                'name' => $template->name,
                'description' => $template->description,
                'source_type' => $template->source_type,
                'default_record_type' => $template->default_record_type,
                'is_active' => $template->is_active,
                'reactivate' => $template->reactivate,
                'client_uuid' => $template->client?->uuid,
                'sample_headers' => $template->sample_headers,
                'meta' => $template->meta,
                'mappings' => $template->mappings()->orderBy('position')->get(['id', 'entity', 'source_column', 'target_field', 'transform', 'apply_mode', 'options', 'position']),
            ],
            'clients' => $clients,
            'segments' => $segments,
            'decisions' => $decisions,
            'actions' => $actions,
        ]);
    }

    // Add a new mapping to a template (by uuid)
    public function addMapping(Request $request, ImportTemplate $template)
    {
        // Normalize empty transform to null
        $raw = $request->all();
        if (array_key_exists('transform', $raw) && $raw['transform'] === '') {
            $raw['transform'] = null;
        }
        $data = validator($raw, [
            'source_column' => 'required|string',
            'entity' => 'nullable|string|in:person,person_addresses,person_phones,emails,accounts,contracts,client_cases,case_objects,payments,activities',
            'target_field' => 'nullable|string',
            'transform' => 'nullable|string|in:trim,upper,lower',
            'apply_mode' => 'nullable|string|in:insert,update,both,keyref',
            'options' => 'nullable|array',
            'position' => 'nullable|integer',
        ])->validate();

        // Avoid duplicates by source_column within the same template: update if exists
        $existing = ImportTemplateMapping::where('import_template_id', $template->id)
            ->where('source_column', $data['source_column'])
            ->first();

        if ($existing) {
            $existing->update([
                'target_field' => $data['target_field'] ?? $existing->target_field,
                'entity' => $data['entity'] ?? $existing->entity,
                'transform' => $data['transform'] ?? $existing->transform,
                'apply_mode' => $data['apply_mode'] ?? $existing->apply_mode ?? 'both',
                'options' => $data['options'] ?? $existing->options,
                'position' => $data['position'] ?? $existing->position,
            ]);

            return redirect()->route('importTemplates.edit', ['template' => $template->uuid])
                ->with('info', 'Mapping already existed. Updated existing mapping.');
        } else {
            $position = $data['position'] ?? (int) (($template->mappings()->max('position') ?? 0) + 1);
            ImportTemplateMapping::create([
                'import_template_id' => $template->id,
                'entity' => $data['entity'] ?? null,
                'source_column' => $data['source_column'],
                'target_field' => $data['target_field'] ?? null,
                'transform' => $data['transform'] ?? null,
                'apply_mode' => $data['apply_mode'] ?? 'both',
                'options' => $data['options'] ?? null,
                'position' => $position,
            ]);

            return redirect()->route('importTemplates.edit', ['template' => $template->uuid])
                ->with('success', 'Mapping added');
        }
    }

    // Update template basic fields
    public function update(Request $request, ImportTemplate $template)
    {
        $raw = $request->all();
        if (! empty($raw['client_uuid'] ?? null)) {
            $raw['client_id'] = Client::where('uuid', $raw['client_uuid'])->value('id');
        }
        // If template already has mappings, lock client assignment on backend as well
        // to prevent accidental clearing when client_uuid/client_id not sent.
        $hasMappings = $template->mappings()->exists();
        if ($hasMappings) {
            unset($raw['client_id'], $raw['client_uuid']);
        }
        $data = validator($raw, [
            'name' => 'required|string|max:100',
            'description' => 'nullable|string|max:255',
            'source_type' => 'required|string|in:csv,xml,xls,xlsx,json',
            'default_record_type' => 'nullable|string|max:50',
            'client_id' => 'nullable|integer|exists:clients,id',
            'is_active' => 'boolean',
            'reactivate' => 'boolean',
            'sample_headers' => 'nullable|array',
            'meta' => 'nullable|array',
            'meta.delimiter' => 'nullable|string|max:4',
            'meta.segment_id' => 'nullable|integer|exists:segments,id',
            'meta.decision_id' => 'nullable|integer|exists:decisions,id',
            'meta.action_id' => 'nullable|integer|exists:actions,id',
            'meta.activity_action_id' => 'nullable|integer|exists:actions,id',
            'meta.activity_decision_id' => 'nullable|integer|exists:decisions,id',
            'meta.activity_created_at' => 'nullable|date',
            'meta.payments_import' => 'nullable|boolean',
            'meta.history_import' => 'nullable|boolean',
            'meta.contract_key_mode' => 'nullable|string|in:reference',
        ])->validate();

        // Validate decision/action consistency on update as well
        $meta = $data['meta'] ?? [];
        if (! empty($meta['action_id']) && ! empty($meta['decision_id'])) {
            $belongs = \DB::table('action_decision')
                ->where('action_id', $meta['action_id'])
                ->where('decision_id', $meta['decision_id'])
                ->exists();
            if (! $belongs) {
                return back()->withErrors(['meta.decision_id' => 'Selected decision is not associated with the chosen action.'])->withInput();
            }
        }
        // Merge meta safely, preserving existing keys when not provided
        $newMeta = $template->meta ?? [];
        if (array_key_exists('meta', $data) && is_array($data['meta'])) {
            $newMeta = array_merge($newMeta, $data['meta']);
            // Drop empty delimiter to allow auto-detect
            if (array_key_exists('delimiter', $newMeta) && (! is_string($newMeta['delimiter']) || trim((string) $newMeta['delimiter']) === '')) {
                unset($newMeta['delimiter']);
            }
            foreach (['segment_id', 'decision_id', 'action_id', 'payments_import', 'contract_key_mode'] as $k) {
                if (array_key_exists($k, $newMeta) && ($newMeta[$k] === '' || is_null($newMeta[$k]))) {
                    unset($newMeta[$k]);
                }
            }
            foreach (['activity_action_id', 'activity_decision_id', 'activity_created_at'] as $k) {
                if (array_key_exists($k, $newMeta) && ($newMeta[$k] === '' || is_null($newMeta[$k]))) {
                    unset($newMeta[$k]);
                }
            }
        }

        // Finalize meta (ensure payments entities forced if enabled)
        $finalMeta = $newMeta;
        if (! empty($finalMeta['payments_import'])) {
            $finalMeta['entities'] = ['contracts', 'accounts', 'payments'];
        }
        if (! empty($finalMeta['history_import'])) {
            $finalMeta['payments_import'] = false;
            $allowedHistoryEntities = ['person', 'person_addresses', 'person_phones', 'contracts', 'activities', 'client_cases'];
            $finalMeta['entities'] = array_values(array_intersect($finalMeta['entities'] ?? [], $allowedHistoryEntities));
            if (in_array('contracts', $finalMeta['entities'] ?? [], true) && ! in_array('accounts', $finalMeta['entities'] ?? [], true)) {
                $finalMeta['entities'][] = 'accounts';
            }
        }

        if (in_array('activities', $finalMeta['entities'] ?? [], true)) {
            if (empty($finalMeta['activity_action_id']) || empty($finalMeta['activity_decision_id'])) {
                return back()->withErrors(['meta.activity_action_id' => 'Activities import requires selecting both a default action and decision.'])->withInput();
            }
        }

        $update = [
            'name' => $data['name'],
            'description' => $data['description'] ?? null,
            'source_type' => $data['source_type'],
            'default_record_type' => $data['default_record_type'] ?? null,
            // Only set client_id if explicitly present and not locked, otherwise keep existing
            'is_active' => $data['is_active'] ?? $template->is_active,
            'reactivate' => $data['reactivate'] ?? $template->reactivate,
            'sample_headers' => $data['sample_headers'] ?? $template->sample_headers,
            'meta' => $finalMeta,
        ];
        if (! $hasMappings && array_key_exists('client_id', $data)) {
            $update['client_id'] = $data['client_id'];
        }
        // When locked, do not touch client_id (prevents clearing to null)
        $template->update($update);

        return redirect()->route('importTemplates.edit', ['template' => $template->uuid])
            ->with('success', 'Template updated');
    }

    // Bulk add multiple mappings from a textarea input
    public function bulkAddMappings(Request $request, ImportTemplate $template)
    {
        // Accept either commas or newlines as separators
        $raw = $request->all();
        if (array_key_exists('transform', $raw) && $raw['transform'] === '') {
            $raw['transform'] = null;
        }
        $data = validator($raw, [
            'sources' => 'required|string', // comma and/or newline separated
            'entity' => 'nullable|string|in:person,person_addresses,person_phones,emails,accounts,contracts,client_cases,case_objects,payments,activities',
            'default_field' => 'nullable|string', // if provided, used as the field name for all entries
            'apply_mode' => 'nullable|string|in:insert,update,both,keyref',
            'transform' => 'nullable|string|in:trim,upper,lower',
            'options' => 'nullable|array',
            'group' => 'nullable|string|max:50', // convenience: will be wrapped into options.group
        ])->validate();

        // Accept commas, semicolons, and newlines; strip surrounding quotes/apostrophes and whitespace
        $list = preg_split('/[\r\n,;]+/', $data['sources']);
        $list = array_values(array_filter(array_map(function ($s) {
            $s = trim((string) $s);
            // remove surrounding double/single quotes if present
            $s = preg_replace('/^([\"\'])|([\"\'])$/u', '', $s) ?? $s;

            return $s;
        }, $list), fn ($s) => $s !== ''));

        if (empty($list)) {
            return redirect()->route('importTemplates.edit', ['template' => $template->uuid])
                ->with('warning', 'No valid source columns provided.');
        }

        $basePosition = (int) (($template->mappings()->max('position') ?? 0));
        $apply = $data['apply_mode'] ?? 'both';
        $transform = $data['transform'] ?? null;
        $entity = $data['entity'] ?? null;
        $defaultField = $data['default_field'] ?? null; // allows forcing a specific field for all

        // Build options payload once
        $opts = [];
        if (isset($data['options']) && is_array($data['options'])) {
            $opts = $data['options'];
        }
        if (! empty($data['group'])) {
            $opts['group'] = (string) $data['group'];
        }

        $created = 0;
        $updated = 0;
        DB::transaction(function () use ($template, $list, $apply, $transform, $entity, $defaultField, $basePosition, $opts, &$created, &$updated) {
            foreach ($list as $idx => $source) {
                $targetField = null;
                if ($defaultField) {
                    $targetField = $entity ? ($entity.'.'.$defaultField) : $defaultField;
                } elseif ($entity) {
                    $targetField = $entity.'.'.$source;
                }

                $existing = ImportTemplateMapping::where('import_template_id', $template->id)
                    ->where('source_column', $source)
                    ->first();

                if ($existing) {
                    $existing->update([
                        'target_field' => $targetField ?? $existing->target_field,
                        'entity' => $entity ?? $existing->entity,
                        'transform' => $transform ?? $existing->transform,
                        'apply_mode' => $apply ?? $existing->apply_mode ?? 'both',
                        'options' => empty($opts) ? $existing->options : $opts,
                        // keep existing position
                    ]);
                    $updated++;
                } else {
                    ImportTemplateMapping::create([
                        'import_template_id' => $template->id,
                        'entity' => $entity,
                        'source_column' => $source,
                        'target_field' => $targetField,
                        'transform' => $transform,
                        'apply_mode' => $apply,
                        'options' => empty($opts) ? null : $opts,
                        'position' => $basePosition + $idx + 1,
                    ]);
                    $created++;
                }
            }
        });

        $msg = [];
        if ($created) {
            $msg[] = "$created created";
        }
        if ($updated) {
            $msg[] = "$updated updated";
        }
        $text = 'Mappings processed';
        if (! empty($msg)) {
            $text .= ': '.implode(', ', $msg);
        }

        return redirect()->route('importTemplates.edit', ['template' => $template->uuid])
            ->with('success', $text);
    }

    // Update an existing mapping
    public function updateMapping(Request $request, ImportTemplate $template, ImportTemplateMapping $mapping)
    {
        if ($mapping->import_template_id !== $template->id) {
            abort(404);
        }
        $raw = $request->all();
        if (array_key_exists('transform', $raw) && $raw['transform'] === '') {
            $raw['transform'] = null;
        }
        $data = validator($raw, [
            'source_column' => 'required|string',
            'entity' => 'nullable|string|in:person,person_addresses,person_phones,emails,accounts,contracts,client_cases,case_objects,payments',
            'target_field' => 'nullable|string',
            'transform' => 'nullable|string|in:trim,upper,lower',
            'apply_mode' => 'nullable|string|in:insert,update,both,keyref',
            'options' => 'nullable|array',
            'position' => 'nullable|integer',
        ])->validate();

        $mapping->update([
            'source_column' => $data['source_column'],
            'entity' => $data['entity'] ?? null,
            'target_field' => $data['target_field'] ?? null,
            'transform' => $data['transform'] ?? null,
            'apply_mode' => $data['apply_mode'] ?? 'both',
            'options' => $data['options'] ?? null,
            'position' => $data['position'] ?? $mapping->position,
        ]);

        return back()->with('success', 'Mapping updated');
    }

    // Delete a mapping
    public function deleteMapping(ImportTemplate $template, ImportTemplateMapping $mapping)
    {
        if ($mapping->import_template_id !== $template->id) {
            abort(404);
        }
        $mapping->delete();

        return redirect()->route('importTemplates.edit', ['template' => $template->uuid])
            ->with('success', 'Mapping deleted');
    }

    // Reorder mappings in bulk
    public function reorderMappings(Request $request, ImportTemplate $template)
    {
        $data = $request->validate([
            'order' => 'required|array',
            'order.*' => 'integer',
        ]);
        $ids = $data['order'];
        // Ensure all ids belong to template
        $validIds = ImportTemplateMapping::where('import_template_id', $template->id)
            ->whereIn('id', $ids)->pluck('id')->all();
        if (count($validIds) !== count($ids)) {
            abort(422, 'Invalid mapping ids');
        }
        // Apply new positions
        foreach ($ids as $idx => $id) {
            ImportTemplateMapping::where('id', $id)->update(['position' => $idx]);
        }

        return redirect()->route('importTemplates.edit', ['template' => $template->uuid])
            ->with('success', 'Mappings reordered');
    }

    // Apply a template’s mappings to a specific import (copy into import_mappings)
    public function applyToImport(Request $request, ImportTemplate $template, Import $import)
    {
        // optional: clear previous mappings
        $clear = $request->boolean('clear', true);
        $copied = 0;
        DB::transaction(function () use ($clear, $template, $import, &$copied) {
            if ($clear) {
                \DB::table('import_mappings')->where('import_id', $import->id)->delete();
            }

            $rows = $template->mappings()->orderBy('position')->get();
            foreach ($rows as $row) {
                $options = $row->options;
                if (is_array($options) || $options instanceof \JsonSerializable || $options instanceof \stdClass) {
                    $options = json_encode($options);
                }
                \DB::table('import_mappings')->insert([
                    'import_id' => $import->id,
                    'entity' => $row->entity,
                    'source_column' => $row->source_column,
                    'target_field' => $row->target_field,
                    'transform' => $row->transform,
                    'apply_mode' => $row->apply_mode ?? 'both',
                    'options' => $options,
                    'position' => $row->position ?? null,
                    'created_at' => now(),
                    'updated_at' => now(),
                ]);
                $copied++;
            }

            // Merge default actions (segment/decision) into import meta for processing
            $importMeta = $import->meta ?? [];
            $tplMeta = $template->meta ?? [];
            $merged = array_merge($importMeta, array_filter([
                'segment_id' => $tplMeta['segment_id'] ?? null,
                'decision_id' => $tplMeta['decision_id'] ?? null,
                'action_id' => $tplMeta['action_id'] ?? null,
                'activity_action_id' => $tplMeta['activity_action_id'] ?? null,
                'activity_decision_id' => $tplMeta['activity_decision_id'] ?? null,
                'activity_created_at' => $tplMeta['activity_created_at'] ?? null,
                'template_name' => $template->name,
            ], fn ($v) => ! is_null($v) && $v !== ''));

            $import->update([
                'import_template_id' => $template->id,
                'reactivate' => $template->reactivate,
                'meta' => $merged,
            ]);
        });

        return response()->json(['ok' => true, 'copied' => $copied, 'cleared' => $clear]);
    }

    // Delete a template and cascade delete its mappings; detach from imports
    public function destroy(ImportTemplate $template)
    {
        DB::transaction(function () use ($template) {
            // Nullify references from imports to this template
            \DB::table('imports')->where('import_template_id', $template->id)->update(['import_template_id' => null]);
            // Delete mappings first (if FK cascade not set)
            \DB::table('import_template_mappings')->where('import_template_id', $template->id)->delete();
            // Delete the template
            $template->delete();
        });

        return redirect()->route('importTemplates.index')->with('success', 'Template deleted');
    }

    // Export template as JSON file
    public function export(ImportTemplate $template)
    {
        $template->load('mappings');

        $data = [
            'name' => $template->name,
            'description' => $template->description,
            'source_type' => $template->source_type,
            'default_record_type' => $template->default_record_type,
            'sample_headers' => $template->sample_headers,
            'is_active' => $template->is_active,
            'reactivate' => $template->reactivate,
            'meta' => $template->meta,
            'mappings' => $template->mappings->map(fn ($m) => [
                'source_column' => $m->source_column,
                'entity' => $m->entity,
                'target_field' => $m->target_field,
                'transform' => $m->transform,
                'apply_mode' => $m->apply_mode,
                'options' => $m->options,
                'position' => $m->position,
            ])->values()->toArray(),
        ];

        $filename = Str::slug($template->name).'-'.now()->format('Y-m-d').'.json';

        return response()->json($data)
            ->header('Content-Disposition', 'attachment; filename="'.$filename.'"');
    }

    // Import template from JSON file
    public function import(Request $request)
    {
        $data = $request->validate([
            'file' => 'required|file|mimes:json,txt|max:10240',
            'client_uuid' => 'nullable|string|exists:clients,uuid',
            'segment_id' => 'nullable|integer|exists:segments,id',
            'decision_id' => 'nullable|integer|exists:decisions,id',
            'action_id' => 'nullable|integer|exists:actions,id',
            'activity_action_id' => 'nullable|integer|exists:actions,id',
            'activity_decision_id' => 'nullable|integer|exists:decisions,id',
        ]);

        $file = $request->file('file');
        $contents = file_get_contents($file->getRealPath());
        $json = json_decode($contents, true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            return back()->withErrors(['file' => 'Invalid JSON file']);
        }

        // Validate structure
        $validator = validator($json, [
            'name' => 'required|string|max:100',
            'description' => 'nullable|string|max:255',
            'source_type' => 'required|string|in:csv,xml,xls,xlsx,json',
            'default_record_type' => 'nullable|string|max:50',
            'sample_headers' => 'nullable|array',
            'is_active' => 'nullable|boolean',
            'reactivate' => 'nullable|boolean',
            'meta' => 'nullable|array',
            'mappings' => 'nullable|array',
            'mappings.*.source_column' => 'required|string',
            'mappings.*.entity' => 'nullable|string',
            'mappings.*.target_field' => 'nullable|string',
            'mappings.*.transform' => 'nullable|string',
            'mappings.*.apply_mode' => 'nullable|string|in:insert,update,both,keyref',
            'mappings.*.options' => 'nullable|array',
            'mappings.*.position' => 'nullable|integer',
        ]);

        if ($validator->fails()) {
            return back()->withErrors($validator)->withInput();
        }

        $clientId = null;
        if (! empty($data['client_uuid'])) {
            $clientId = Client::where('uuid', $data['client_uuid'])->value('id');
        }

        // Replace IDs in meta if provided
        $meta = $json['meta'] ?? [];
        if (! empty($data['segment_id'])) {
            $meta['segment_id'] = (int) $data['segment_id'];
        }
        if (! empty($data['decision_id'])) {
            $meta['decision_id'] = (int) $data['decision_id'];
        }
        if (! empty($data['action_id'])) {
            $meta['action_id'] = (int) $data['action_id'];
        }
        if (! empty($data['activity_action_id'])) {
            $meta['activity_action_id'] = (int) $data['activity_action_id'];
        }
        if (! empty($data['activity_decision_id'])) {
            $meta['activity_decision_id'] = (int) $data['activity_decision_id'];
        }

        $template = null;
        DB::transaction(function () use (&$template, $request, $json, $clientId, $meta) {
            $template = ImportTemplate::create([
                'uuid' => (string) Str::uuid(),
                'name' => $json['name'],
                'description' => $json['description'] ?? null,
                'source_type' => $json['source_type'],
                'default_record_type' => $json['default_record_type'] ?? null,
                'sample_headers' => $json['sample_headers'] ?? null,
                'user_id' => $request->user()?->id,
                'client_id' => $clientId,
                'is_active' => $json['is_active'] ?? true,
                'reactivate' => $json['reactivate'] ?? false,
                'meta' => $meta,
            ]);

            foreach (($json['mappings'] ?? []) as $m) {
                ImportTemplateMapping::create([
                    'import_template_id' => $template->id,
                    'entity' => $m['entity'] ?? null,
                    'source_column' => $m['source_column'],
                    'target_field' => $m['target_field'] ?? null,
                    'transform' => $m['transform'] ?? null,
                    'apply_mode' => $m['apply_mode'] ?? 'both',
                    'options' => $m['options'] ?? null,
                    'position' => $m['position'] ?? null,
                ]);
            }
        });

        return redirect()
            ->route('importTemplates.edit', ['template' => $template->uuid])
            ->with('success', 'Template imported successfully');
    }
}
