<?php
declare(strict_types=1);

namespace App\Services;

use App\Industry\Catalog;

final class SetupDefaults
{
    public const LABEL_KEYS = [
        'opportunity' => 'Deal',
        'opportunities' => 'Deals',
        'account' => 'Account',
        'accounts' => 'Accounts',
        'lead' => 'Lead',
        'leads' => 'Leads',
        'contact' => 'Contact',
        'contacts' => 'Contacts',
    ];

    public const FIELD_TYPES = ['text', 'number', 'date', 'select', 'money'];

    public const FORM_KEYS = ['lead_create', 'opportunity_create', 'visit', 'service_request'];

    public const MODULES = [
        'dashboard' => 'Home',
        'leads' => 'Leads',
        'accounts' => 'Accounts',
        'contacts' => 'Contacts',
        'opportunities' => 'Deals',
        'tasks' => 'Tasks',
        'calendar' => 'Calendar',
        'emails' => 'Email',
        'reports' => 'Reports',
        'assignment' => 'Lead assignment',
        'campaigns' => 'Campaigns',
        'lists' => 'Lists',
        'templates' => 'Templates',
        'unsubscribes' => 'Unsubscribes',
        'campaign_reports' => 'Campaign reports',
        'service_visits' => 'Service visits',
        'quotes' => 'Quotes',
        'documents' => 'Documents',
        'orders' => 'Orders',
        'contracts' => 'Contracts',
        'invoices' => 'Invoices',
        'approvals' => 'Approvals',
        'renewals' => 'Renewals',
        'service_jobs' => 'Service jobs',
        'equipment' => 'Equipment',
        'settings' => 'Settings',
    ];

    public const ROLES = ['salesperson', 'manager', 'admin', 'marketing', 'service'];

    public const DASH_CARDS = [
        'salesperson' => [
            'kpis' => 'Today numbers',
            'tasks' => 'My tasks',
            'upcoming' => 'Upcoming meetings',
            'recent' => 'Recent activity',
            'marketing' => 'Marketing snapshot',
        ],
        'manager' => [
            'kpis' => 'Team numbers',
            'pipeline' => 'Pipeline overview',
            'team' => 'Team and late work',
            'marketing' => 'Marketing snapshot',
        ],
        'admin' => [
            'kpis' => 'Company numbers',
            'jumps' => 'Quick links',
        ],
        'service' => [
            'kpis' => 'Visit numbers',
            'visits' => 'My visits',
            'tasks' => 'My tasks',
            'upcoming' => 'Upcoming meetings',
        ],
        'marketing' => [
            'kpis' => 'Campaign numbers',
            'jumps' => 'Quick links',
        ],
    ];

    public const CORE_FORM_FIELDS = [
        'lead_create' => [
            'first_name' => 'First name',
            'last_name' => 'Last name',
            'company' => 'Company',
            'email' => 'Email',
            'phone' => 'Phone',
            'source' => 'Source',
        ],
        'opportunity_create' => [
            'name' => 'Name',
            'account_id' => 'Account',
            'amount' => 'Amount',
        ],
        'visit' => [
            'service_assignee_id' => 'Assigned technician / consultant',
            'notes' => 'Notes',
        ],
        'service_request' => [
            'account_id' => 'Account',
            'subject' => 'Subject',
            'visit_at' => 'Visit date',
            'service_assignee_id' => 'Assigned technician / consultant',
            'body' => 'Details',
        ],
    ];

    public const LOCKED_FORM_FIELDS = [
        'lead_create' => ['first_name'],
        'opportunity_create' => ['name', 'account_id'],
        'visit' => ['notes'],
        'service_request' => ['account_id', 'subject', 'visit_at', 'body'],
    ];

    public const TRIGGERS = [
        'lead_created' => 'A lead is created',
        'task_overdue' => 'A task is overdue',
        'deal_won' => 'A deal is won',
        'deal_stage_changed' => 'A deal changes stage',
    ];

    public const ACTIONS = [
        'create_task' => 'Create a follow-up task',
        'notify_owner' => 'Notify the owner',
        'notify_manager' => 'Notify the manager',
        'assign_round_robin' => 'Assign the next salesperson',
    ];

    /** @return array<string, list<string>> */
    public static function roleModules(): array
    {
        return [
            'dashboard' => ['salesperson', 'manager', 'admin', 'service', 'marketing'],
            'leads' => ['salesperson', 'manager'],
            'accounts' => ['salesperson', 'manager', 'service'],
            'contacts' => ['salesperson', 'manager', 'service'],
            'opportunities' => ['salesperson', 'manager'],
            'tasks' => ['salesperson', 'manager', 'service'],
            'calendar' => ['salesperson', 'manager', 'service'],
            'emails' => ['salesperson', 'manager'],
            'reports' => ['manager'],
            'assignment' => ['manager'],
            'campaigns' => ['marketing'],
            'lists' => ['marketing'],
            'templates' => ['marketing'],
            'unsubscribes' => ['marketing', 'admin'],
            'campaign_reports' => ['marketing', 'manager', 'salesperson'],
            'service_visits' => ['service', 'manager'],
            'quotes' => ['salesperson', 'manager'],
            'documents' => ['salesperson', 'manager'],
            'orders' => ['salesperson', 'manager'],
            'contracts' => ['salesperson', 'manager'],
            'invoices' => ['salesperson', 'manager'],
            'approvals' => ['manager'],
            'renewals' => ['salesperson', 'manager'],
            'service_jobs' => ['service', 'manager'],
            'equipment' => ['service', 'manager'],
            'settings' => ['admin', 'salesperson', 'manager', 'service', 'marketing'],
        ];
    }

    /** @return array<string, mixed> */
    public static function payload(?array $industry = null): array
    {
        $industry ??= Catalog::current();
        $labels = self::LABEL_KEYS;
        $labels['opportunity'] = rtrim((string) ($industry['opportunity_label'] ?? 'Deal'), 's') ?: 'Deal';
        $labels['opportunities'] = (string) ($industry['opportunity_label'] ?? 'Deals');
        $labels['account'] = rtrim((string) ($industry['account_label'] ?? 'Account'), 's') ?: 'Account';
        $labels['accounts'] = (string) ($industry['account_label'] ?? 'Accounts');

        $fields = [];
        foreach (['account' => 'account_fields', 'opportunity' => 'opportunity_fields'] as $entity => $key) {
            foreach ($industry[$key] ?? [] as $f) {
                $fields[] = self::normalizeField($entity, $f, 'catalog');
            }
        }

        $stages = [];
        $sort = 1;
        foreach ($industry['stages'] ?? [] as $s) {
            $stages[] = [
                'id' => 'stg_' . (string) $s['code'],
                'code' => (string) $s['code'],
                'name' => (string) $s['name'],
                'probability' => (int) $s['probability'],
                'is_won' => (int) $s['won'],
                'is_lost' => (int) $s['lost'],
                'sort_order' => $sort,
                'required_fields' => [],
            ];
            $sort++;
        }

        $forms = [];
        foreach (self::CORE_FORM_FIELDS as $form => $core) {
            $forms[$form] = array_keys($core);
            $entity = match ($form) {
                'lead_create' => 'lead',
                'opportunity_create' => 'opportunity',
                default => 'service',
            };
            foreach ($fields as $f) {
                if (($f['entity'] ?? '') === $entity) {
                    $forms[$form][] = $f['key'];
                }
            }
        }

        $dashboard = [];
        foreach (self::DASH_CARDS as $role => $cards) {
            $dashboard[$role] = array_keys($cards);
        }

        $permissions = [];
        $map = self::roleModules();
        foreach (self::ROLES as $role) {
            $permissions[$role] = [];
            foreach (self::MODULES as $module => $_) {
                $permissions[$role][$module] = in_array($role, $map[$module] ?? [], true) ? 'edit' : 'hide';
            }
            $permissions[$role]['dashboard'] = 'edit';
        }

        return [
            'labels' => $labels,
            'fields' => $fields,
            'stages' => $stages,
            'forms' => $forms,
            'automations' => [
                [
                    'id' => 'aut_lead_followup',
                    'active' => false,
                    'trigger' => 'lead_created',
                    'action' => 'create_task',
                    'title' => 'Follow up on new lead',
                    'due_days' => 1,
                ],
                [
                    'id' => 'aut_task_late',
                    'active' => false,
                    'trigger' => 'task_overdue',
                    'action' => 'notify_manager',
                    'title' => 'Task is overdue',
                    'due_days' => 0,
                ],
                [
                    'id' => 'aut_deal_won',
                    'active' => false,
                    'trigger' => 'deal_won',
                    'action' => 'create_task',
                    'title' => 'Next step after win',
                    'due_days' => 2,
                ],
            ],
            'dashboard' => $dashboard,
            'permissions' => $permissions,
        ];
    }

    /** @param array<string, mixed> $field */
    public static function normalizeField(string $entity, array $field, string $source = 'custom'): array
    {
        $options = [];
        if (($field['type'] ?? '') === 'select') {
            foreach ($field['options'] ?? [] as $val => $label) {
                $options[(string) $val] = (string) $label;
            }
        }
        return [
            'id' => (string) ($field['id'] ?? $source . '_' . $entity . '_' . $field['key']),
            'entity' => $entity,
            'key' => (string) $field['key'],
            'label' => (string) $field['label'],
            'type' => in_array((string) ($field['type'] ?? 'text'), self::FIELD_TYPES, true) ? (string) $field['type'] : 'text',
            'options' => $options,
            'active' => array_key_exists('active', $field) ? (bool) $field['active'] : true,
            'source' => $source,
        ];
    }
}
