<?php

namespace App\Extensions\Installed\Importer\Services;

use App\Models\{Tickets, Responses, User, Departments, Announcements, Categories};
use App\Enums\{Status as TicketStatus, Priorities as TicketPriority, Organize as TicketOrganize};
use Illuminate\Support\Facades\{DB, Hash, Log, Validator};
use Illuminate\Support\Str;

/**
 * CSV Importer Service
 *
 * Handles importing from CSV files:
 * - Customers (users)
 * - Tickets
 * - Responses
 * - Announcements
 * - Departments
 *
 * Features:
 * - Column mapping
 * - Data validation
 * - Batch processing
 * - Error handling
 */
class CsvImporter
{
    protected string $filePath;
    protected string $importType; // 'customers', 'tickets', 'responses', 'announcements', 'departments'
    protected array $mapping = [];
    protected array $options = [];
    protected array $errors = [];
    protected int $imported = 0;
    protected int $skipped = 0;
    protected bool $dryRun = false;

    /**
     * Constructor
     *
     * @param string $filePath Path to the CSV file
     * @param string $importType Type of import ('customers', 'tickets', 'responses', 'announcements', 'departments')
     * @param array $mapping Column mapping (CSV column => Ticaga field)
     * @param array $options Import options
     */
    public function __construct(string $filePath, string $importType = 'tickets', array $mapping = [], array $options = [])
    {
        $this->filePath = $filePath;
        $this->importType = $importType;
        $this->mapping = $mapping;
        $this->options = array_merge([
            'delimiter' => ',',
            'enclosure' => '"',
            'escape' => '\\',
            'batch_size' => 100,
            'skip_header' => true,
            'default_password' => 'changeme123',
            'force_password_reset' => true,
            'update_existing' => false, // Update if exists (for customers/announcements)
            'dry_run' => false,
        ], $options);

        $this->dryRun = (bool) ($this->options['dry_run'] ?? false);
    }

    /**
     * Read CSV headers
     *
     * @return array
     */
    public function getHeaders(): array
    {
        if (!file_exists($this->filePath)) {
            throw new \Exception("File not found: {$this->filePath}");
        }

        $file = fopen($this->filePath, 'r');
        $headers = fgetcsv($file, 0, $this->options['delimiter'], $this->options['enclosure'], $this->options['escape']);
        fclose($file);

        return $headers ?: [];
    }

    /**
     * Preview data from CSV
     *
     * @param int $rows Number of rows to preview
     * @return array
     */
    public function preview(int $rows = 10): array
    {
        if (!file_exists($this->filePath)) {
            throw new \Exception("File not found: {$this->filePath}");
        }

        $data = [];
        $file = fopen($this->filePath, 'r');

        // Skip header if needed
        if ($this->options['skip_header']) {
            fgetcsv($file, 0, $this->options['delimiter'], $this->options['enclosure'], $this->options['escape']);
        }

        $count = 0;
        while (($row = fgetcsv($file, 0, $this->options['delimiter'], $this->options['enclosure'], $this->options['escape'])) !== false && $count < $rows) {
            $data[] = $row;
            $count++;
        }

        fclose($file);

        return $data;
    }

    /**
     * Import data from CSV
     *
     * @return array Results summary
     */
    public function import(): array
    {
        if (!file_exists($this->filePath)) {
            throw new \Exception("File not found: {$this->filePath}");
        }

        $file = fopen($this->filePath, 'r');

        // Get headers
        $headers = fgetcsv($file, 0, $this->options['delimiter'], $this->options['enclosure'], $this->options['escape']);

        if (!$headers) {
            throw new \Exception("Could not read CSV headers");
        }

        $this->errors = [];
        $this->imported = 0;
        $this->skipped = 0;

        $rowNumber = 1; // Start at 1 (header is row 0)

        while (($row = fgetcsv($file, 0, $this->options['delimiter'], $this->options['enclosure'], $this->options['escape'])) !== false) {
            $rowNumber++;

            try {
                // Route to appropriate import method based on type
                switch ($this->importType) {
                    case 'customers':
                        $this->importCustomerRow($headers, $row, $rowNumber);
                        break;
                    case 'tickets':
                        $this->importTicketRow($headers, $row, $rowNumber);
                        break;
                    case 'responses':
                        $this->importResponseRow($headers, $row, $rowNumber);
                        break;
                    case 'announcements':
                        $this->importAnnouncementRow($headers, $row, $rowNumber);
                        break;
                    case 'departments':
                        $this->importDepartmentRow($headers, $row, $rowNumber);
                        break;
                    default:
                        throw new \Exception("Invalid import type: {$this->importType}");
                }

                $this->imported++;
            } catch (\Exception $e) {
                $this->errors[] = [
                    'row' => $rowNumber,
                    'error' => $e->getMessage(),
                    'data' => $row,
                ];
                $this->skipped++;
                Log::warning("Importer: Row {$rowNumber} failed: {$e->getMessage()}");
            }
        }

        fclose($file);

        return [
            'type' => $this->importType,
            'imported' => $this->imported,
            'skipped' => $this->skipped,
            'errors' => $this->errors,
        ];
    }

    /**
     * Import a customer row
     *
     * @param array $headers
     * @param array $row
     * @param int $rowNumber
     * @return void
     */
    protected function importCustomerRow(array $headers, array $row, int $rowNumber): void
    {
        $data = array_combine($headers, $row);
        $customerData = $this->mapData($data);

        $forcePasswordReset = $this->options['force_password_reset'];
        if (array_key_exists('force_password_reset', $customerData)) {
            $forcePasswordReset = $this->interpretBoolean($customerData['force_password_reset']);
        }

        $temporaryPassword = trim((string)($customerData['password'] ?? ''));
        $passwordToUse = $temporaryPassword !== ''
            ? Hash::make($temporaryPassword)
            : Hash::make($this->options['default_password']);

        $accountManagerValue = $this->normalizeInteger($customerData['account_manager'] ?? 0);
        $billingIdValue = $this->normalizeInteger($customerData['billing_id'] ?? 0);

        // Validate required fields
        $validator = Validator::make($customerData, [
            'email' => 'required|email',
            'name' => 'required|string|max:255',
        ]);

        if ($validator->fails()) {
            throw new \Exception("Row {$rowNumber}: " . implode(', ', $validator->errors()->all()));
        }

        // Check if user exists
        $existingUser = User::where('email', $customerData['email'])->first();

        if ($existingUser) {
            if (!$this->options['update_existing']) {
                throw new \Exception("Customer already exists: {$customerData['email']}");
            }

            if (!$this->dryRun) {
                $updatePayload = [
                    'name' => $customerData['name'],
                    'force_password_reset' => $forcePasswordReset,
                ];

                if (array_key_exists('company', $customerData) && $customerData['company'] !== '') {
                    $updatePayload['company'] = $customerData['company'];
                }

                $updatePayload['billing_id'] = $billingIdValue;

                if (array_key_exists('billing_system', $customerData) && $customerData['billing_system'] !== '') {
                    $updatePayload['billing_system'] = $customerData['billing_system'];
                }

                $updatePayload['account_manager'] = $accountManagerValue;

                if ($temporaryPassword !== '') {
                    $updatePayload['password'] = $passwordToUse;
                }

                $existingUser->update($updatePayload);

                if (method_exists($existingUser, 'assignRole') && method_exists($existingUser, 'hasRole')) {
                    if (!$existingUser->hasRole('customer')) {
                        $existingUser->assignRole('customer');
                    }
                }
                Log::info("Importer: Updated customer: {$customerData['email']}");
            }
        } else {
            if (!$this->dryRun) {
                $payload = [
                    'name' => $customerData['name'],
                    'email' => $customerData['email'],
                    'company' => $customerData['company'] ?? null,
                    'billing_id' => $billingIdValue,
                    'billing_system' => $customerData['billing_system'] ?? null,
                    'account_manager' => $accountManagerValue,
                    'password' => $passwordToUse,
                    'email_verified_at' => $customerData['email_verified_at'] ?? null,
                    'force_password_reset' => $forcePasswordReset,
                ];

                $createdUser = User::create($payload);

                if (isset($createdUser) && method_exists($createdUser, 'assignRole')) {
                    $createdUser->assignRole('customer');
                }
                Log::info("Importer: Created new customer: {$customerData['email']}");
            }
        }
    }

    /**
     * Import a ticket row
     *
     * @param array $headers
     * @param array $row
     * @param int $rowNumber
     * @return void
     */
    protected function importTicketRow(array $headers, array $row, int $rowNumber): void
    {
        $data = array_combine($headers, $row);
        $ticketData = $this->mapData($data);

        $validator = Validator::make($ticketData, [
            'subject' => 'required|string|max:255',
            'department_id' => 'nullable|integer|min:1',
            'department_name' => 'nullable|string',
            'user_id' => 'nullable|integer|min:0',
            'user_email' => 'nullable|email',
            'public_email' => 'nullable|email',
            'assigned' => 'nullable|integer|min:0',
            'ip_address' => 'nullable|string|max:45',
            'organize' => 'nullable|string',
        ]);

        $validator->after(function ($validator) use ($ticketData) {
            $userId = isset($ticketData['user_id']) ? (int) $ticketData['user_id'] : 0;
            $userEmail = $ticketData['user_email'] ?? null;
            $publicEmail = $ticketData['public_email'] ?? null;
            $departmentId = isset($ticketData['department_id']) ? (int) $ticketData['department_id'] : 0;
            $departmentName = $ticketData['department_name'] ?? null;

            if (
                $userId <= 0 &&
                empty($userEmail) &&
                empty($publicEmail)
            ) {
                $validator->errors()->add(
                    'user_id',
                    'Either a valid user_id, user_email, or public_email is required for ticket imports.'
                );
            }

            if ($departmentId <= 0 && empty($departmentName)) {
                $validator->errors()->add(
                    'department_id',
                    'Either a valid department_id or department_name is required.'
                );
            }

            try {
                $this->normalizeStatusValue($ticketData['status'] ?? null);
            } catch (\InvalidArgumentException $e) {
                $validator->errors()->add('status', $e->getMessage());
            }

            try {
                $this->normalizePriorityValue($ticketData['priority'] ?? null);
            } catch (\InvalidArgumentException $e) {
                $validator->errors()->add('priority', $e->getMessage());
            }

            try {
                $this->normalizeOrganizeValue($ticketData['organize'] ?? null);
            } catch (\InvalidArgumentException $e) {
                $validator->errors()->add('organize', $e->getMessage());
            }
        });

        if ($validator->fails()) {
            throw new \Exception("Row {$rowNumber}: " . implode(', ', $validator->errors()->all()));
        }

        $user = null;
        $userId = isset($ticketData['user_id']) ? (int) $ticketData['user_id'] : 0;
        if ($userId > 0) {
            $user = User::find($userId);
            if (!$user) {
                throw new \Exception("Row {$rowNumber}: Customer not found for user_id {$userId}.");
            }
        } elseif (!empty($ticketData['user_email'])) {
            $user = User::where('email', $ticketData['user_email'])->first();
            if (!$user) {
                throw new \Exception("Row {$rowNumber}: Customer not found: {$ticketData['user_email']}. Please import customers first.");
            }
        }

        $departmentId = isset($ticketData['department_id']) ? (int) $ticketData['department_id'] : 0;
        if ($departmentId > 0) {
            $department = Departments::find($departmentId);
            if (!$department) {
                throw new \Exception("Row {$rowNumber}: Department not found for department_id {$departmentId}.");
            }
        } else {
            $department = Departments::where('department_name', $ticketData['department_name'])->first();
        }

        if (!$department) {
            $identifier = $ticketData['department_name'] ?? (string) $departmentId;
            throw new \Exception("Row {$rowNumber}: Department not found: {$identifier}");
        }

        $statusValue = $this->normalizeStatusValue($ticketData['status'] ?? null);
        $priorityValue = $this->normalizePriorityValue($ticketData['priority'] ?? null);
        $organizeValue = $this->normalizeOrganizeValue($ticketData['organize'] ?? null);

        if ($this->dryRun) {
            return;
        }

        $ticketPayload = [
            'subject' => $ticketData['subject'],
            'message' => $ticketData['message'] ?? '',
            'status' => $statusValue,
            'priority' => $priorityValue,
            'department_id' => $department->id,
            'public_hash' => hash_hmac('sha256', uniqid('', true), config('app.key')),
            'organize' => $organizeValue,
            'created_at' => $ticketData['created_at'] ?? now(),
            'updated_at' => $ticketData['updated_at'] ?? now(),
        ];

        if ($user) {
            $ticketPayload['user_id'] = $user->id;
        }

        if (!empty($ticketData['public_name'])) {
            $ticketPayload['public_name'] = $ticketData['public_name'];
        }

        if (array_key_exists('public_email', $ticketData)) {
            $ticketPayload['public_email'] = $ticketData['public_email'] ?: null;
            if (!$user && empty($ticketPayload['public_email'])) {
                throw new \Exception("Row {$rowNumber}: Public email is required when no customer ID or email is provided.");
            }
        } elseif (!$user) {
            throw new \Exception("Row {$rowNumber}: Public email is required when no customer ID or email is provided.");
        }

        if (array_key_exists('assigned', $ticketData)) {
            $ticketPayload['assigned'] = (string) $this->normalizeInteger($ticketData['assigned']);
        }

        if (array_key_exists('ip_address', $ticketData)) {
            $ticketPayload['ip_address'] = $ticketData['ip_address'] !== '' ? $ticketData['ip_address'] : null;
        }

        Tickets::create($ticketPayload);
    }

    /**
     * Import a response row
     *
     * @param array $headers
     * @param array $row
     * @param int $rowNumber
     * @return void
     */
    protected function importResponseRow(array $headers, array $row, int $rowNumber): void
    {
        $data = array_combine($headers, $row);
        $responseData = $this->mapData($data);

        // Validate required fields
        $validator = Validator::make($responseData, [
            'ticket_id' => 'nullable|exists:tickets,id',
            'ticket_number' => 'nullable|integer|min:1',
            'content' => 'required|string',
            'organize' => 'nullable|string',
            'ip_address' => 'nullable|string|max:255',
            'employee_response' => 'nullable',
        ]);

        $validator->after(function ($validator) use ($responseData) {
            $ticketId = $responseData['ticket_id'] ?? null;
            $ticketNumber = $responseData['ticket_number'] ?? null;

            if (empty($ticketId) && empty($ticketNumber)) {
                $validator->errors()->add('ticket_id', 'Either a valid ticket_id or ticket_number is required for response imports.');
            }
        });

        if ($validator->fails()) {
            throw new \Exception("Row {$rowNumber}: " . implode(', ', $validator->errors()->all()));
        }

        // Get ticket
        $ticket = null;
        if (!empty($responseData['ticket_id'])) {
            $ticket = Tickets::find($responseData['ticket_id']);
        } elseif (!empty($responseData['ticket_number'])) {
            $ticket = Tickets::find($responseData['ticket_number']);
        }

        if (!$ticket) {
            $reference = $responseData['ticket_id'] ?? $responseData['ticket_number'];
            throw new \Exception("Ticket not found: {$reference}");
        }

        // Determine user ID
        $userId = $responseData['user_id'] ?? $ticket->user_id;

        $organizeValue = $this->normalizeOrganizeValue($responseData['organize'] ?? 'ticket');
        $employeeResponse = array_key_exists('employee_response', $responseData)
            ? $this->interpretBoolean($responseData['employee_response'])
            : (array_key_exists('is_employee', $responseData)
                ? $this->interpretBoolean($responseData['is_employee'])
                : false);
        $isNote = array_key_exists('is_note', $responseData)
            ? $this->interpretBoolean($responseData['is_note'])
            : false;

        if ($this->dryRun) {
            return;
        }

        Responses::create([
            'ticket_number' => $ticket->id,
            'user_id' => $userId,
            'content' => $responseData['content'],
            'employee_response' => $employeeResponse,
            'is_note' => $isNote,
            'organize' => $organizeValue,
            'ip_address' => $responseData['ip_address'] ?? null,
            'created_at' => $responseData['created_at'] ?? now(),
            'updated_at' => $responseData['updated_at'] ?? now(),
        ]);
    }

    /**
     * Import a department row
     *
     * @param array $headers
     * @param array $row
     * @param int $rowNumber
     * @return void
     */
    protected function importDepartmentRow(array $headers, array $row, int $rowNumber): void
    {
        $data = array_combine($headers, $row);
        $departmentData = $this->mapData($data);

        $validator = Validator::make($departmentData, [
            'department_name' => 'required|string|max:255',
            'slug' => 'nullable|string|max:255',
            'department_email' => 'nullable|email',
        ]);

        if ($validator->fails()) {
            throw new \Exception("Row {$rowNumber}: " . implode(', ', $validator->errors()->all()));
        }

        $updateExisting = (bool) ($this->options['update_existing'] ?? false);
        $slugSource = $departmentData['slug'] ?? $departmentData['department_name'];
        $normalizedSlug = Str::slug((string) $slugSource);
        if ($normalizedSlug === '') {
            $normalizedSlug = 'department';
        }

        $existingByName = Departments::where('department_name', $departmentData['department_name'])->first();
        $existingBySlug = Departments::where('slug', $normalizedSlug)->first();

        $existingDepartment = $existingByName ?? ($updateExisting ? $existingBySlug : null);

        $departmentPayload = [
            'department_name' => $departmentData['department_name'],
            'department_description' => $departmentData['department_description'] ?? null,
            'department_email' => $departmentData['department_email'] ?? null,
            'allows_high_priority' => array_key_exists('allows_high_priority', $departmentData)
                ? $this->interpretBoolean($departmentData['allows_high_priority'])
                : true,
            'cc_enabled' => array_key_exists('cc_enabled', $departmentData)
                ? $this->interpretBoolean($departmentData['cc_enabled'])
                : false,
            'is_public' => array_key_exists('is_public', $departmentData)
                ? $this->interpretBoolean($departmentData['is_public'])
                : true,
            'is_disabled' => array_key_exists('is_disabled', $departmentData)
                ? $this->interpretBoolean($departmentData['is_disabled'])
                : false,
            'soft_deleted' => array_key_exists('soft_deleted', $departmentData)
                ? $this->interpretBoolean($departmentData['soft_deleted'])
                : false,
            'created_at' => $departmentData['created_at'] ?? now(),
            'updated_at' => $departmentData['updated_at'] ?? now(),
        ];

        if ($this->dryRun) {
            return;
        }

        if ($existingDepartment) {
            if (!$updateExisting) {
                throw new \Exception("Row {$rowNumber}: Department already exists: {$departmentData['department_name']} ({$normalizedSlug}).");
            }

            $departmentPayload['slug'] = $existingDepartment->slug;
            $existingDepartment->update($departmentPayload);
            return;
        }

        $departmentPayload['slug'] = $this->generateUniqueSlug($normalizedSlug);

        Departments::create($departmentPayload);
    }

    /**
     * Import an announcement row
     *
     * @param array $headers
     * @param array $row
     * @param int $rowNumber
     * @return void
     */
    protected function importAnnouncementRow(array $headers, array $row, int $rowNumber): void
    {
        $data = array_combine($headers, $row);
        $announcementData = $this->mapData($data);

        // Validate required fields
        $validator = Validator::make($announcementData, [
            'title' => 'required|string|max:255',
            'body' => 'required|string',
        ]);

        if ($validator->fails()) {
            throw new \Exception("Row {$rowNumber}: " . implode(', ', $validator->errors()->all()));
        }

        // Generate slug
        $slug = Str::slug($announcementData['title']);

        // Check if announcement exists (by slug)
        $existing = Announcements::where('slug', $slug)->first();

        if ($existing) {
            if (!$this->options['update_existing']) {
                throw new \Exception("Announcement already exists: {$announcementData['title']}");
            }

            if (!$this->dryRun) {
                $existing->update([
                    'title' => $announcementData['title'],
                    'body' => $announcementData['body'],
                    'is_published' => $announcementData['is_published'] ?? true,
                ]);
                Log::info("Importer: Updated announcement: {$announcementData['title']}");
            }
        } else {
            if (!$this->dryRun) {
                Announcements::create([
                    'title' => $announcementData['title'],
                    'slug' => $slug,
                    'body' => $announcementData['body'],
                    'is_published' => $announcementData['is_published'] ?? true,
                    'views' => 0,
                    'user_id' => auth()->id() ?? 1, // Default to admin
                    'created_at' => $announcementData['created_at'] ?? now(),
                    'updated_at' => $announcementData['updated_at'] ?? now(),
                ]);
                Log::info("Importer: Created announcement: {$announcementData['title']}");
            }
        }
    }

    /**
     * Map CSV data to Ticaga fields
     *
     * @param array $data
     * @return array
     */
    protected function mapData(array $data): array
    {
        $mapped = [];

        foreach ($this->mapping as $csvColumn => $ticagaField) {
            if (isset($data[$csvColumn])) {
                $mapped[$ticagaField] = $data[$csvColumn];
            }
        }

        return $mapped;
    }

    protected function interpretBoolean($value): bool
    {
        if (is_bool($value)) {
            return $value;
        }

        $normalized = strtolower(trim((string)$value));

        return in_array($normalized, ['1', 'true', 'yes', 'y', 'on', 'enabled'], true);
    }

    protected function normalizeInteger($value): int
    {
        if ($value === null || $value === '' || !is_numeric($value)) {
            return 0;
        }

        return (int) $value;
    }

    protected function normalizeStatusValue($value): string
    {
        if ($value === null || $value === '') {
            return TicketStatus::Open->value;
        }

        if (is_numeric($value)) {
            $statusMap = [
                -1 => TicketStatus::Closed->value,
                0 => TicketStatus::Open->value,
                1 => TicketStatus::Open->value,
                2 => TicketStatus::InProgress->value,
                3 => TicketStatus::AwaitingReply->value,
                4 => TicketStatus::InProgress->value,
            ];

            $intValue = (int) $value;
            if (isset($statusMap[$intValue])) {
                return $statusMap[$intValue];
            }
        }

        $normalized = strtolower(trim((string) $value));
        $aliases = [
            TicketStatus::Open->value => TicketStatus::Open->value,
            'open' => TicketStatus::Open->value,
            'unassigned' => TicketStatus::Open->value,
            TicketStatus::Closed->value => TicketStatus::Closed->value,
            'closed' => TicketStatus::Closed->value,
            TicketStatus::AwaitingReply->value => TicketStatus::AwaitingReply->value,
            'awaiting_reply' => TicketStatus::AwaitingReply->value,
            'awaitingreply' => TicketStatus::AwaitingReply->value,
            'waiting on customer' => TicketStatus::AwaitingReply->value,
            'waiting_on_customer' => TicketStatus::AwaitingReply->value,
            'waitingoncustomer' => TicketStatus::AwaitingReply->value,
            TicketStatus::InProgress->value => TicketStatus::InProgress->value,
            'in_progress' => TicketStatus::InProgress->value,
            'inprogress' => TicketStatus::InProgress->value,
            'on_hold' => TicketStatus::InProgress->value,
            'on hold' => TicketStatus::InProgress->value,
            'hold' => TicketStatus::InProgress->value,
            'trash' => TicketStatus::Closed->value,
        ];

        if (isset($aliases[$normalized])) {
            return $aliases[$normalized];
        }

        throw new \InvalidArgumentException("Unsupported status value: {$value}");
    }

    protected function normalizePriorityValue($value): string
    {
        if ($value === null || $value === '') {
            return TicketPriority::None->value;
        }

        if (is_numeric($value)) {
            $priorityMap = [
                0 => TicketPriority::None->value,
                1 => TicketPriority::Low->value,
                2 => TicketPriority::Medium->value,
                3 => TicketPriority::High->value,
                4 => TicketPriority::Emergency->value,
            ];

            $intValue = (int) $value;
            if (isset($priorityMap[$intValue])) {
                return $priorityMap[$intValue];
            }
        }

        $normalized = strtolower(trim((string) $value));
        $aliases = [
            TicketPriority::None->value => TicketPriority::None->value,
            'not set' => TicketPriority::None->value,
            TicketPriority::Low->value => TicketPriority::Low->value,
            TicketPriority::Medium->value => TicketPriority::Medium->value,
            TicketPriority::High->value => TicketPriority::High->value,
            TicketPriority::Emergency->value => TicketPriority::Emergency->value,
            'urgent' => TicketPriority::Emergency->value,
        ];

        if (isset($aliases[$normalized])) {
            return $aliases[$normalized];
        }

        throw new \InvalidArgumentException("Unsupported priority value: {$value}");
    }

    protected function normalizeOrganizeValue($value): string
    {
        if ($value === null || $value === '') {
            return TicketOrganize::Ticket->value;
        }

        $normalized = strtolower(trim((string) $value));
        $aliases = [
            TicketOrganize::Ticket->value => TicketOrganize::Ticket->value,
            'web' => TicketOrganize::Ticket->value,
            TicketOrganize::Email->value => TicketOrganize::Email->value,
            'mail' => TicketOrganize::Email->value,
            'imap' => TicketOrganize::Email->value,
            TicketOrganize::Blesta->value => TicketOrganize::Blesta->value,
            TicketOrganize::WHMCS->value => TicketOrganize::WHMCS->value,
            'clientexec' => TicketOrganize::ClientExec->value,
            'client_exec' => TicketOrganize::ClientExec->value,
            'client-exec' => TicketOrganize::ClientExec->value,
        ];

        if (isset($aliases[$normalized])) {
            return $aliases[$normalized];
        }

        foreach (TicketOrganize::cases() as $case) {
            if (strcasecmp($case->value, (string) $value) === 0) {
                return $case->value;
            }
        }

        throw new \InvalidArgumentException("Unsupported organize value: {$value}");
    }

    protected function generateUniqueSlug(string $baseSlug): string
    {
        $slug = $baseSlug;
        $counter = 1;

        while ($this->slugExists($slug)) {
            $slug = $baseSlug . '-' . $counter;
            $counter++;
        }

        return $slug;
    }

    protected function slugExists(string $slug): bool
    {
        return Departments::where('slug', $slug)->exists();
    }

    /**
     * Get import results
     *
     * @return array
     */
    public function getResults(): array
    {
        return [
            'type' => $this->importType,
            'imported' => $this->imported,
            'skipped' => $this->skipped,
            'errors' => $this->errors,
        ];
    }
}
