<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\InvoiceBillingRuleStoreRequest;
use App\Http\Requests\Admin\InvoiceBillingRuleUpdateRequest;
use App\Models\Invoice;
use App\Models\InvoiceBilling;
use App\Models\InvoiceBillingRule;
use App\Models\Setting;
use App\Services\Billing\InvoiceBillingRuleOverlapDetector;
use App\Services\Billing\InvoicingRuleEvaluator;
use App\Traits\LogsAdminActivity;
use Illuminate\Http\Request;

class InvoiceBillingRuleController extends Controller
{
    use LogsAdminActivity;

    private const OPERATIONAL_SETTING_KEYS = [
        'billing_enable_automatic',
        'billing_default_module',
        'billing_auto_process_delay',
        'billing_retry_failed_jobs',
        'billing_max_retry_attempts',
        'billing_notify_on_failure',
        'billing_failure_notification_email',
    ];

    public function __construct(
        private InvoicingRuleEvaluator $evaluator,
        private InvoiceBillingRuleOverlapDetector $overlapDetector,
    ) {}

    public function index()
    {
        $rules = InvoiceBillingRule::with('billingModule')
            ->byPriority()
            ->paginate(50);

        $settings = [
            'billing_enable_automatic' => (bool) Setting::getValue('billing_enable_automatic', false),
            'billing_default_module' => Setting::getValue('billing_default_module', 'gib'),
            'billing_auto_process_delay' => (int) Setting::getValue('billing_auto_process_delay', 5),
            'billing_retry_failed_jobs' => (bool) Setting::getValue('billing_retry_failed_jobs', true),
            'billing_max_retry_attempts' => (int) Setting::getValue('billing_max_retry_attempts', 3),
            'billing_notify_on_failure' => (bool) Setting::getValue('billing_notify_on_failure', true),
            'billing_failure_notification_email' => Setting::getValue('billing_failure_notification_email', ''),
        ];
        $modules = InvoiceBilling::where('is_active', true)->orderBy('display_name')->get();

        return view('admin.billing-rules.index', compact('rules', 'settings', 'modules'));
    }

    public function saveSettings(Request $request)
    {
        $data = $request->validate([
            'billing_enable_automatic' => 'nullable|boolean',
            'billing_default_module' => 'nullable|string|max:50',
            'billing_auto_process_delay' => 'nullable|integer|min:1|max:60',
            'billing_retry_failed_jobs' => 'nullable|boolean',
            'billing_max_retry_attempts' => 'nullable|integer|min:1|max:10',
            'billing_notify_on_failure' => 'nullable|boolean',
            'billing_failure_notification_email' => 'nullable|email|max:255',
        ]);

        Setting::setValue('billing_enable_automatic', (bool) ($data['billing_enable_automatic'] ?? false));
        Setting::setValue('billing_default_module', $data['billing_default_module'] ?? 'gib');
        Setting::setValue('billing_auto_process_delay', (int) ($data['billing_auto_process_delay'] ?? 5));
        Setting::setValue('billing_retry_failed_jobs', (bool) ($data['billing_retry_failed_jobs'] ?? false));
        Setting::setValue('billing_max_retry_attempts', (int) ($data['billing_max_retry_attempts'] ?? 3));
        Setting::setValue('billing_notify_on_failure', (bool) ($data['billing_notify_on_failure'] ?? false));
        Setting::setValue('billing_failure_notification_email', $data['billing_failure_notification_email'] ?? '');

        \App\Models\Log::create([
            'type' => \App\Models\Log::TYPE_ADMIN,
            'admin_id' => auth('admin')->id(),
            'description' => 'Updated E-Billing operational settings via /admin/billing/rules',
        ]);

        return redirect()->route('admin.billing.rules.index')
            ->with('success', __('admin/billing-rules.settings_saved'));
    }

    public function create()
    {
        $modules = InvoiceBilling::where('is_active', true)->orderBy('display_name')->get();
        $fields = InvoicingRuleEvaluator::ALLOWED_FIELDS;
        $operators = InvoicingRuleEvaluator::ALLOWED_OPERATORS;

        return view('admin.billing-rules.create', compact('modules', 'fields', 'operators'));
    }

    public function store(InvoiceBillingRuleStoreRequest $request)
    {
        $rule = InvoiceBillingRule::create($request->validated());

        $this->logCreated(
            model: $rule,
            description: "Created billing rule '{$rule->name}'"
        );

        return redirect()
            ->route('admin.billing.rules.index')
            ->with('success', __('admin/billing-rules.created'));
    }

    public function edit(InvoiceBillingRule $rule)
    {
        $modules = InvoiceBilling::where('is_active', true)->orderBy('display_name')->get();
        $fields = InvoicingRuleEvaluator::ALLOWED_FIELDS;
        $operators = InvoicingRuleEvaluator::ALLOWED_OPERATORS;

        return view('admin.billing-rules.edit', compact('rule', 'modules', 'fields', 'operators'));
    }

    public function update(InvoiceBillingRuleUpdateRequest $request, InvoiceBillingRule $rule)
    {
        $rule->update($request->validated());

        $this->logUpdated(
            model: $rule,
            description: "Updated billing rule '{$rule->name}'"
        );

        return redirect()
            ->route('admin.billing.rules.index')
            ->with('success', __('admin/billing-rules.updated'));
    }

    public function destroy(InvoiceBillingRule $rule)
    {
        $name = $rule->name;
        $rule->delete();

        $this->logDeleted(
            model: $rule,
            description: "Deleted billing rule '{$name}'"
        );

        return redirect()
            ->route('admin.billing.rules.index')
            ->with('success', __('admin/billing-rules.deleted'));
    }

    public function reorder(Request $request)
    {
        $request->validate([
            'order' => 'required|array',
            'order.*' => 'integer|exists:invoice_billing_rules,id',
        ]);

        foreach ($request->input('order') as $priority => $id) {
            InvoiceBillingRule::where('id', $id)->update(['priority' => $priority]);
        }

        return response()->json(['ok' => true]);
    }

    public function test(InvoiceBillingRule $rule, Request $request)
    {
        $request->validate(['invoice_id' => 'required|integer|exists:invoices,id']);

        $invoice = Invoice::with(['client.country', 'currency', 'items.product'])
            ->findOrFail($request->input('invoice_id'));

        $context = $this->evaluator->buildContext($invoice);
        $matched = $this->evaluator->matchesTree($rule->conditions, $context);

        return response()->json([
            'ok' => true,
            'matched' => $matched,
            'context' => $context,
            'rule_action' => $rule->action,
            'effective_dispatch' => $matched && $rule->action === InvoiceBillingRule::ACTION_DISPATCH,
        ]);
    }

    /**
     * Kural çakışma tespiti — API endpoint (AJAX / Bearer).
     *
     * Yönetici kural oluştururken / düzenlerken anlık çakışma kontrolü için
     * kullanılır. Sonuç yalnızca uyarı niteliğindedir; kaydetmeyi engellemez.
     *
     * POST /api/admin/billing-rules/check-overlap
     * Body: { events: [...], conditions: {...}, ignore_rule_id?: int }
     * Response: { overlaps: [{rule_id, rule_name, module_name, reason}, ...] }
     */
    public function checkOverlap(Request $request)
    {
        $data = $request->validate([
            'events'         => 'required|array|min:1',
            'events.*'       => 'string|in:' . implode(',', InvoiceBillingRule::ALL_EVENTS),
            'conditions'     => 'required|array',
            'ignore_rule_id' => 'nullable|integer|exists:invoice_billing_rules,id',
        ]);

        // conditions JSON string olarak gelebilir (JS builder'dan)
        $conditions = $data['conditions'];
        if (is_string($conditions)) {
            $conditions = json_decode($conditions, true) ?? [];
        }

        $overlaps = $this->overlapDetector->detect(
            $data['events'],
            $conditions,
            $data['ignore_rule_id'] ?? null,
        );

        return response()->json(['overlaps' => $overlaps]);
    }

    public function fields()
    {
        return response()->json([
            'fields'    => InvoicingRuleEvaluator::ALLOWED_FIELDS,
            'operators' => InvoicingRuleEvaluator::ALLOWED_OPERATORS,
        ]);
    }
}
