<?php
if (!defined('ABSPATH')) exit;

require_once plugin_dir_path(__FILE__) . '../includes/api.php';
require_once plugin_dir_path(__FILE__) . '../includes/security.php';

if (!function_exists('afb_gf_asana_items')) {
    function afb_gf_asana_items($res) {
        if (!$res) return [];
        if (isset($res['data']) && is_array($res['data'])) return $res['data'];
        return is_array($res) ? $res : [];
    }
}

if (!function_exists('afb_gf_cf_type')) {
    function afb_gf_cf_type(array $field) {
        $type = strtolower((string)($field['type'] ?? ''));
        if ($type !== '') return $type;
        $type = strtolower((string)($field['resource_subtype'] ?? ''));
        if ($type !== '') return $type;
        return strtolower((string)($field['representation_type'] ?? ''));
    }
}

if (!function_exists('afb_gf_add_field_to_index')) {
    function afb_gf_add_field_to_index(array &$index, array $field) {
        $gid = preg_replace('/\D+/', '', (string)($field['gid'] ?? ''));
        if ($gid === '') return;

        $type = afb_gf_cf_type($field);
        if ($type !== '' && $type !== 'text') return;

        $index[$gid] = [
            'gid' => $gid,
            'name' => trim((string)($field['name'] ?? $gid)),
            'type' => $type,
        ];
    }
}

if (!function_exists('afb_gf_collect_workspace_custom_fields')) {
    function afb_gf_collect_workspace_custom_fields($workspace_gid, $pat, array &$dbg) {
        if (!$workspace_gid || !$pat) return [];

        $endpoint = 'workspaces/' . urlencode((string)$workspace_gid) . '/custom_fields?limit=200&opt_fields=gid,name,type,resource_subtype';
        $rows = afb_gf_asana_items(afb_fetch_asana($endpoint, $pat));

        $index = [];
        foreach ($rows as $row) {
            afb_gf_add_field_to_index($index, is_array($row) ? $row : []);
        }

        $dbg['workspace_fields'] = count($rows);
        return $index;
    }
}

if (!function_exists('afb_gf_collect_portfolio_custom_fields')) {
    function afb_gf_collect_portfolio_custom_fields($portfolio_gid, $pat, array &$dbg) {
        if (!$portfolio_gid || !$pat) return [];

        $projects = afb_gf_asana_items(afb_get_portfolio_projects((string)$portfolio_gid, $pat));
        if (!$projects) {
            $projects = afb_gf_asana_items(
                afb_fetch_asana('portfolios/' . urlencode((string)$portfolio_gid) . '/items?limit=200&opt_fields=gid,name,resource_type,resource_subtype', $pat)
            );
        }

        $index = [];
        $project_gids = [];
        $field_cache = [];

        foreach ($projects as $item) {
            $gid = preg_replace('/\D+/', '', (string)($item['gid'] ?? ''));
            if ($gid === '') continue;

            $resource_type = strtolower((string)($item['resource_type'] ?? ''));
            $resource_subtype = strtolower((string)($item['resource_subtype'] ?? ''));
            if ($resource_type === 'project' || $resource_subtype === 'project' || $resource_type === '') {
                $project_gids[$gid] = true;
            }
        }

        if (!$project_gids) {
            $dbg['notes'][] = 'No project IDs found in selected portfolio payload.';
        }

        foreach (array_keys($project_gids) as $project_gid) {
            $dbg['projects']++;
            $settings = afb_gf_asana_items(afb_get_project_fields($project_gid, $pat));

            if (!$settings) {
                $settings = afb_gf_asana_items(
                    afb_fetch_asana('projects/' . urlencode($project_gid) . '/custom_field_settings?limit=200&opt_fields=custom_field.gid,custom_field.name,custom_field.type,custom_field.resource_subtype,custom_field.representation_type,custom_field_gid', $pat)
                );
            }

            foreach ($settings as $setting) {
                if (!is_array($setting)) continue;
                $field = [];
                if (!empty($setting['custom_field']) && is_array($setting['custom_field'])) {
                    $field = $setting['custom_field'];
                } elseif (!empty($setting['custom_field_gid'])) {
                    $cf_gid = preg_replace('/\D+/', '', (string)$setting['custom_field_gid']);
                    if ($cf_gid !== '') {
                        if (!isset($field_cache[$cf_gid])) {
                            $field_cache[$cf_gid] = afb_fetch_asana('custom_fields/' . urlencode($cf_gid) . '?opt_fields=gid,name,type,resource_subtype', $pat);
                        }
                        if (is_array($field_cache[$cf_gid])) {
                            $field = $field_cache[$cf_gid];
                        }
                    }
                }

                afb_gf_add_field_to_index($index, $field);
            }
        }

        return $index;
    }
}

if (!function_exists('afb_gf_guess_identity_field_gid')) {
    function afb_gf_guess_identity_field_gid(array $fields_for_ui, $kind) {
        $patterns = [
            'first_name' => '/(^|\\b)(first\\s*name|forename|given\\s*name)(\\b|$)/i',
            'last_name'  => '/(^|\\b)(last\\s*name|surname|family\\s*name)(\\b|$)/i',
            'email'      => '/(^|\\b)(work\\s*)?e-?mail(\\b|$)/i',
        ];

        $pattern = $patterns[$kind] ?? null;
        if (!$pattern) return '';

        foreach ($fields_for_ui as $f) {
            if (preg_match($pattern, (string)($f['name'] ?? ''))) {
                return (string)($f['gid'] ?? '');
            }
        }

        return '';
    }
}

if (!function_exists('afb_gf_map_read')) {
    function afb_gf_map_read() {
        $path = WP_CONTENT_DIR . '/mu-plugins/global-field-map.json';
        if (is_readable($path)) {
            $json = @file_get_contents($path);
            if ($json !== false) {
                $decoded = json_decode($json, true);
                if (is_array($decoded)) {
                    return $decoded;
                }
            }
        }

        // Fallback to shared loader helpers when direct file reads are unavailable.
        if (function_exists('get_global_field_map')) {
            $map = get_global_field_map();
            if (is_array($map)) return $map;
        }

        if (function_exists('load_global_field_map')) {
            $map = load_global_field_map();
            if (is_array($map)) return $map;
        }

        return [];
    }
}

if (!function_exists('afb_gf_map_write')) {
    function afb_gf_map_write(array $map) {
        $path = WP_CONTENT_DIR . '/mu-plugins/global-field-map.json';
        $json = wp_json_encode($map, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
        if ($json === false) return false;

        $dir = dirname($path);
        if (!is_dir($dir) && !wp_mkdir_p($dir)) {
            return false;
        }

        $tmp = $path . '.tmp-' . uniqid('', true);
        $res = @file_put_contents($tmp, $json, LOCK_EX);
        if ($res === false) return false;

        if (!@rename($tmp, $path)) {
            @unlink($tmp);
            return false;
        }

        @chmod($path, 0644);
        return true;
    }
}

if (!function_exists('afb_gf_get_accounts')) {
    function afb_gf_get_accounts() {
        global $wpdb;
        $table = $wpdb->prefix . 'asana_accounts';
        $rows = $wpdb->get_results("SELECT * FROM $table ORDER BY id DESC", ARRAY_A) ?: [];

        $out = [];
        foreach ($rows as $row) {
            $pat_raw = sanitize_text_field((string)($row['pat'] ?? ''));
            $pat = function_exists('afb_decrypt') ? (afb_decrypt($pat_raw) ?: $pat_raw) : $pat_raw;
            $out[] = [
                'id' => (int)($row['id'] ?? 0),
                'label' => sanitize_text_field((string)($row['label'] ?? '')),
                'portfolio_gid' => preg_replace('/\D+/', '', (string)($row['portfolio_gid'] ?? '')),
                'active' => (int)($row['active'] ?? 0) === 1,
                'pat' => $pat,
            ];
        }

        return $out;
    }
}

if (!function_exists('afb_gf_get_account')) {
    function afb_gf_get_account($pat_id) {
        $pat_id = (int)$pat_id;
        foreach (afb_gf_get_accounts() as $account) {
            if ((int)$account['id'] === $pat_id) return $account;
        }
        return null;
    }
}

if (!function_exists('afb_gf_load_editor_context')) {
    function afb_gf_load_editor_context($pat_id, $workspace_gid = '', $target_scope = 'workspace', $portfolio_gid = '') {
        $account = afb_gf_get_account($pat_id);
        if (!$account || empty($account['pat'])) {
            return ['error' => 'Unable to resolve PAT account.'];
        }

        $pat = (string)$account['pat'];
        $workspace_gid = preg_replace('/\D+/', '', (string)$workspace_gid);
        $portfolio_gid = preg_replace('/\D+/', '', (string)$portfolio_gid);
        $target_scope = ($target_scope === 'portfolio') ? 'portfolio' : 'workspace';

        $map = afb_gf_map_read();

        $workspaces = [];
        $ws_res = afb_fetch_asana('workspaces', $pat);
        foreach (afb_gf_asana_items($ws_res) as $ws) {
            if (empty($ws['gid'])) continue;
            $workspaces[] = [
                'gid' => preg_replace('/\D+/', '', (string)$ws['gid']),
                'name' => sanitize_text_field((string)($ws['name'] ?? $ws['gid'])),
            ];
        }

        if ($workspace_gid === '' && !empty($workspaces[0]['gid'])) {
            $workspace_gid = $workspaces[0]['gid'];
        }

        $portfolios = [];
        if ($workspace_gid !== '') {
            $pf_rows = afb_gf_asana_items(
                afb_fetch_asana('workspaces/' . urlencode((string)$workspace_gid) . '/portfolios?limit=200&opt_fields=name,gid,workspace.gid', $pat)
            );

            if (!$pf_rows) {
                $pf_rows = afb_gf_asana_items(
                    afb_fetch_asana('portfolios?limit=200&workspace=' . urlencode($workspace_gid) . '&opt_fields=name,gid,workspace.gid', $pat)
                );
            }

            if (!$pf_rows) {
                $pf_rows = afb_gf_asana_items(
                    afb_fetch_asana('portfolios?limit=200&workspace=' . urlencode($workspace_gid) . '&owner=me&opt_fields=name,gid,workspace.gid', $pat)
                );
            }

            if (!$pf_rows) {
                $fallback_rows = afb_gf_asana_items(
                    afb_fetch_asana('portfolios?limit=200&owner=me&opt_fields=name,gid,workspace.gid', $pat)
                );
                if ($fallback_rows) {
                    $filtered = [];
                    foreach ($fallback_rows as $pf) {
                        $pf_ws_gid = preg_replace('/\D+/', '', (string)($pf['workspace']['gid'] ?? ''));
                        if ($pf_ws_gid === '' || $pf_ws_gid === $workspace_gid) {
                            $filtered[] = $pf;
                        }
                    }
                    $pf_rows = !empty($filtered) ? $filtered : $fallback_rows;
                }
            }

            $portfolio_index = [];
            $add_portfolio = static function (array &$index, $gid, $name = '') {
                $safe_gid = preg_replace('/\D+/', '', (string)$gid);
                if ($safe_gid === '') return;

                $safe_name = sanitize_text_field((string)($name !== '' ? $name : $safe_gid));
                $index[$safe_gid] = [
                    'gid' => $safe_gid,
                    'name' => ($safe_name !== '' ? $safe_name : $safe_gid),
                ];
            };

            foreach ($pf_rows as $pf) {
                $add_portfolio($portfolio_index, $pf['gid'] ?? '', (string)($pf['name'] ?? ''));
            }

            $saved_portfolios = $map['workspaces'][$workspace_gid]['portfolios'] ?? [];
            if (is_array($saved_portfolios)) {
                foreach (array_keys($saved_portfolios) as $saved_gid) {
                    $safe_saved_gid = preg_replace('/\D+/', '', (string)$saved_gid);
                    if ($safe_saved_gid === '' || isset($portfolio_index[$safe_saved_gid])) {
                        continue;
                    }

                    $one = afb_fetch_asana('portfolios/' . urlencode($safe_saved_gid) . '?opt_fields=name,gid', $pat);
                    $one = is_array($one) && isset($one['data']) && is_array($one['data']) ? $one['data'] : $one;
                    if (is_array($one) && !empty($one['gid'])) {
                        $add_portfolio($portfolio_index, $one['gid'], (string)($one['name'] ?? $safe_saved_gid));
                    } else {
                        $add_portfolio($portfolio_index, $safe_saved_gid, 'Saved portfolio • ' . $safe_saved_gid);
                    }
                }
            }

            $default_portfolio_gid = preg_replace('/\D+/', '', (string)($account['portfolio_gid'] ?? ''));
            if ($default_portfolio_gid !== '') {
                if (!isset($portfolio_index[$default_portfolio_gid])) {
                    $one = afb_fetch_asana('portfolios/' . urlencode($default_portfolio_gid) . '?opt_fields=name,gid', $pat);
                    $one = is_array($one) && isset($one['data']) && is_array($one['data']) ? $one['data'] : $one;
                    if (is_array($one) && !empty($one['gid'])) {
                        $add_portfolio($portfolio_index, $one['gid'], (string)($one['name'] ?? $default_portfolio_gid));
                    } else {
                        $add_portfolio($portfolio_index, $default_portfolio_gid, $default_portfolio_gid);
                    }
                }
            }

            $requested_portfolio_gid = preg_replace('/\D+/', '', (string)$portfolio_gid);
            if ($requested_portfolio_gid !== '' && !isset($portfolio_index[$requested_portfolio_gid])) {
                $one = afb_fetch_asana('portfolios/' . urlencode($requested_portfolio_gid) . '?opt_fields=name,gid', $pat);
                $one = is_array($one) && isset($one['data']) && is_array($one['data']) ? $one['data'] : $one;
                if (is_array($one) && !empty($one['gid'])) {
                    $add_portfolio($portfolio_index, $one['gid'], (string)($one['name'] ?? $requested_portfolio_gid));
                } else {
                    $add_portfolio($portfolio_index, $requested_portfolio_gid, 'Selected portfolio • ' . $requested_portfolio_gid);
                }
            }

            $portfolios = array_values($portfolio_index);

            usort($portfolios, static function ($a, $b) {
                return strcasecmp((string)($a['name'] ?? ''), (string)($b['name'] ?? ''));
            });
        }

        if ($target_scope === 'portfolio' && $portfolio_gid === '') {
            $portfolio_gid = preg_replace('/\D+/', '', (string)($account['portfolio_gid'] ?? ''));
            if ($portfolio_gid === '' && !empty($portfolios[0]['gid'])) {
                $portfolio_gid = $portfolios[0]['gid'];
            }
        }

        $dbg = [
            'workspace_fields' => 0,
            'projects' => 0,
            'cfs' => 0,
            'notes' => [],
        ];

        if ($workspace_gid !== '' && empty($portfolios)) {
            $dbg['notes'][] = 'No portfolios discovered for selected workspace.';
        }

        $fields_index = [];
        if ($workspace_gid !== '') {
            $workspace_index = afb_gf_collect_workspace_custom_fields($workspace_gid, $pat, $dbg);
            $fields_index = array_replace($fields_index, $workspace_index);

            if ($target_scope === 'portfolio' && $portfolio_gid !== '') {
                $portfolio_index = afb_gf_collect_portfolio_custom_fields($portfolio_gid, $pat, $dbg);
                $fields_index = array_replace($fields_index, $portfolio_index);
            }

            // Fallback: some PAT/workspace combinations return no workspace-level custom field library.
            // In that case, discover text fields via the account's default portfolio projects.
            if (empty($fields_index)) {
                $fallback_portfolio_gid = preg_replace('/\D+/', '', (string)($account['portfolio_gid'] ?? ''));
                if ($fallback_portfolio_gid !== '') {
                    $dbg['notes'][] = 'Workspace field library empty; falling back to default portfolio project fields.';
                    $fallback_index = afb_gf_collect_portfolio_custom_fields($fallback_portfolio_gid, $pat, $dbg);
                    $fields_index = array_replace($fields_index, $fallback_index);
                }
            }

            if (empty($fields_index) && !empty($portfolios[0]['gid'])) {
                $dbg['notes'][] = 'No fields from workspace/default portfolio; trying first available portfolio.';
                $fallback_index = afb_gf_collect_portfolio_custom_fields((string)$portfolios[0]['gid'], $pat, $dbg);
                $fields_index = array_replace($fields_index, $fallback_index);
            }
        }

        $fields = array_values($fields_index);
        usort($fields, static function ($a, $b) {
            return strcasecmp((string)($a['name'] ?? ''), (string)($b['name'] ?? ''));
        });
        $dbg['cfs'] = count($fields);

        $existing_default_raw = $map['workspaces'][$workspace_gid]['default'] ?? [];
        $existing_pf_raw = $map['workspaces'][$workspace_gid]['portfolios'][$portfolio_gid] ?? [];

        $existing_default = [
            'first_name' => (string)($existing_default_raw['first_name'] ?? $map['first_name'] ?? ''),
            'last_name' => (string)($existing_default_raw['last_name'] ?? $map['last_name'] ?? ''),
            'email' => (string)($existing_default_raw['work_email'] ?? $existing_default_raw['email'] ?? $map['work_email'] ?? $map['email'] ?? ''),
        ];

        $existing_pf = [
            'first_name' => (string)($existing_pf_raw['first_name'] ?? $existing_default['first_name'] ?? ''),
            'last_name' => (string)($existing_pf_raw['last_name'] ?? $existing_default['last_name'] ?? ''),
            'email' => (string)($existing_pf_raw['work_email'] ?? $existing_pf_raw['email'] ?? $existing_default['email'] ?? ''),
        ];

        $existing_identity = ($target_scope === 'portfolio') ? $existing_pf : $existing_default;

        if ($existing_identity['first_name'] === '') {
            $existing_identity['first_name'] = afb_gf_guess_identity_field_gid($fields, 'first_name');
        }
        if ($existing_identity['last_name'] === '') {
            $existing_identity['last_name'] = afb_gf_guess_identity_field_gid($fields, 'last_name');
        }
        if ($existing_identity['email'] === '') {
            $existing_identity['email'] = afb_gf_guess_identity_field_gid($fields, 'email');
        }

        $gateway = [
            'create' => sanitize_text_field((string)get_option('afb_client_gateway_create_field_gid', '1211304630299020')),
            'link' => sanitize_text_field((string)get_option('afb_client_gateway_link_field_gid', '1211304630299018')),
            'pin' => sanitize_text_field((string)get_option('afb_client_gateway_pin_field_gid', '1214258543781835')),
        ];

        return [
            'account' => [
                'id' => (int)$account['id'],
                'label' => (string)$account['label'],
                'portfolio_gid' => (string)$account['portfolio_gid'],
            ],
            'selected' => [
                'workspace_gid' => (string)$workspace_gid,
                'target' => $target_scope,
                'portfolio_gid' => (string)$portfolio_gid,
            ],
            'workspaces' => $workspaces,
            'portfolios' => $portfolios,
            'fields' => $fields,
            'existing_identity' => $existing_identity,
            'existing_gateway' => $gateway,
            'debug' => $dbg,
        ];
    }
}

if (!function_exists('afb_gf_save_mapping')) {
    function afb_gf_save_mapping(array $payload) {
        $pat_id = (int)($payload['pat_id'] ?? 0);
        $workspace_gid = preg_replace('/\D+/', '', (string)($payload['workspace_gid'] ?? ''));
        $target = ((string)($payload['target'] ?? 'workspace') === 'portfolio') ? 'portfolio' : 'workspace';
        $portfolio_gid = preg_replace('/\D+/', '', (string)($payload['portfolio_gid'] ?? ''));

        if ($pat_id <= 0) {
            return ['ok' => false, 'message' => 'Missing PAT account id.'];
        }

        if ($workspace_gid === '') {
            return ['ok' => false, 'message' => 'Select a workspace before saving.'];
        }

        if ($target === 'portfolio' && $portfolio_gid === '') {
            return ['ok' => false, 'message' => 'Select a portfolio before saving portfolio mapping.'];
        }

        $first = preg_replace('/\D+/', '', (string)($payload['first_name_gid'] ?? ''));
        $last  = preg_replace('/\D+/', '', (string)($payload['last_name_gid'] ?? ''));
        $email = preg_replace('/\D+/', '', (string)($payload['email_gid'] ?? ''));

        $gateway_create = preg_replace('/\D+/', '', (string)($payload['gateway_create_gid'] ?? ''));
        $gateway_link = preg_replace('/\D+/', '', (string)($payload['gateway_link_gid'] ?? ''));
        $gateway_pin = preg_replace('/\D+/', '', (string)($payload['gateway_pin_gid'] ?? ''));

        if ($gateway_create !== '') update_option('afb_client_gateway_create_field_gid', $gateway_create);
        if ($gateway_link !== '') update_option('afb_client_gateway_link_field_gid', $gateway_link);
        if ($gateway_pin !== '') update_option('afb_client_gateway_pin_field_gid', $gateway_pin);

        $map = afb_gf_map_read();
        if (!isset($map['workspaces'][$workspace_gid])) $map['workspaces'][$workspace_gid] = [];
        $map['workspaces'][$workspace_gid]['source_meta']['pat_id'] = $pat_id;

        $map['first_name'] = $first;
        $map['last_name'] = $last;
        $map['work_email'] = $email;
        $map['email'] = $email;

        if ($target === 'portfolio') {
            if (!isset($map['workspaces'][$workspace_gid]['portfolios'])) $map['workspaces'][$workspace_gid]['portfolios'] = [];
            $map['workspaces'][$workspace_gid]['portfolios'][$portfolio_gid] = [
                'first_name' => $first,
                'last_name' => $last,
                'work_email' => $email,
                'email' => $email,
                'projects' => [],
                'updated' => time(),
            ];
        } else {
            $map['workspaces'][$workspace_gid]['default'] = [
                'first_name' => $first,
                'last_name' => $last,
                'work_email' => $email,
                'email' => $email,
                'updated' => time(),
            ];
        }

        if (!afb_gf_map_write($map)) {
            return ['ok' => false, 'message' => 'Unable to write global field map JSON.'];
        }

        return ['ok' => true, 'message' => 'Mapping saved.'];
    }
}
