<?php

namespace App\Http\Controllers;

use App\Http\Requests\DeveloperOverrideRequest;
use App\Models\Customer;
use App\Models\DeveloperOverrideLog;
use App\Models\Order;
use App\Models\Payment;
use App\Models\PaymentAccount;
use App\Models\Product;
use App\Models\User;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;

class DeveloperOverrideController extends Controller
{
    public function __construct()
    {
        $this->middleware(['auth']);
    }

    protected function ensureDeveloper(Request $request): void
    {
        abort_unless($request->user() && $request->user()->isDeveloper(), 403, 'Hanya developer yang dapat mengakses fitur ini.');
    }

    protected function confirmPassword(Request $request): void
    {
        $password = (string) $request->input('developer_password', '');
        abort_if(
            !Hash::check($password, (string) $request->user()->password),
            422,
            'Password developer tidak valid.'
        );
    }

    protected function logAction(Request $request, string $action, string $targetType, int|string|null $targetId, array $before = [], array $after = [], array $meta = []): void
    {
        DeveloperOverrideLog::create([
            'user_id' => $request->user()->id,
            'action' => $action,
            'target_type' => $targetType,
            'target_id' => (string) ($targetId ?? ''),
            'reason' => (string) $request->input('reason', ''),
            'before_data' => $before,
            'after_data' => $after,
            'meta' => $meta,
            'ip_address' => $request->ip(),
            'user_agent' => substr((string) $request->userAgent(), 0, 1000),
        ]);
    }

    public function search(Request $request)
    {
        $this->ensureDeveloper($request);

        $type = (string) $request->input('type', 'orders');
        $keyword = trim((string) $request->input('keyword', ''));
        $results = collect();

        if ($keyword === '') {
            return response()->json([
                'success' => true,
                'type' => $type,
                'results' => [],
            ]);
        }

        if ($type === 'orders') {
            $results = Order::query()
                ->with(['customer', 'payments'])
                ->where(function ($q) use ($keyword) {
                    $q->where('invoice_number', 'like', "%{$keyword}%")
                      ->orWhere('customer_name', 'like', "%{$keyword}%");
                })
                ->latest()
                ->limit(10)
                ->get()
                ->map(function (Order $order) {
                    return [
                        'id' => $order->id,
                        'label' => $order->invoice_number . ' • ' . $order->customer_name,
                        'sub' => 'Status bayar: ' . $order->payment_status . ' | Produksi: ' . $order->production_status,
                    ];
                });
        } elseif ($type === 'customers') {
            $results = Customer::query()
                ->where(function ($q) use ($keyword) {
                    $q->where('name', 'like', "%{$keyword}%")
                      ->orWhere('phone', 'like', "%{$keyword}%")
                      ->orWhere('email', 'like', "%{$keyword}%");
                })
                ->latest()
                ->limit(10)
                ->get()
                ->map(fn (Customer $customer) => [
                    'id' => $customer->id,
                    'label' => $customer->name,
                    'sub' => trim(($customer->phone ?? '-') . ' | ' . ($customer->email ?? '-')),
                ]);
        } elseif ($type === 'users') {
            $results = User::query()
                ->where(function ($q) use ($keyword) {
                    $q->where('name', 'like', "%{$keyword}%")
                      ->orWhere('email', 'like', "%{$keyword}%");
                })
                ->orderBy('name')
                ->limit(10)
                ->get()
                ->map(fn (User $user) => [
                    'id' => $user->id,
                    'label' => $user->name,
                    'sub' => $user->email,
                ]);
        }

        return response()->json([
            'success' => true,
            'type' => $type,
            'results' => $results->values(),
        ]);
    }

    public function updateOrder(DeveloperOverrideRequest $request, Order $order): RedirectResponse
    {
        $this->ensureDeveloper($request);
        $this->confirmPassword($request);

        $before = $order->only([
            'customer_id', 'customer_name', 'customer_phone', 'payment_status',
            'production_status', 'pickup_status', 'is_credit', 'notes',
            'paid_at', 'cashier_id', 'operator_id', 'designer_id'
        ]);

        $validated = $request->validated();

        DB::transaction(function () use ($validated, $order, $request) {
            if (!empty($validated['customer_id'])) {
                $customer = Customer::find($validated['customer_id']);
                if ($customer) {
                    $order->customer_id = $customer->id;
                    $order->customer_name = $customer->name;
                    $order->customer_phone = $customer->phone;
                }
            }

            foreach ([
                'payment_status', 'production_status', 'pickup_status',
                'notes', 'cashier_id', 'operator_id', 'designer_id'
            ] as $field) {
                if (array_key_exists($field, $validated) && $validated[$field] !== null && $validated[$field] !== '') {
                    $order->{$field} = $validated[$field];
                }
            }

            if (array_key_exists('is_credit', $validated)) {
                $order->is_credit = (bool) $validated['is_credit'];
            }

            if (($validated['payment_status'] ?? null) === Order::PAYMENT_PAID && !$order->paid_at) {
                $order->paid_at = now();
            }

            if (($validated['payment_status'] ?? null) !== Order::PAYMENT_PAID) {
                $order->paid_at = null;
            }

            $order->save();
        });

        $after = $order->fresh()->only([
            'customer_id', 'customer_name', 'customer_phone', 'payment_status',
            'production_status', 'pickup_status', 'is_credit', 'notes',
            'paid_at', 'cashier_id', 'operator_id', 'designer_id'
        ]);

        $this->logAction($request, 'override_update_order', 'order', $order->id, $before, $after);

        return back()->with('success', 'Override order berhasil disimpan.');
    }

    public function updatePayment(DeveloperOverrideRequest $request, Payment $payment): RedirectResponse
    {
        $this->ensureDeveloper($request);
        $this->confirmPassword($request);

        $before = $payment->only([
            'amount', 'payment_method', 'payment_account_id', 'notes', 'cashier_id'
        ]);

        $validated = $request->validated();

        DB::transaction(function () use ($validated, $payment) {
            foreach (['amount', 'payment_method', 'payment_account_id', 'notes', 'cashier_id'] as $field) {
                if (array_key_exists($field, $validated)) {
                    $payment->{$field} = $validated[$field];
                }
            }
            $payment->save();

            if ($payment->order) {
                $payment->order->paid_amount = $payment->order->payments()->sum('amount');
                $payment->order->change_amount = max((float) $payment->order->paid_amount - (float) $payment->order->total_price, 0);
                $payment->order->payment_status = $payment->order->paid_amount >= $payment->order->total_price
                    ? Order::PAYMENT_PAID
                    : ($payment->order->paid_amount > 0 ? Order::PAYMENT_PARTIAL : Order::PAYMENT_UNPAID);
                $payment->order->paid_at = $payment->order->payment_status === Order::PAYMENT_PAID ? ($payment->order->paid_at ?: now()) : null;
                $payment->order->save();
            }
        });

        $after = $payment->fresh()->only([
            'amount', 'payment_method', 'payment_account_id', 'notes', 'cashier_id'
        ]);

        $this->logAction($request, 'override_update_payment', 'payment', $payment->id, $before, $after);

        return back()->with('success', 'Override pembayaran berhasil disimpan.');
    }

    public function archiveCustomer(DeveloperOverrideRequest $request, Customer $customer): RedirectResponse
    {
        $this->ensureDeveloper($request);
        $this->confirmPassword($request);

        $before = $customer->only(['id', 'name', 'phone', 'email', 'address', 'member_type']);

        DB::transaction(function () use ($customer) {
            $customer->update([
                'name' => '[ARCHIVED] ' . $customer->name,
                'email' => null,
                'phone' => null,
                'address' => $customer->address,
            ]);
        });

        $after = $customer->fresh()->only(['id', 'name', 'phone', 'email', 'address', 'member_type']);

        $this->logAction($request, 'override_archive_customer', 'customer', $customer->id, $before, $after);

        return back()->with('success', 'Customer berhasil di-archive secara aman.');
    }

    public function deactivateUser(DeveloperOverrideRequest $request, User $user): RedirectResponse
    {
        $this->ensureDeveloper($request);
        $this->confirmPassword($request);

        abort_if($user->id === $request->user()->id, 422, 'Tidak bisa menonaktifkan akun yang sedang dipakai.');

        $before = $user->only(['id', 'name', 'email', 'is_active']);

        $user->update(['is_active' => false]);

        $after = $user->fresh()->only(['id', 'name', 'email', 'is_active']);

        $this->logAction($request, 'override_deactivate_user', 'user', $user->id, $before, $after);

        return back()->with('success', 'User berhasil dinonaktifkan.');
    }

    public function archiveProduct(DeveloperOverrideRequest $request, Product $product): RedirectResponse
    {
        $this->ensureDeveloper($request);
        $this->confirmPassword($request);

        $before = $product->only(['id', 'name', 'code', 'is_active', 'description']);

        $product->update([
            'is_active' => false,
            'description' => trim((string) $product->description . "\n[ARCHIVED BY DEVELOPER OVERRIDE]"),
        ]);

        $after = $product->fresh()->only(['id', 'name', 'code', 'is_active', 'description']);

        $this->logAction($request, 'override_archive_product', 'product', $product->id, $before, $after);

        return back()->with('success', 'Produk berhasil diarsipkan/nonaktifkan.');
    }

    public function deactivatePaymentAccount(DeveloperOverrideRequest $request, PaymentAccount $paymentAccount): RedirectResponse
    {
        $this->ensureDeveloper($request);
        $this->confirmPassword($request);

        $before = $paymentAccount->only(['id', 'name', 'provider', 'is_active']);

        $paymentAccount->update(['is_active' => false]);

        $after = $paymentAccount->fresh()->only(['id', 'name', 'provider', 'is_active']);

        $this->logAction($request, 'override_deactivate_payment_account', 'payment_account', $paymentAccount->id, $before, $after);

        return back()->with('success', 'Rekening pembayaran berhasil dinonaktifkan.');
    }
}
