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

class Novajyin_Capture
{
    public function hooks()
    {
        add_action('wpcf7_before_send_mail', array($this, 'capture_submission'), 10, 1);
    }

    public function capture_submission($contact_form)
    {
        if (!class_exists('WPCF7_Submission')) {
            return;
        }

        $submission = WPCF7_Submission::get_instance();
        if (!$submission) {
            return;
        }

        $form_id = method_exists($contact_form, 'id') ? (int) $contact_form->id() : 0;
        $form_name = method_exists($contact_form, 'title') ? $contact_form->title() : '';

        $settings = Novajyin_Repository::get_settings();
        $managed_forms = array_filter(array_map('absint', (array) $settings['managed_forms']));
        if (!empty($managed_forms) && !in_array($form_id, $managed_forms, true)) {
            return;
        }

        $posted_data = $submission->get_posted_data();
        $raw_data = self::sanitize_posted_data($posted_data);
        $mapping = self::mapping_for_form($form_id, $settings);

        $name = self::mapped_value($raw_data, $mapping, 'name');
        $email = sanitize_email(self::mapped_value($raw_data, $mapping, 'email'));
        $tel = self::mapped_value($raw_data, $mapping, 'tel');
        $subject = self::mapped_value($raw_data, $mapping, 'subject');
        $inquiry_type = self::mapped_value($raw_data, $mapping, 'inquiry_type');
        $shop_name = self::mapped_value($raw_data, $mapping, 'shop_name');
        $message = self::mapped_value($raw_data, $mapping, 'message');

        $context = array(
            'form_id' => $form_id,
            'form_name' => $form_name,
            'name' => $name,
            'email' => $email,
            'tel' => $tel,
            'subject' => $subject,
            'inquiry_type' => $inquiry_type,
            'shop_name' => $shop_name,
            'message' => $message,
            'raw_data' => $raw_data,
        );

        $rule_result = Novajyin_Rules_Engine::apply($context);
        $uploaded_files = method_exists($submission, 'uploaded_files') ? $submission->uploaded_files() : array();

        $data = array(
            'form_id' => $form_id,
            'form_name' => sanitize_text_field($form_name),
            'submitted_at' => current_time('mysql'),
            'name' => sanitize_text_field($name),
            'email' => $email,
            'tel' => sanitize_text_field($tel),
            'subject' => sanitize_text_field($subject),
            'inquiry_type' => sanitize_text_field($inquiry_type),
            'shop_name' => sanitize_text_field($shop_name),
            'message' => sanitize_textarea_field($message),
            'raw_data_json' => wp_json_encode($raw_data, JSON_UNESCAPED_UNICODE),
            'attachments_json' => wp_json_encode(self::attachment_metadata($uploaded_files), JSON_UNESCAPED_UNICODE),
        );

        $data = array_merge($data, $rule_result['updates']);
        $inquiry_id = Novajyin_Repository::insert_inquiry($data);
        if (!$inquiry_id) {
            return;
        }

        Novajyin_Repository::add_history($inquiry_id, 'created', '問い合わせを受け付けました。', 0);

        if (!empty($rule_result['matched_rules'])) {
            Novajyin_Repository::add_history(
                $inquiry_id,
                'auto_rule',
                '自動振り分けルールが適用されました：' . implode('、', array_map('sanitize_text_field', $rule_result['matched_rules'])),
                0
            );
        }

        if (!empty($settings['save_attachments'])) {
            $saved_attachments = self::save_attachments($inquiry_id, $uploaded_files);
            if (!empty($saved_attachments)) {
                Novajyin_Repository::update_inquiry(
                    $inquiry_id,
                    array('attachments_json' => wp_json_encode($saved_attachments, JSON_UNESCAPED_UNICODE)),
                    0,
                    false
                );
            }
        }

        self::send_new_inquiry_notification($inquiry_id, $rule_result['notifications']);
    }

    private static function mapping_for_form($form_id, $settings)
    {
        $mapping = array();
        if (!empty($settings['field_mapping']) && is_array($settings['field_mapping'])) {
            if (!empty($settings['field_mapping'][$form_id]) && is_array($settings['field_mapping'][$form_id])) {
                $mapping = $settings['field_mapping'][$form_id];
            } elseif (!empty($settings['field_mapping']['default']) && is_array($settings['field_mapping']['default'])) {
                $mapping = $settings['field_mapping']['default'];
            }
        }

        return $mapping;
    }

    private static function mapped_value($raw_data, $mapping, $standard_key)
    {
        $field_key = isset($mapping[$standard_key]) ? sanitize_text_field($mapping[$standard_key]) : '';
        if ($field_key === '' || !isset($raw_data[$field_key])) {
            return '';
        }

        $value = $raw_data[$field_key];
        if (is_array($value)) {
            return implode(', ', array_map('strval', $value));
        }

        return (string) $value;
    }

    private static function sanitize_posted_data($value)
    {
        if (is_array($value)) {
            $clean = array();
            foreach ($value as $key => $child) {
                $clean[sanitize_text_field((string) $key)] = self::sanitize_posted_data($child);
            }
            return $clean;
        }

        if (is_scalar($value)) {
            return sanitize_textarea_field(wp_unslash((string) $value));
        }

        return '';
    }

    private static function attachment_metadata($uploaded_files)
    {
        $metadata = array();

        foreach ((array) $uploaded_files as $field => $files) {
            foreach (self::normalize_files($files) as $file) {
                $metadata[] = array(
                    'field' => sanitize_key($field),
                    'name' => sanitize_file_name(basename($file)),
                    'saved' => false,
                );
            }
        }

        return $metadata;
    }

    private static function save_attachments($inquiry_id, $uploaded_files)
    {
        $saved = array();
        $upload_dir = wp_upload_dir();
        if (!empty($upload_dir['error'])) {
            return $saved;
        }

        $base_dir = trailingslashit($upload_dir['basedir']) . 'nova-jyo-inquiries/' . absint($inquiry_id);
        $base_url = trailingslashit($upload_dir['baseurl']) . 'nova-jyo-inquiries/' . absint($inquiry_id);
        wp_mkdir_p($base_dir);
        self::protect_attachment_directory(trailingslashit($upload_dir['basedir']) . 'nova-jyo-inquiries');

        foreach ((array) $uploaded_files as $field => $files) {
            foreach (self::normalize_files($files) as $file) {
                if (!is_readable($file)) {
                    continue;
                }

                $filename = wp_unique_filename($base_dir, sanitize_file_name(basename($file)));
                $destination = trailingslashit($base_dir) . $filename;

                if (!copy($file, $destination)) {
                    continue;
                }

                $type = wp_check_filetype($filename);
                $saved[] = array(
                    'field' => sanitize_key($field),
                    'name' => $filename,
                    'path' => $destination,
                    'url' => trailingslashit($base_url) . rawurlencode($filename),
                    'mime' => $type['type'] ?? '',
                    'saved' => true,
                );
            }
        }

        return $saved;
    }

    private static function protect_attachment_directory($directory)
    {
        if (!is_dir($directory) || !is_writable($directory)) {
            return;
        }

        $htaccess = trailingslashit($directory) . '.htaccess';
        if (!file_exists($htaccess)) {
            file_put_contents($htaccess, "Deny from all\n");
        }

        $web_config = trailingslashit($directory) . 'web.config';
        if (!file_exists($web_config)) {
            file_put_contents($web_config, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration><system.webServer><security><authorization><remove users=\"*\" roles=\"\" verbs=\"\" /><add accessType=\"Deny\" users=\"*\" /></authorization></security></system.webServer></configuration>\n");
        }
    }

    private static function normalize_files($files)
    {
        if (is_string($files)) {
            return array($files);
        }

        if (is_array($files)) {
            $normalized = array();
            foreach ($files as $file) {
                if (is_string($file)) {
                    $normalized[] = $file;
                }
            }
            return $normalized;
        }

        return array();
    }

    private static function send_new_inquiry_notification($inquiry_id, $extra_recipients = array())
    {
        $settings = Novajyin_Repository::get_settings();
        if (empty($settings['notify_on_new'])) {
            return;
        }

        $inquiry = Novajyin_Repository::get_inquiry($inquiry_id);
        if (!$inquiry) {
            return;
        }

        $recipients = array();
        if (!empty($settings['notify_admin'])) {
            $recipients[] = get_option('admin_email');
        }

        if (!empty($settings['notify_assignee']) && !empty($inquiry->assignee_user_id)) {
            $user = get_user_by('id', (int) $inquiry->assignee_user_id);
            if ($user && is_email($user->user_email)) {
                $recipients[] = $user->user_email;
            }
        }

        if (!empty($settings['notify_group']) && !empty($inquiry->assignee_group_id)) {
            $group = Novajyin_Repository::get_group((int) $inquiry->assignee_group_id);
            if ($group && is_email($group->notification_email)) {
                $recipients[] = $group->notification_email;
            }
        }

        $recipients = array_merge($recipients, Novajyin_Rules_Engine::parse_emails($settings['notify_emails']), (array) $extra_recipients);
        $recipients = array_values(array_unique(array_filter(array_map('sanitize_email', $recipients))));
        if (empty($recipients)) {
            return;
        }

        $subject = sprintf('【新規問い合わせ】%s - %s', $inquiry->form_name, $inquiry->name ? $inquiry->name : '氏名未設定');
        $admin_url = admin_url('admin.php?page=novajyin_inquiries&action=view&id=' . absint($inquiry_id));
        $body = self::notification_body($inquiry, $admin_url);

        $sent = wp_mail($recipients, $subject, $body);
        if ($sent) {
            Novajyin_Repository::add_history($inquiry_id, 'notification', '新規問い合わせ通知を送信しました：' . implode(', ', $recipients), 0);
        }
    }

    private static function notification_body($inquiry, $admin_url)
    {
        $lines = array(
            '新しい問い合わせが届きました。',
            '',
            '受付日時：' . mysql2date('Y/m/d H:i', $inquiry->submitted_at),
            'フォーム名：' . $inquiry->form_name,
            '氏名：' . $inquiry->name,
            'メールアドレス：' . $inquiry->email,
            '電話番号：' . $inquiry->tel,
            '問い合わせ種別：' . $inquiry->inquiry_type,
            '店舗名：' . $inquiry->shop_name,
            'ステータス：' . $inquiry->status_name,
            '担当者：' . $inquiry->assignee_name,
            '担当グループ：' . $inquiry->group_name,
            '優先度：' . $inquiry->priority_name,
            '対応期限：' . ($inquiry->due_date ? mysql2date('Y/m/d H:i', $inquiry->due_date) : '未設定'),
            '',
            '管理画面URL：',
            $admin_url,
        );

        return implode("\n", $lines);
    }
}





